diff options
46 files changed, 1702 insertions, 1318 deletions
diff --git a/.ci/build.bat b/.ci/build.bat index e7c42be7fa..c2f560fb7c 100644 --- a/.ci/build.bat +++ b/.ci/build.bat @@ -17,7 +17,7 @@ set PATH=C:\Program Files (x86)\CMake\bin\cpack.exe;%PATH% :: Build third-party dependencies C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm -Su" || goto :error -C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-python2 mingw-w64-%ARCH%-diffutils" || goto :error +C:\msys64\usr\bin\bash -lc "pacman --verbose --noconfirm --needed -S mingw-w64-%ARCH%-cmake mingw-w64-%ARCH%-perl mingw-w64-%ARCH%-python2 mingw-w64-%ARCH%-diffutils gperf" || goto :error mkdir .deps cd .deps @@ -28,7 +28,7 @@ cd .. :: Build Neovim mkdir build cd build -cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUSTED_OUTPUT_TYPE=gtest .. || goto :error +cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUSTED_OUTPUT_TYPE=gtest -DGPERF_PRG="C:\msys64\usr\bin\gperf.exe" .. || goto :error mingw32-make VERBOSE=1 || goto :error bin\nvim --version || goto :error diff --git a/CMakeLists.txt b/CMakeLists.txt index 01015fe270..95601d441a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -407,6 +407,8 @@ endif() find_program(LUACHECK_PRG luacheck) +find_program(GPERF_PRG gperf) + include(InstallHelpers) file(GLOB MANPAGES diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt index 0dd8b07b7a..cced1a8d04 100644 --- a/runtime/CMakeLists.txt +++ b/runtime/CMakeLists.txt @@ -3,6 +3,7 @@ set(GENERATED_RUNTIME_DIR ${PROJECT_BINARY_DIR}/runtime) set(GENERATED_SYN_VIM ${GENERATED_RUNTIME_DIR}/syntax/vim/generated.vim) set(GENERATED_HELP_TAGS ${GENERATED_RUNTIME_DIR}/doc/tags) set(GENERATED_PACKAGE_DIR ${GENERATED_RUNTIME_DIR}/pack/dist/opt) +set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack) file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}) file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax) @@ -10,13 +11,14 @@ file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax/vim) add_custom_command(OUTPUT ${GENERATED_SYN_VIM} COMMAND ${LUA_PRG} ${SYN_VIM_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_SYN_VIM} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_SYN_VIM} ${FUNCS_DATA} DEPENDS ${SYN_VIM_GENERATOR} ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua ${PROJECT_SOURCE_DIR}/src/nvim/options.lua ${PROJECT_SOURCE_DIR}/src/nvim/eval.c + ${FUNCS_DATA} ) if(POLICY CMP0054) diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index bdeca367b1..c3d7fdb35b 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -14,13 +14,13 @@ C API for Nvim *API* *api* ============================================================================== 1. Introduction *api-intro* -Nvim exposes a public API for external code to interact with the Nvim core. In -the present version of Nvim the API is primarily used by external processes to -interact with Nvim using the msgpack-rpc protocol, see |msgpack-rpc|. The API -will also be used from vimscript to access new Nvim core features, but this is -not implemented yet. Later on, Nvim might be embeddable in C applications as -libnvim, and the application will then control the embedded instance by -calling the C API directly. +Nvim exposes a public API for external code to interact with the Nvim core. +The API is used by external processes to interact with Nvim using the +msgpack-rpc protocol, see |msgpack-rpc|. The API is used from vimscript to +access some new Nvim core features. See |eval-api| for how api functions are +called from vimscript. Later on, Nvim might be embeddable in C applications as +libnvim, and the application will then control the embedded instance by calling +the C API directly. ============================================================================== 2. API Types *api-types* @@ -73,10 +73,10 @@ Another use case are plugins that show output in an append-only buffer, and want to add highlights to the outputs. Highlight data cannot be preserved on writing and loading a buffer to file, nor in undo/redo cycles. -Highlights are registered using the |buffer_add_highlight| function, see the +Highlights are registered using the |nvim_buf_add_highlight| function, see the generated API documentation for details. If an external highlighter plugin is adding a large number of highlights in a batch, performance can be improved by -calling |buffer_add_highlight| as an asynchronous notification, after first +calling |nvim_buf_add_highlight| as an asynchronous notification, after first (synchronously) reqesting a source id. Here is an example using wrapper functions in the python client: > @@ -91,10 +91,19 @@ functions in the python client: buf.clear_highlight(src) < If the highlights don't need to be deleted or updated, just pass -1 as -src_id (this is the default in python). |buffer_clear_highlight| can be used -to clear highligts from a specific source, in a specific line range or the -entire buffer by passing in the line range 0, -1 (the later is the default +src_id (this is the default in python). |nvim_buf_clear_highlight| can be used +to clear highlights from a specific source, in a specific line range or the +entire buffer by passing in the line range 0, -1 (the latter is the default in python as used above). +An example of calling the api from vimscript: > + + call nvim_buf_set_lines(0, 0, 0, v:true, ["test text"]) + let src = nvim_buf_add_highlight(0, 0, "String", 1, 0, 4) + call nvim_buf_add_highlight(0, src, "Identifier", 0, 5, -1) + + " later + call nvim_buf_clear_highlight(0, src, 0, -1) +> ============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 03d8f84aa6..92f9a0f656 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -2009,6 +2009,7 @@ msgpackdump({list}) List dump a list of objects to msgpack msgpackparse({list}) List parse msgpack to a list of objects nextnonblank({lnum}) Number line nr of non-blank line >= {lnum} nr2char({expr}[, {utf8}]) String single char with ASCII/UTF8 value {expr} +nvim_...({args}...) any call nvim |api| functions or({expr}, {expr}) Number bitwise OR pathshorten({expr}) String shorten directory names in a path pow({x}, {y}) Float {x} to the power of {y} @@ -2208,11 +2209,9 @@ and({expr}, {expr}) *and()* Example: > :let flag = and(bits, 0x80) - api_info() *api_info()* Returns Dictionary of |api-metadata|. - append({lnum}, {expr}) *append()* When {expr} is a |List|: Append each item of the |List| as a text line below line {lnum} in the current buffer. @@ -5172,6 +5171,17 @@ nr2char({expr}[, {utf8}]) *nr2char()* characters. nr2char(0) is a real NUL and terminates the string, thus results in an empty string. +nvim_...({...}) *nvim_...()* *eval-api* + Call nvim |api| functions. The type checking of arguments will + be stricter than for most other builtins. For instance, + if Integer is expected, a |Number| must be passed in, a + |String| will not be autoconverted. + Buffer numbers, as returned by |bufnr()| could be used as + first argument to nvim_buf_... functions. All functions + expecting an object (buffer, window or tabpage) can + also take the numerical value 0 to indicate the current + (focused) object. + or({expr}, {expr}) *or()* Bitwise OR on the two arguments. The arguments are converted to a number. A List, Dict or Float argument causes an error. diff --git a/runtime/doc/msgpack_rpc.txt b/runtime/doc/msgpack_rpc.txt index 30f68ca942..59e9e44f8f 100644 --- a/runtime/doc/msgpack_rpc.txt +++ b/runtime/doc/msgpack_rpc.txt @@ -47,7 +47,7 @@ instance. There are three ways to obtain API metadata: - 1. Connect to a running Nvim instance and call `vim_get_api_info` via + 1. Connect to a running Nvim instance and call `nvim_get_api_info` via msgpack-rpc. This is best for clients written in dynamic languages which can define functions at runtime. @@ -105,7 +105,7 @@ Nvim instance: require 'msgpack/rpc/transport/unix' nvim = MessagePack::RPC::Client.new(MessagePack::RPC::UNIXTransport.new, ENV['NVIM_LISTEN_ADDRESS']) - result = nvim.call(:vim_command, 'echo "hello world!"') + result = nvim.call(:nvim_command, 'echo "hello world!"') < A better way is to use the Python REPL with the `neovim` package, where API functions can be called interactively: @@ -117,9 +117,9 @@ functions can be called interactively: You can also embed an Nvim instance via |jobstart()|, and communicate using |rpcrequest()| and |rpcnotify()|: > - let vim = jobstart(['nvim', '--embed'], {'rpc': v:true}) - echo rpcrequest(vim, 'vim_eval', '"Hello " . "world!"') - call jobstop(vim) + let nvim = jobstart(['nvim', '--embed'], {'rpc': v:true}) + echo rpcrequest(nvim, 'nvim_eval', '"Hello " . "world!"') + call jobstop(nvim) < ============================================================================== 4. Implementing API clients *rpc-api-client* *api-client* @@ -177,15 +177,20 @@ contains information that makes this task easier (see also |rpc-types|): - Container types may be decorated with type/size constraints, e.g. ArrayOf(Buffer) or ArrayOf(Integer, 2). This can be useful to generate even more strongly-typed APIs. - - Methods that operate on instances of Nvim special types (msgpack EXT) are - prefixed with the type name in lower case, e.g. `buffer_get_line` - represents the `get_line` method of a Buffer instance. - - Global methods are prefixed with `vim`, e.g. `vim_get_buffers`. + - Functions that are considered to be methods that operate on instances of + Nvim special types (msgpack EXT) will have the `"method"` attribute set to + `true`. The reciever type is the type of the first argument. The method + names are prefixed with `nvim_` plus a shortened type name, e.g. + `nvim_buf_get_lines` represents the `get_lines` method of a Buffer instance. + - Global functions have `"method"` set to `false` and are prefixed with just + `nvim_`, e.g. `nvim_get_buffers`. So for an object-oriented language, an API client contains the classes representing Nvim special types, and the methods of each class could be -defined by inspecting the method name prefix. There could also be a singleton -Vim class with methods mapped to functions prefixed with `vim_`. +defined by stripping the prefix for the type as defined in the `types` metadata +(this will always be the first two "_"-separated parts of the function name). +There could also be a singleton Vim class with methods where the `nvim_` +prefix is stripped off. ============================================================================== 5. Types *rpc-types* @@ -219,18 +224,21 @@ an integer, but not a Window or Tabpage. The most reliable way of determining the type codes for the special Nvim types is to inspect the `types` key of metadata dictionary returned by the -`vim_get_api_info` method at runtime. Here's a sample JSON representation of +`nvim_get_api_info` method at runtime. Here's a sample JSON representation of the `types` object: > "types": { "Buffer": { - "id": 0 + "id": 0, + "prefix": "nvim_buf_" }, "Window": { - "id": 1 + "id": 1, + "prefix": "nvim_win_" }, "Tabpage": { - "id": 2 + "id": 2, + "prefix": "nvim_tabpage_" } } < diff --git a/scripts/dispatch_deprecated.lua b/scripts/dispatch_deprecated.lua new file mode 100644 index 0000000000..f3b299e3fc --- /dev/null +++ b/scripts/dispatch_deprecated.lua @@ -0,0 +1,77 @@ +local deprecated_aliases = { + nvim_buf_line_count="buffer_line_count", + nvim_buf_get_lines="buffer_get_lines", + nvim_buf_set_lines="buffer_set_lines", + nvim_buf_get_var="buffer_get_var", + nvim_buf_set_var="buffer_set_var", + nvim_buf_del_var="buffer_del_var", + nvim_buf_get_option="buffer_get_option", + nvim_buf_set_option="buffer_set_option", + nvim_buf_get_number="buffer_get_number", + nvim_buf_get_name="buffer_get_name", + nvim_buf_set_name="buffer_set_name", + nvim_buf_is_valid="buffer_is_valid", + nvim_buf_get_mark="buffer_get_mark", + nvim_buf_add_highlight="buffer_add_highlight", + nvim_buf_clear_highlight="buffer_clear_highlight", + nvim_tabpage_get_windows="tabpage_get_windows", + nvim_tabpage_get_var="tabpage_get_var", + nvim_tabpage_set_var="tabpage_set_var", + nvim_tabpage_del_var="tabpage_del_var", + nvim_tabpage_get_window="tabpage_get_window", + nvim_tabpage_is_valid="tabpage_is_valid", + nvim_ui_detach="ui_detach", + nvim_ui_try_resize="ui_try_resize", + nvim_command="vim_command", + nvim_feedkeys="vim_feedkeys", + nvim_input="vim_input", + nvim_replace_termcodes="vim_replace_termcodes", + nvim_command_output="vim_command_output", + nvim_eval="vim_eval", + nvim_call_function="vim_call_function", + nvim_strwidth="vim_strwidth", + nvim_list_runtime_paths="vim_list_runtime_paths", + nvim_change_directory="vim_change_directory", + nvim_get_var="vim_get_var", + nvim_set_var="vim_set_var", + nvim_del_var="vim_del_var", + nvim_get_vvar="vim_get_vvar", + nvim_get_option="vim_get_option", + nvim_set_option="vim_set_option", + nvim_out_write="vim_out_write", + nvim_err_write="vim_err_write", + nvim_report_error="vim_report_error", + nvim_get_buffers="vim_get_buffers", + nvim_get_current_buffer="vim_get_current_buffer", + nvim_set_current_buffer="vim_set_current_buffer", + nvim_get_windows="vim_get_windows", + nvim_get_current_window="vim_get_current_window", + nvim_set_current_window="vim_set_current_window", + nvim_get_tabpages="vim_get_tabpages", + nvim_get_current_tabpage="vim_get_current_tabpage", + nvim_set_current_tabpage="vim_set_current_tabpage", + nvim_set_current_line="vim_set_current_line", + nvim_get_current_line="vim_get_current_line", + nvim_del_current_line="vim_del_current_line", + nvim_subscribe="vim_subscribe", + nvim_unsubscribe="vim_unsubscribe", + nvim_name_to_color="vim_name_to_color", + nvim_get_color_map="vim_get_color_map", + nvim_get_api_info="vim_get_api_info", + nvim_win_get_buffer="window_get_buffer", + nvim_win_get_cursor="window_get_cursor", + nvim_win_set_cursor="window_set_cursor", + nvim_win_get_height="window_get_height", + nvim_win_set_height="window_set_height", + nvim_win_get_width="window_get_width", + nvim_win_set_width="window_set_width", + nvim_win_get_var="window_get_var", + nvim_win_set_var="window_set_var", + nvim_win_del_var="window_del_var", + nvim_win_get_option="window_get_option", + nvim_win_set_option="window_set_option", + nvim_win_get_position="window_get_position", + nvim_win_get_tabpage="window_get_tabpage", + nvim_win_is_valid="window_is_valid" +} +return deprecated_aliases diff --git a/scripts/msgpack-gen.lua b/scripts/gendispatch.lua index 2da3c174f9..12d6261b5a 100644 --- a/scripts/msgpack-gen.lua +++ b/scripts/gendispatch.lua @@ -37,22 +37,28 @@ c_proto = Ct( Cg(Cc(false), 'async') * (fill * Cg((P('FUNC_API_ASYNC') * Cc(true)), 'async') ^ -1) * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) * + (fill * Cg((P('FUNC_API_NOEVAL') * Cc(true)), 'noeval') ^ -1) * fill * P(';') ) 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 4 arguments since the last two are output files +assert(#arg >= 3) functions = {} +local scriptdir = arg[1] +package.path = scriptdir .. '/?.lua;' .. package.path + -- 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 = 2, #arg - 2 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -84,6 +90,45 @@ for i = 1, #arg - 1 do input:close() end +local function shallowcopy(orig) + local copy = {} + for orig_key, orig_value in pairs(orig) do + copy[orig_key] = orig_value + end + return copy +end + +local function startswith(String,Start) + return string.sub(String,1,string.len(Start))==Start +end + +-- Export functions under older deprecated names. +-- These will be removed eventually. +local deprecated_aliases = require("dispatch_deprecated") +for i,f in ipairs(shallowcopy(functions)) do + local ismethod = false + if startswith(f.name, "nvim_buf_") then + ismethod = true + elseif startswith(f.name, "nvim_win_") then + ismethod = true + elseif startswith(f.name, "nvim_tabpage_") then + ismethod = true + elseif not startswith(f.name, "nvim_") then + f.noeval = true + f.deprecated_since = 1 + end + f.method = ismethod + local newname = deprecated_aliases[f.name] + if newname ~= nil then + local newf = shallowcopy(f) + newf.name = newname + newf.impl_name = f.name + newf.noeval = true + newf.deprecated_since = 1 + functions[#functions+1] = newf + end +end + -- start building the output output = io.open(outputf, 'wb') @@ -99,7 +144,7 @@ output:write([[ #include "nvim/log.h" #include "nvim/vim.h" #include "nvim/msgpack_rpc/helpers.h" -#include "nvim/msgpack_rpc/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/defs.h" ]]) @@ -163,99 +208,95 @@ end -- the real API. 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('\n{') - output:write('\n Object ret = NIL;') - -- Declare/initialize variables that will hold converted arguments - for j = 1, #fn.parameters do - local param = fn.parameters[j] - local converted = 'arg_'..j - output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';') - end - output:write('\n') - output:write('\n if (args.size != '..#fn.parameters..') {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') - output:write('\n error->set = true;') - output:write('\n goto cleanup;') - output:write('\n }\n') - - -- Validation/conversion for each argument - for j = 1, #fn.parameters do - local converted, convert_arg, param, arg - param = fn.parameters[j] - converted = 'arg_'..j - local rt = real_type(param[1]) - if rt ~= 'Object' then - output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') - output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') - if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then - -- accept positive integers for Buffers, Windows and Tabpages - output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer > 0) {') - output:write('\n '..converted..' = (unsigned)args.items['..(j - 1)..'].data.integer;') - end - output:write('\n } else {') - output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') - output:write('\n error->set = true;') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') + if fn.impl_name == nil then + local args = {} + + 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 + for j = 1, #fn.parameters do + local param = fn.parameters[j] + local converted = 'arg_'..j + output:write('\n '..param[1]..' '..converted..' api_init_'..string.lower(real_type(param[1]))..';') end + output:write('\n') + output:write('\n if (args.size != '..#fn.parameters..') {') + output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);') + output:write('\n error->set = true;') + output:write('\n goto cleanup;') + output:write('\n }\n') - args[#args + 1] = converted - end + -- Validation/conversion for each argument + for j = 1, #fn.parameters do + local converted, convert_arg, param, arg + param = fn.parameters[j] + converted = 'arg_'..j + local rt = real_type(param[1]) + if rt ~= 'Object' then + output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {') + output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..rt:lower()..';') + if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then + -- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages + output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {') + output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;') + end + output:write('\n } else {') + output:write('\n snprintf(error->msg, sizeof(error->msg), "Wrong type for argument '..j..', expecting '..param[1]..'");') + output:write('\n error->set = true;') + output:write('\n goto cleanup;') + output:write('\n }\n') + else + output:write('\n '..converted..' = args.items['..(j - 1)..'];\n') + end - -- function call - local call_args = table.concat(args, ', ') - output:write('\n ') - if fn.return_type ~= 'void' then - -- has a return value, prefix the call with a declaration - output:write(fn.return_type..' rv = ') - end + args[#args + 1] = converted + end - -- write the function name and the opening parenthesis - output:write(fn.name..'(') + -- function call + local call_args = table.concat(args, ', ') + output:write('\n ') + if fn.return_type ~= 'void' then + -- has a return value, prefix the call with a declaration + output:write(fn.return_type..' rv = ') + end - if fn.receives_channel_id then - -- if the function receives the channel id, pass it as first argument - if #args > 0 or fn.can_fail then - output:write('channel_id, '..call_args) + -- write the function name and the opening parenthesis + output:write(fn.name..'(') + + if fn.receives_channel_id then + -- if the function receives the channel id, pass it as first argument + if #args > 0 or fn.can_fail then + output:write('channel_id, '..call_args) + else + output:write('channel_id') + end else - output:write('channel_id') + output:write(call_args) end - else - output:write(call_args) - end - if fn.can_fail then - -- if the function can fail, also pass a pointer to the local error object - if #args > 0 then - output:write(', error);\n') + if fn.can_fail then + -- if the function can fail, also pass a pointer to the local error object + if #args > 0 then + output:write(', error);\n') + else + output:write('error);\n') + end + -- and check for the error + output:write('\n if (error->set) {') + output:write('\n goto cleanup;') + output:write('\n }\n') else - output:write('error);\n') + output:write(');\n') end - -- and check for the error - output:write('\n if (error->set) {') - output:write('\n goto cleanup;') - output:write('\n }\n') - else - output:write(');\n') - end - if fn.return_type ~= 'void' then - output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') - end - -- Now generate the cleanup label for freeing memory allocated for the - -- arguments - output:write('\n\ncleanup:'); + if fn.return_type ~= 'void' then + output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);') + end + output:write('\n\ncleanup:'); - for j = 1, #fn.parameters do - local param = fn.parameters[j] - output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') + output:write('\n return ret;\n}\n\n'); end - output:write('\n return ret;\n}\n\n'); end -- Generate a function that initializes method names with handler functions @@ -281,7 +322,7 @@ for i = 1, #functions do output:write(' msgpack_rpc_add_method_handler('.. '(String) {.data = "'..fn.name..'", '.. '.size = sizeof("'..fn.name..'") - 1}, '.. - '(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name.. + '(MsgpackRpcRequestHandler) {.fn = handle_'.. (fn.impl_name or fn.name).. ', .async = '..tostring(fn.async)..'});\n') if #fn.name > max_fname_len then @@ -311,3 +352,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 new file mode 100644 index 0000000000..b1ba76296c --- /dev/null +++ b/scripts/geneval.lua @@ -0,0 +1,66 @@ +mpack = require('mpack') + +local nvimsrcdir = arg[1] +local autodir = arg[2] +local metadata_file = arg[3] +local funcs_file = arg[4] + +if nvimsrcdir == '--help' then + print([[ +Usage: + lua geneval.lua src/nvim build/src/nvim/auto + +Will generate build/src/nvim/auto/funcs.generated.h with definition of functions +static const array. +]]) + os.exit(0) +end + +package.path = nvimsrcdir .. '/?.lua;' .. package.path + +local funcsfname = autodir .. '/funcs.generated.h' + +local gperfpipe = io.open(funcsfname .. '.gperf', 'wb') + +local funcs = require('eval').funcs +local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) +for i,fun in ipairs(metadata) do + if not fun.noeval then + funcs[fun.name] = { + args=#fun.parameters, + func='api_wrapper', + data='&handle_'..fun.name, + } + end +end + +local funcsdata = io.open(funcs_file, 'w') +funcsdata:write(mpack.pack(funcs)) +funcsdata:close() + +gperfpipe:write([[ +%language=ANSI-C +%global-table +%define initializer-suffix ,0,0,NULL,NULL +%define word-array-name functions +%define hash-function-name hash_internal_func_gperf +%define lookup-function-name find_internal_func_gperf +%omit-struct-type +%struct-type +VimLFuncDef; +%% +]]) + +for name, def in pairs(funcs) do + args = def.args or 0 + if type(args) == 'number' then + args = {args, args} + elseif #args == 1 then + args[2] = 'MAX_FUNC_ARGS' + end + func = def.func or ('f_' .. name) + data = def.data or "NULL" + gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n') + :format(name, args[1], args[2], func, data)) +end +gperfpipe:close() diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 667af7be6c..24c147b811 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -1,3 +1,5 @@ +mpack = require('mpack') + if arg[1] == '--help' then print('Usage: lua genvimvim.lua src/nvim runtime/syntax/vim/generated.vim') os.exit(0) @@ -5,6 +7,7 @@ end local nvimsrcdir = arg[1] local syntax_file = arg[2] +local funcs_file = arg[3] package.path = nvimsrcdir .. '/?.lua;' .. package.path @@ -111,28 +114,16 @@ end w('\n\nsyn case match') local vimfun_start = 'syn keyword vimFuncName contained ' w('\n\n' .. vimfun_start) -eval_fd = io.open(nvimsrcdir .. '/eval.c', 'r') +funcs = mpack.unpack(io.open(funcs_file):read("*all")) local started = 0 -for line in eval_fd:lines() do - if line == '} functions[] =' then - started = 1 - elseif started == 1 then - assert (line == '{') - started = 2 - elseif started == 2 then - if line == '};' then - break - end - local func_name = line:match('^ { "([%w_]+)",') - if func_name then - if lld.line_length > 850 then - w('\n' .. vimfun_start) - end - w(' ' .. func_name) +for name, def in pairs(funcs) do + if name then + if lld.line_length > 850 then + w('\n' .. vimfun_start) end + w(' ' .. name) end end -eval_fd:close() w('\n') syn_fd:close() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5c4df1be0b..3ae75c01c3 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -11,22 +11,28 @@ endif() endif() set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) -set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/msgpack-gen.lua) +set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) file(GLOB API_HEADERS api/*.h) file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) -set(MSGPACK_DISPATCH ${GENERATED_DIR}/msgpack_dispatch.c) +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_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) +set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h) set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h) set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h) set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h) set(EX_CMDS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genex_cmds.lua) +set(FUNCS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/geneval.lua) set(EVENTS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gen_events.lua) set(OPTIONS_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genoptions.lua) set(EVENTS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/auevents.lua) set(EX_CMDS_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/ex_cmds.lua) +set(EVAL_DEFS_FILE ${PROJECT_SOURCE_DIR}/src/nvim/eval.lua) set(OPTIONS_LIST_FILE ${PROJECT_SOURCE_DIR}/src/nvim/options.lua) set(UNICODE_TABLES_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/genunicodetables.lua) set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/unicode) @@ -36,6 +42,7 @@ set(EASTASIANWIDTH_FILE ${UNICODE_DIR}/EastAsianWidth.txt) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) include_directories(${GENERATED_DIR}) +include_directories(${CACHED_GENERATED_DIR}) include_directories(${GENERATED_INCLUDES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) @@ -112,6 +119,10 @@ endforeach() if(NOT MSVC) set_source_files_properties( ${CONV_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion") + # gperf generates ANSI-C with incorrect linkage, ignore it. + set_source_files_properties( + eval.c PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-static-in-inline -Wno-conversion") + endif() if(DEFINED MIN_LOG_LEVEL) @@ -138,9 +149,13 @@ separate_arguments(C_FLAGS_${build_type}_ARRAY UNIX_COMMAND ${CMAKE_C_FLAGS_${bu set(gen_cflags ${gen_cflags} ${C_FLAGS_${build_type}_ARRAY} ${C_FLAGS_ARRAY}) foreach(sfile ${NEOVIM_SOURCES} - "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c") + "${PROJECT_SOURCE_DIR}/src/nvim/regexp_nfa.c" + ${GENERATED_API_DISPATCH}) get_filename_component(full_d ${sfile} PATH) file(RELATIVE_PATH d "${PROJECT_SOURCE_DIR}/src/nvim" "${full_d}") + if(${d} MATCHES "^[.][.]") + file(RELATIVE_PATH d "${GENERATED_DIR}" "${full_d}") + endif() get_filename_component(f ${sfile} NAME) get_filename_component(r ${sfile} NAME_WE) if(NOT ${d} EQUAL ".") @@ -183,8 +198,8 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ${EASTASIANWIDTH_FILE} ) -add_custom_command(OUTPUT ${MSGPACK_DISPATCH} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${MSGPACK_DISPATCH} +add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA} + COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${PROJECT_SOURCE_DIR}/scripts ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} @@ -193,7 +208,7 @@ add_custom_command(OUTPUT ${MSGPACK_DISPATCH} list(APPEND NEOVIM_GENERATED_SOURCES "${PROJECT_BINARY_DIR}/config/auto/pathdef.c" - "${MSGPACK_DISPATCH}" + "${GENERATED_API_DISPATCH}" "${GENERATED_EX_CMDS_ENUM}" "${GENERATED_EX_CMDS_DEFS}" "${GENERATED_EVENTS_ENUM}" @@ -208,6 +223,19 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE} ) +if(NOT GPERF_PRG) + message(FATAL_ERROR "gperf was not found.") +endif() +add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA} + COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA} + COMMAND ${GPERF_PRG} + ${GENERATED_FUNCS_HASH_INPUT} --output-file=${GENERATED_FUNCS} + DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} +) +list(APPEND NEOVIM_GENERATED_SOURCES + "${GENERATED_FUNCS}") + add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} COMMAND ${LUA_PRG} ${EVENTS_GENERATOR} ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index c3bc1f52af..cf8d538f86 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -32,7 +32,7 @@ /// @param buffer The buffer handle /// @param[out] err Details of an error that may have occurred /// @return The line count -Integer buffer_line_count(Buffer buffer, Error *err) +Integer nvim_buf_line_count(Buffer buffer, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -45,11 +45,11 @@ Integer buffer_line_count(Buffer buffer, Error *err) /// Gets a buffer line /// -/// @deprecated use buffer_get_lines instead. +/// @deprecated use nvim_buf_get_lines instead. /// for positive indices (including 0) use -/// "buffer_get_lines(buffer, index, index+1, true)" +/// "nvim_buf_get_lines(buffer, index, index+1, true)" /// for negative indices use -/// "buffer_get_lines(buffer, index-1, index, true)" +/// "nvim_buf_get_lines(buffer, index-1, index, true)" /// /// @param buffer The buffer handle /// @param index The line index @@ -60,7 +60,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) String rv = { .size = 0 }; index = convert_index(index); - Array slice = buffer_get_lines(buffer, index, index+1, true, err); + Array slice = nvim_buf_get_lines(0, buffer, index, index+1, true, err); if (!err->set && slice.size) { rv = slice.items[0].data.string; @@ -73,11 +73,11 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// Sets a buffer line /// -/// @deprecated use buffer_set_lines instead. +/// @deprecated use nvim_buf_set_lines instead. /// for positive indices use -/// "buffer_set_lines(buffer, index, index+1, true, [line])" +/// "nvim_buf_set_lines(buffer, index, index+1, true, [line])" /// for negative indices use -/// "buffer_set_lines(buffer, index-1, index, true, [line])" +/// "nvim_buf_set_lines(buffer, index-1, index, true, [line])" /// /// @param buffer The buffer handle /// @param index The line index @@ -88,16 +88,16 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) Object l = STRING_OBJ(line); Array array = { .items = &l, .size = 1 }; index = convert_index(index); - buffer_set_lines(buffer, index, index+1, true, array, err); + nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); } /// Deletes a buffer line /// -/// @deprecated use buffer_set_lines instead. +/// @deprecated use nvim_buf_set_lines instead. /// for positive indices use -/// "buffer_set_lines(buffer, index, index+1, true, [])" +/// "nvim_buf_set_lines(buffer, index, index+1, true, [])" /// for negative indices use -/// "buffer_set_lines(buffer, index-1, index, true, [])" +/// "nvim_buf_set_lines(buffer, index-1, index, true, [])" /// @param buffer The buffer handle /// @param index The line index /// @param[out] err Details of an error that may have occurred @@ -105,12 +105,12 @@ void buffer_del_line(Buffer buffer, Integer index, Error *err) { Array array = ARRAY_DICT_INIT; index = convert_index(index); - buffer_set_lines(buffer, index, index+1, true, array, err); + nvim_buf_set_lines(0, buffer, index, index+1, true, array, err); } /// Retrieves a line range from the buffer /// -/// @deprecated use buffer_get_lines(buffer, newstart, newend, false) +/// @deprecated use nvim_buf_get_lines(buffer, newstart, newend, false) /// where newstart = start + int(not include_start) - int(start < 0) /// newend = end + int(include_end) - int(end < 0) /// int(bool) = 1 if bool is true else 0 @@ -122,15 +122,15 @@ void buffer_del_line(Buffer buffer, Integer index, Error *err) /// @param[out] err Details of an error that may have occurred /// @return An array of lines ArrayOf(String) buffer_get_line_slice(Buffer buffer, - Integer start, - Integer end, - Boolean include_start, - Boolean include_end, - Error *err) + Integer start, + Integer end, + Boolean include_start, + Boolean include_end, + Error *err) { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - return buffer_get_lines(buffer, start , end, false, err); + return nvim_buf_get_lines(0, buffer, start , end, false, err); } @@ -149,11 +149,12 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, /// @param strict_indexing whether out-of-bounds should be an error. /// @param[out] err Details of an error that may have occurred /// @return An array of lines -ArrayOf(String) buffer_get_lines(Buffer buffer, - Integer start, - Integer end, - Boolean strict_indexing, - Error *err) +ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id, + Buffer buffer, + Integer start, + Integer end, + Boolean strict_indexing, + Error *err) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -191,7 +192,9 @@ ArrayOf(String) buffer_get_lines(Buffer buffer, Object str = STRING_OBJ(cstr_to_string(bufstr)); // Vim represents NULs as NLs, but this may confuse clients. - strchrsub(str.data.string.data, '\n', '\0'); + if (channel_id != INVALID_CHANNEL) { + strchrsub(str.data.string.data, '\n', '\0'); + } rv.items[i] = str; } @@ -212,7 +215,7 @@ end: /// Replaces a line range on the buffer /// -/// @deprecated use buffer_set_lines(buffer, newstart, newend, false, lines) +/// @deprecated use nvim_buf_set_lines(buffer, newstart, newend, false, lines) /// where newstart = start + int(not include_start) + int(start < 0) /// newend = end + int(include_end) + int(end < 0) /// int(bool) = 1 if bool is true else 0 @@ -226,16 +229,16 @@ end: // array will simply delete the line range) /// @param[out] err Details of an error that may have occurred void buffer_set_line_slice(Buffer buffer, - Integer start, - Integer end, - Boolean include_start, - Boolean include_end, - ArrayOf(String) replacement, - Error *err) + Integer start, + Integer end, + Boolean include_start, + Boolean include_end, + ArrayOf(String) replacement, // NOLINT + Error *err) { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - buffer_set_lines(buffer, start, end, false, replacement, err); + nvim_buf_set_lines(0, buffer, start, end, false, replacement, err); } @@ -257,12 +260,13 @@ void buffer_set_line_slice(Buffer buffer, /// @param strict_indexing whether out-of-bounds should be an error. /// @param replacement An array of lines to use as replacement /// @param[out] err Details of an error that may have occurred -void buffer_set_lines(Buffer buffer, - Integer start, - Integer end, - Boolean strict_indexing, - ArrayOf(String) replacement, - Error *err) +void nvim_buf_set_lines(uint64_t channel_id, + Buffer buffer, + Integer start, + Integer end, + Boolean strict_indexing, + ArrayOf(String) replacement, // NOLINT + Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -309,7 +313,7 @@ void buffer_set_lines(Buffer buffer, // line and convert NULs to newlines to avoid truncation. lines[i] = xmallocz(l.size); for (size_t j = 0; j < l.size; j++) { - if (l.data[j] == '\n') { + if (l.data[j] == '\n' && channel_id != INVALID_CHANNEL) { api_set_error(err, Exception, _("string cannot contain newlines")); new_len = i + 1; goto end; @@ -412,7 +416,7 @@ end: /// @param name The variable name /// @param[out] err Details of an error that may have occurred /// @return The variable value -Object buffer_get_var(Buffer buffer, String name, Error *err) +Object nvim_buf_get_var(Buffer buffer, String name, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -433,7 +437,7 @@ Object buffer_get_var(Buffer buffer, String name, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) +Object nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -453,7 +457,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object buffer_del_var(Buffer buffer, String name, Error *err) +Object nvim_buf_del_var(Buffer buffer, String name, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -470,7 +474,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err) /// @param name The option name /// @param[out] err Details of an error that may have occurred /// @return The option value -Object buffer_get_option(Buffer buffer, String name, Error *err) +Object nvim_buf_get_option(Buffer buffer, String name, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -488,7 +492,7 @@ Object buffer_get_option(Buffer buffer, String name, Error *err) /// @param name The option name /// @param value The option value /// @param[out] err Details of an error that may have occurred -void buffer_set_option(Buffer buffer, String name, Object value, Error *err) +void nvim_buf_set_option(Buffer buffer, String name, Object value, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -504,7 +508,7 @@ void buffer_set_option(Buffer buffer, String name, Object value, Error *err) /// @param buffer The buffer handle /// @param[out] err Details of an error that may have occurred /// @return The buffer number -Integer buffer_get_number(Buffer buffer, Error *err) +Integer nvim_buf_get_number(Buffer buffer, Error *err) { Integer rv = 0; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -521,7 +525,7 @@ Integer buffer_get_number(Buffer buffer, Error *err) /// @param buffer The buffer handle /// @param[out] err Details of an error that may have occurred /// @return The buffer name -String buffer_get_name(Buffer buffer, Error *err) +String nvim_buf_get_name(Buffer buffer, Error *err) { String rv = STRING_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -538,7 +542,7 @@ String buffer_get_name(Buffer buffer, Error *err) /// @param buffer The buffer handle /// @param name The buffer name /// @param[out] err Details of an error that may have occurred -void buffer_set_name(Buffer buffer, String name, Error *err) +void nvim_buf_set_name(Buffer buffer, String name, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -567,7 +571,7 @@ void buffer_set_name(Buffer buffer, String name, Error *err) /// /// @param buffer The buffer handle /// @return true if the buffer is valid, false otherwise -Boolean buffer_is_valid(Buffer buffer) +Boolean nvim_buf_is_valid(Buffer buffer) { Error stub = ERROR_INIT; return find_buffer_by_handle(buffer, &stub) != NULL; @@ -575,7 +579,7 @@ Boolean buffer_is_valid(Buffer buffer) /// Inserts a sequence of lines to a buffer at a certain index /// -/// @deprecated use buffer_set_lines(buffer, lnum, lnum, true, lines) +/// @deprecated use nvim_buf_set_lines(buffer, lnum, lnum, true, lines) /// /// @param buffer The buffer handle /// @param lnum Insert the lines after `lnum`. If negative, it will append @@ -589,7 +593,7 @@ void buffer_insert(Buffer buffer, { // "lnum" will be the index of the line after inserting, // no matter if it is negative or not - buffer_set_lines(buffer, lnum, lnum, true, lines, err); + nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err); } /// Return a tuple (row,col) representing the position of the named mark @@ -598,7 +602,7 @@ void buffer_insert(Buffer buffer, /// @param name The mark's name /// @param[out] err Details of an error that may have occurred /// @return The (row, col) tuple -ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err) +ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) { Array rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer_by_handle(buffer, err); @@ -648,7 +652,7 @@ ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err) /// called with src_id = 0, an unique source id is generated and returned. /// Succesive calls can pass in it as "src_id" to add new highlights to the same /// source group. All highlights in the same group can then be cleared with -/// buffer_clear_highlight. If the highlight never will be manually deleted +/// nvim_buf_clear_highlight. If the highlight never will be manually deleted /// pass in -1 for "src_id". /// /// If "hl_group" is the empty string no highlight is added, but a new src_id @@ -666,13 +670,13 @@ ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err) /// or -1 to highlight to end of line /// @param[out] err Details of an error that may have occurred /// @return The src_id that was used -Integer buffer_add_highlight(Buffer buffer, - Integer src_id, - String hl_group, - Integer line, - Integer col_start, - Integer col_end, - Error *err) +Integer nvim_buf_add_highlight(Buffer buffer, + Integer src_id, + String hl_group, + Integer line, + Integer col_start, + Integer col_end, + Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { @@ -708,11 +712,11 @@ Integer buffer_add_highlight(Buffer buffer, /// @param line_end End of range of lines to clear (exclusive) /// or -1 to clear to end of file. /// @param[out] err Details of an error that may have occurred -void buffer_clear_highlight(Buffer buffer, - Integer src_id, - Integer line_start, - Integer line_end, - Error *err) +void nvim_buf_clear_highlight(Buffer buffer, + Integer src_id, + Integer line_start, + Integer line_end, + Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); if (!buf) { diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 5fb95a163f..a6710193ff 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -9,13 +9,15 @@ #define STRING_INIT {.data = NULL, .size = 0} #define OBJECT_INIT { .type = kObjectTypeNil } #define ERROR_INIT { .set = false } -#define REMOTE_TYPE(type) typedef uint64_t type +#define REMOTE_TYPE(type) typedef handle_T type #ifdef INCLUDE_GENERATED_DECLARATIONS # define ArrayOf(...) Array # define DictionaryOf(...) Dictionary #endif +typedef int handle_T; + // Basic types typedef enum { kErrorTypeException, @@ -31,6 +33,9 @@ typedef enum { /// Used as the message ID of notifications. #define NO_RESPONSE UINT64_MAX +/// Used as channel_id when the call is local +#define INVALID_CHANNEL UINT64_MAX + typedef struct { ErrorType type; char msg[1024]; diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h new file mode 100644 index 0000000000..d91456c306 --- /dev/null +++ b/src/nvim/api/private/dispatch.h @@ -0,0 +1,23 @@ +#ifndef NVIM_API_PRIVATE_DISPATCH_H +#define NVIM_API_PRIVATE_DISPATCH_H + +#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 { + 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; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/dispatch.h.generated.h" +#endif + +#endif // NVIM_API_PRIVATE_DISPATCH_H diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c index 69df7294ad..acb0fb332a 100644 --- a/src/nvim/api/private/handle.c +++ b/src/nvim/api/private/handle.c @@ -5,30 +5,26 @@ #include "nvim/map.h" #include "nvim/api/private/handle.h" -#define HANDLE_INIT(name) name##_handles = pmap_new(uint64_t)() +#define HANDLE_INIT(name) name##_handles = pmap_new(handle_T)() #define HANDLE_IMPL(type, name) \ - static PMap(uint64_t) *name##_handles = NULL; \ + static PMap(handle_T) *name##_handles = NULL; /* NOLINT */ \ \ - type *handle_get_##name(uint64_t handle) \ + type *handle_get_##name(handle_T handle) \ { \ - return pmap_get(uint64_t)(name##_handles, handle); \ + return pmap_get(handle_T)(name##_handles, handle); \ } \ \ void handle_register_##name(type *name) \ { \ - assert(!name->handle); \ - name->handle = next_handle++; \ - pmap_put(uint64_t)(name##_handles, name->handle, name); \ + pmap_put(handle_T)(name##_handles, name->handle, name); \ } \ \ void handle_unregister_##name(type *name) \ { \ - pmap_del(uint64_t)(name##_handles, name->handle); \ + pmap_del(handle_T)(name##_handles, name->handle); \ } -static uint64_t next_handle = 1; - HANDLE_IMPL(buf_T, buffer) HANDLE_IMPL(win_T, window) HANDLE_IMPL(tabpage_T, tabpage) diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h index 804e266dc3..30bbfbee1b 100644 --- a/src/nvim/api/private/handle.h +++ b/src/nvim/api/private/handle.h @@ -3,9 +3,10 @@ #include "nvim/vim.h" #include "nvim/buffer_defs.h" +#include "nvim/api/private/defs.h" #define HANDLE_DECLS(type, name) \ - type *handle_get_##name(uint64_t handle); \ + type *handle_get_##name(handle_T handle); \ void handle_register_##name(type *name); \ void handle_unregister_##name(type *name); diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index c88bf2127a..7df2079d93 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -507,6 +507,10 @@ Object vim_to_object(typval_T *obj) buf_T *find_buffer_by_handle(Buffer buffer, Error *err) { + if (buffer == 0) { + return curbuf; + } + buf_T *rv = handle_get_buffer(buffer); if (!rv) { @@ -518,6 +522,10 @@ buf_T *find_buffer_by_handle(Buffer buffer, Error *err) win_T * find_window_by_handle(Window window, Error *err) { + if (window == 0) { + return curwin; + } + win_T *rv = handle_get_window(window); if (!rv) { @@ -529,6 +537,10 @@ win_T * find_window_by_handle(Window window, Error *err) tabpage_T * find_tab_by_handle(Tabpage tabpage, Error *err) { + if (tabpage == 0) { + return curtab; + } + tabpage_T *rv = handle_get_tabpage(tabpage); if (!rv) { @@ -764,12 +776,15 @@ static void init_type_metadata(Dictionary *metadata) Dictionary buffer_metadata = ARRAY_DICT_INIT; PUT(buffer_metadata, "id", INTEGER_OBJ(kObjectTypeBuffer)); + PUT(buffer_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_buf_"))); Dictionary window_metadata = ARRAY_DICT_INIT; PUT(window_metadata, "id", INTEGER_OBJ(kObjectTypeWindow)); + PUT(window_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_win_"))); Dictionary tabpage_metadata = ARRAY_DICT_INIT; PUT(tabpage_metadata, "id", INTEGER_OBJ(kObjectTypeTabpage)); + PUT(tabpage_metadata, "prefix", STRING_OBJ(cstr_to_string("nvim_tabpage_"))); PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata)); PUT(types, "Window", DICTIONARY_OBJ(window_metadata)); diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index c8311b0aa0..5eb901bcb1 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -14,7 +14,7 @@ /// @param tabpage The tabpage /// @param[out] err Details of an error that may have occurred /// @return The windows in `tabpage` -ArrayOf(Window) tabpage_get_windows(Tabpage tabpage, Error *err) +ArrayOf(Window) nvim_tabpage_get_windows(Tabpage tabpage, Error *err) { Array rv = ARRAY_DICT_INIT; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -43,7 +43,7 @@ ArrayOf(Window) tabpage_get_windows(Tabpage tabpage, Error *err) /// @param name The variable name /// @param[out] err Details of an error that may have occurred /// @return The variable value -Object tabpage_get_var(Tabpage tabpage, String name, Error *err) +Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -64,7 +64,10 @@ Object tabpage_get_var(Tabpage tabpage, String name, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) +Object nvim_tabpage_set_var(Tabpage tabpage, + String name, + Object value, + Error *err) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -84,7 +87,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object tabpage_del_var(Tabpage tabpage, String name, Error *err) +Object nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err) { tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -100,7 +103,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err) /// @param tabpage The tab page handle /// @param[out] err Details of an error that may have occurred /// @return The Window handle -Window tabpage_get_window(Tabpage tabpage, Error *err) +Window nvim_tabpage_get_window(Tabpage tabpage, Error *err) { Window rv = 0; tabpage_T *tab = find_tab_by_handle(tabpage, err); @@ -110,7 +113,7 @@ Window tabpage_get_window(Tabpage tabpage, Error *err) } if (tab == curtab) { - return vim_get_current_window(); + return nvim_get_current_window(); } else { FOR_ALL_WINDOWS_IN_TAB(wp, tab) { if (wp == tab->tp_curwin) { @@ -126,7 +129,7 @@ Window tabpage_get_window(Tabpage tabpage, Error *err) /// /// @param tabpage The tab page handle /// @return true if the tab page is valid, false otherwise -Boolean tabpage_is_valid(Tabpage tabpage) +Boolean nvim_tabpage_is_valid(Tabpage tabpage) { Error stub = ERROR_INIT; return find_tab_by_handle(tabpage, &stub) != NULL; diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 2b131443d3..56b41f1eea 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -48,6 +48,7 @@ void remote_ui_disconnect(uint64_t channel_id) void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictionary options, Error *err) + FUNC_API_NOEVAL { if (pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(err, Exception, _("UI already attached for channel")); @@ -117,6 +118,7 @@ void ui_attach(uint64_t channel_id, Integer width, Integer height, } void nvim_ui_detach(uint64_t channel_id, Error *err) + FUNC_API_NOEVAL { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(err, Exception, _("UI is not attached for channel")); @@ -125,14 +127,10 @@ void nvim_ui_detach(uint64_t channel_id, Error *err) remote_ui_disconnect(channel_id); } -/// @deprecated -void ui_detach(uint64_t channel_id, Error *err) -{ - nvim_ui_detach(channel_id, err); -} void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Error *err) + FUNC_API_NOEVAL { if (!pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(err, Exception, _("UI is not attached for channel")); @@ -151,15 +149,10 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width, ui_refresh(); } -/// @deprecated -void ui_try_resize(uint64_t channel_id, Integer width, - Integer height, Error *err) -{ - nvim_ui_try_resize(channel_id, width, height, err); -} - void nvim_ui_set_option(uint64_t channel_id, String name, - Object value, Error *error) { + Object value, Error *error) + FUNC_API_NOEVAL +{ if (!pmap_has(uint64_t)(connected_uis, channel_id)) { api_set_error(error, Exception, _("UI is not attached for channel")); return; diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ac7cc65ee4..bba7d7b9c2 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -36,7 +36,7 @@ /// /// @param str The command str /// @param[out] err Details of an error that may have occurred -void vim_command(String str, Error *err) +void nvim_command(String str, Error *err) { // Run the command try_start(); @@ -52,7 +52,7 @@ void vim_command(String str, Error *err) /// @param escape_csi the string needs escaping for K_SPECIAL/CSI bytes /// @see feedkeys() /// @see vim_strsave_escape_csi -void vim_feedkeys(String keys, String mode, Boolean escape_csi) +void nvim_feedkeys(String keys, String mode, Boolean escape_csi) { bool remap = true; bool insert = false; @@ -96,14 +96,14 @@ void vim_feedkeys(String keys, String mode, Boolean escape_csi) } } -/// Passes input keys to Neovim. Unlike `vim_feedkeys`, this will use a +/// Passes input keys to Neovim. Unlike `nvim_feedkeys`, this will use a /// lower-level input buffer and the call is not deferred. /// This is the most reliable way to emulate real user input. /// /// @param keys to be typed /// @return The number of bytes actually written, which can be lower than /// requested if the buffer becomes full. -Integer vim_input(String keys) +Integer nvim_input(String keys) FUNC_API_ASYNC { return (Integer)input_enqueue(keys); @@ -113,7 +113,7 @@ Integer vim_input(String keys) /// /// @see replace_termcodes /// @see cpoptions -String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, +String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special) { if (str.size == 0) { @@ -133,10 +133,10 @@ String vim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, return cstr_as_string(ptr); } -String vim_command_output(String str, Error *err) +String nvim_command_output(String str, Error *err) { do_cmdline_cmd("redir => v:command_output"); - vim_command(str, err); + nvim_command(str, err); do_cmdline_cmd("redir END"); if (err->set) { @@ -153,7 +153,7 @@ String vim_command_output(String str, Error *err) /// @param str The expression str /// @param[out] err Details of an error that may have occurred /// @return The expanded object -Object vim_eval(String str, Error *err) +Object nvim_eval(String str, Error *err) { Object rv = OBJECT_INIT; // Evaluate the expression @@ -180,7 +180,7 @@ Object vim_eval(String str, Error *err) /// @param args Functions arguments packed in an Array /// @param[out] err Details of an error that may have occurred /// @return Result of the function call -Object vim_call_function(String fname, Array args, Error *err) +Object nvim_call_function(String fname, Array args, Error *err) { Object rv = OBJECT_INIT; if (args.size > MAX_FUNC_ARGS) { @@ -229,7 +229,7 @@ free_vim_args: /// @param str Some text /// @param[out] err Details of an error that may have occurred /// @return The number of cells -Integer vim_strwidth(String str, Error *err) +Integer nvim_strwidth(String str, Error *err) { if (str.size > INT_MAX) { api_set_error(err, Validation, _("String length is too high")); @@ -242,7 +242,7 @@ Integer vim_strwidth(String str, Error *err) /// Gets a list of paths contained in 'runtimepath' /// /// @return The list of paths -ArrayOf(String) vim_list_runtime_paths(void) +ArrayOf(String) nvim_list_runtime_paths(void) { Array rv = ARRAY_DICT_INIT; uint8_t *rtp = p_rtp; @@ -283,7 +283,7 @@ ArrayOf(String) vim_list_runtime_paths(void) /// /// @param dir The new working directory /// @param[out] err Details of an error that may have occurred -void vim_change_directory(String dir, Error *err) +void nvim_change_directory(String dir, Error *err) { if (dir.size >= MAXPATHL) { api_set_error(err, Validation, _("Directory string is too long")); @@ -311,7 +311,7 @@ void vim_change_directory(String dir, Error *err) /// /// @param[out] err Details of an error that may have occurred /// @return The current line string -String vim_get_current_line(Error *err) +String nvim_get_current_line(Error *err) { return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -320,7 +320,7 @@ String vim_get_current_line(Error *err) /// /// @param line The line contents /// @param[out] err Details of an error that may have occurred -void vim_set_current_line(String line, Error *err) +void nvim_set_current_line(String line, Error *err) { buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } @@ -328,7 +328,7 @@ void vim_set_current_line(String line, Error *err) /// Deletes the current line /// /// @param[out] err Details of an error that may have occurred -void vim_del_current_line(Error *err) +void nvim_del_current_line(Error *err) { buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } @@ -338,7 +338,7 @@ void vim_del_current_line(Error *err) /// @param name The variable name /// @param[out] err Details of an error that may have occurred /// @return The variable value -Object vim_get_var(String name, Error *err) +Object nvim_get_var(String name, Error *err) { return dict_get_value(&globvardict, name, err); } @@ -352,7 +352,7 @@ Object vim_get_var(String name, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object vim_set_var(String name, Object value, Error *err) +Object nvim_set_var(String name, Object value, Error *err) { return dict_set_value(&globvardict, name, value, false, err); } @@ -365,7 +365,7 @@ Object vim_set_var(String name, Object value, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object vim_del_var(String name, Error *err) +Object nvim_del_var(String name, Error *err) { return dict_set_value(&globvardict, name, NIL, true, err); } @@ -375,7 +375,7 @@ Object vim_del_var(String name, Error *err) /// @param name The variable name /// @param[out] err Details of an error that may have occurred /// @return The variable value -Object vim_get_vvar(String name, Error *err) +Object nvim_get_vvar(String name, Error *err) { return dict_get_value(&vimvardict, name, err); } @@ -385,7 +385,7 @@ Object vim_get_vvar(String name, Error *err) /// @param name The option name /// @param[out] err Details of an error that may have occurred /// @return The option value -Object vim_get_option(String name, Error *err) +Object nvim_get_option(String name, Error *err) { return get_option_from(NULL, SREQ_GLOBAL, name, err); } @@ -395,7 +395,7 @@ Object vim_get_option(String name, Error *err) /// @param name The option name /// @param value The new option value /// @param[out] err Details of an error that may have occurred -void vim_set_option(String name, Object value, Error *err) +void nvim_set_option(String name, Object value, Error *err) { set_option_to(NULL, SREQ_GLOBAL, name, value, err); } @@ -403,7 +403,7 @@ void vim_set_option(String name, Object value, Error *err) /// Writes a message to vim output buffer /// /// @param str The message -void vim_out_write(String str) +void nvim_out_write(String str) { write_msg(str, false); } @@ -411,25 +411,25 @@ void vim_out_write(String str) /// Writes a message to vim error buffer /// /// @param str The message -void vim_err_write(String str) +void nvim_err_write(String str) { write_msg(str, true); } /// Higher level error reporting function that ensures all str contents -/// are written by sending a trailing linefeed to `vim_err_write` +/// are written by sending a trailing linefeed to `nvim_err_write` /// /// @param str The message -void vim_report_error(String str) +void nvim_report_error(String str) { - vim_err_write(str); - vim_err_write((String) {.data = "\n", .size = 1}); + nvim_err_write(str); + nvim_err_write((String) { .data = "\n", .size = 1 }); } /// Gets the current list of buffer handles /// /// @return The number of buffers -ArrayOf(Buffer) vim_get_buffers(void) +ArrayOf(Buffer) nvim_get_buffers(void) { Array rv = ARRAY_DICT_INIT; @@ -450,7 +450,7 @@ ArrayOf(Buffer) vim_get_buffers(void) /// Gets the current buffer /// /// @reqturn The buffer handle -Buffer vim_get_current_buffer(void) +Buffer nvim_get_current_buffer(void) { return curbuf->handle; } @@ -459,7 +459,7 @@ Buffer vim_get_current_buffer(void) /// /// @param id The buffer handle /// @param[out] err Details of an error that may have occurred -void vim_set_current_buffer(Buffer buffer, Error *err) +void nvim_set_current_buffer(Buffer buffer, Error *err) { buf_T *buf = find_buffer_by_handle(buffer, err); @@ -472,7 +472,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err) if (!try_end(err) && result == FAIL) { api_set_error(err, Exception, - _("Failed to switch to buffer %" PRIu64), + _("Failed to switch to buffer %d"), buffer); } } @@ -480,7 +480,7 @@ void vim_set_current_buffer(Buffer buffer, Error *err) /// Gets the current list of window handles /// /// @return The number of windows -ArrayOf(Window) vim_get_windows(void) +ArrayOf(Window) nvim_get_windows(void) { Array rv = ARRAY_DICT_INIT; @@ -501,7 +501,7 @@ ArrayOf(Window) vim_get_windows(void) /// Gets the current window /// /// @return The window handle -Window vim_get_current_window(void) +Window nvim_get_current_window(void) { return curwin->handle; } @@ -509,7 +509,7 @@ Window vim_get_current_window(void) /// Sets the current window /// /// @param handle The window handle -void vim_set_current_window(Window window, Error *err) +void nvim_set_current_window(Window window, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -522,7 +522,7 @@ void vim_set_current_window(Window window, Error *err) if (!try_end(err) && win != curwin) { api_set_error(err, Exception, - _("Failed to switch to window %" PRIu64), + _("Failed to switch to window %d"), window); } } @@ -530,7 +530,7 @@ void vim_set_current_window(Window window, Error *err) /// Gets the current list of tabpage handles /// /// @return The number of tab pages -ArrayOf(Tabpage) vim_get_tabpages(void) +ArrayOf(Tabpage) nvim_get_tabpages(void) { Array rv = ARRAY_DICT_INIT; @@ -551,7 +551,7 @@ ArrayOf(Tabpage) vim_get_tabpages(void) /// Gets the current tab page /// /// @return The tab page handle -Tabpage vim_get_current_tabpage(void) +Tabpage nvim_get_current_tabpage(void) { return curtab->handle; } @@ -560,7 +560,7 @@ Tabpage vim_get_current_tabpage(void) /// /// @param handle The tab page handle /// @param[out] err Details of an error that may have occurred -void vim_set_current_tabpage(Tabpage tabpage, Error *err) +void nvim_set_current_tabpage(Tabpage tabpage, Error *err) { tabpage_T *tp = find_tab_by_handle(tabpage, err); @@ -573,7 +573,7 @@ void vim_set_current_tabpage(Tabpage tabpage, Error *err) if (!try_end(err) && tp != curtab) { api_set_error(err, Exception, - _("Failed to switch to tabpage %" PRIu64), + _("Failed to switch to tabpage %d"), tabpage); } } @@ -582,7 +582,8 @@ void vim_set_current_tabpage(Tabpage tabpage, Error *err) /// /// @param channel_id The channel id (passed automatically by the dispatcher) /// @param event The event type string -void vim_subscribe(uint64_t channel_id, String event) +void nvim_subscribe(uint64_t channel_id, String event) + FUNC_API_NOEVAL { size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN); char e[METHOD_MAXLEN + 1]; @@ -595,7 +596,8 @@ void vim_subscribe(uint64_t channel_id, String event) /// /// @param channel_id The channel id (passed automatically by the dispatcher) /// @param event The event type string -void vim_unsubscribe(uint64_t channel_id, String event) +void nvim_unsubscribe(uint64_t channel_id, String event) + FUNC_API_NOEVAL { size_t length = (event.size < METHOD_MAXLEN ? event.size : @@ -606,12 +608,12 @@ void vim_unsubscribe(uint64_t channel_id, String event) channel_unsubscribe(channel_id, e); } -Integer vim_name_to_color(String name) +Integer nvim_name_to_color(String name) { return name_to_color((uint8_t *)name.data); } -Dictionary vim_get_color_map(void) +Dictionary nvim_get_color_map(void) { Dictionary colors = ARRAY_DICT_INIT; @@ -623,8 +625,8 @@ Dictionary vim_get_color_map(void) } -Array vim_get_api_info(uint64_t channel_id) - FUNC_API_ASYNC +Array nvim_get_api_info(uint64_t channel_id) + FUNC_API_ASYNC FUNC_API_NOEVAL { Array rv = ARRAY_DICT_INIT; diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index f644453358..9c7fdb0697 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -19,7 +19,7 @@ /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return The buffer handle -Buffer window_get_buffer(Window window, Error *err) +Buffer nvim_win_get_buffer(Window window, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -35,7 +35,7 @@ Buffer window_get_buffer(Window window, Error *err) /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return the (row, col) tuple -ArrayOf(Integer, 2) window_get_cursor(Window window, Error *err) +ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -53,7 +53,7 @@ ArrayOf(Integer, 2) window_get_cursor(Window window, Error *err) /// @param window The window handle /// @param pos the (row, col) tuple representing the new position /// @param[out] err Details of an error that may have occurred -void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) +void nvim_win_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -99,7 +99,7 @@ void window_set_cursor(Window window, ArrayOf(Integer, 2) pos, Error *err) /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return the height in rows -Integer window_get_height(Window window, Error *err) +Integer nvim_win_get_height(Window window, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -116,7 +116,7 @@ Integer window_get_height(Window window, Error *err) /// @param window The window handle /// @param height the new height in rows /// @param[out] err Details of an error that may have occurred -void window_set_height(Window window, Integer height, Error *err) +void nvim_win_set_height(Window window, Integer height, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -142,7 +142,7 @@ void window_set_height(Window window, Integer height, Error *err) /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return the width in columns -Integer window_get_width(Window window, Error *err) +Integer nvim_win_get_width(Window window, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -159,7 +159,7 @@ Integer window_get_width(Window window, Error *err) /// @param window The window handle /// @param width the new width in columns /// @param[out] err Details of an error that may have occurred -void window_set_width(Window window, Integer width, Error *err) +void nvim_win_set_width(Window window, Integer width, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -186,7 +186,7 @@ void window_set_width(Window window, Integer width, Error *err) /// @param name The variable name /// @param[out] err Details of an error that may have occurred /// @return The variable value -Object window_get_var(Window window, String name, Error *err) +Object nvim_win_get_var(Window window, String name, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -207,7 +207,7 @@ Object window_get_var(Window window, String name, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object window_set_var(Window window, String name, Object value, Error *err) +Object nvim_win_set_var(Window window, String name, Object value, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -227,7 +227,7 @@ Object window_set_var(Window window, String name, Object value, Error *err) /// /// @warning It may return nil if there was no previous value /// or if previous value was `v:null`. -Object window_del_var(Window window, String name, Error *err) +Object nvim_win_del_var(Window window, String name, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -244,7 +244,7 @@ Object window_del_var(Window window, String name, Error *err) /// @param name The option name /// @param[out] err Details of an error that may have occurred /// @return The option value -Object window_get_option(Window window, String name, Error *err) +Object nvim_win_get_option(Window window, String name, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -262,7 +262,7 @@ Object window_get_option(Window window, String name, Error *err) /// @param name The option name /// @param value The option value /// @param[out] err Details of an error that may have occurred -void window_set_option(Window window, String name, Object value, Error *err) +void nvim_win_set_option(Window window, String name, Object value, Error *err) { win_T *win = find_window_by_handle(window, err); @@ -278,7 +278,7 @@ void window_set_option(Window window, String name, Object value, Error *err) /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return The (row, col) tuple with the window position -ArrayOf(Integer, 2) window_get_position(Window window, Error *err) +ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err) { Array rv = ARRAY_DICT_INIT; win_T *win = find_window_by_handle(window, err); @@ -296,7 +296,7 @@ ArrayOf(Integer, 2) window_get_position(Window window, Error *err) /// @param window The window handle /// @param[out] err Details of an error that may have occurred /// @return The tab page that contains the window -Tabpage window_get_tabpage(Window window, Error *err) +Tabpage nvim_win_get_tabpage(Window window, Error *err) { Tabpage rv = 0; win_T *win = find_window_by_handle(window, err); @@ -312,7 +312,7 @@ Tabpage window_get_tabpage(Window window, Error *err) /// /// @param window The window handle /// @return true if the window is valid, false otherwise -Boolean window_is_valid(Window window) +Boolean nvim_win_is_valid(Window window) { Error stub = ERROR_INIT; return find_window_by_handle(window, &stub) != NULL; diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index c934d44e70..af29798654 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -1397,8 +1397,7 @@ buflist_new ( } if (buf != curbuf || curbuf == NULL) { buf = xcalloc(1, sizeof(buf_T)); - handle_register_buffer(buf); - /* init b: variables */ + // init b: variables buf->b_vars = dict_alloc(); init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); } @@ -1451,11 +1450,12 @@ buflist_new ( lastbuf = buf; buf->b_fnum = top_file_num++; - if (top_file_num < 0) { /* wrap around (may cause duplicates) */ + handle_register_buffer(buf); + if (top_file_num < 0) { // wrap around (may cause duplicates) EMSG(_("W14: Warning: List of file names overflow")); if (emsg_silent == 0) { ui_flush(); - os_delay(3000L, true); /* make sure it is noticed */ + os_delay(3000L, true); // make sure it is noticed } top_file_num = 1; } @@ -5231,12 +5231,12 @@ wipe_buffer ( int aucmd /* When TRUE trigger autocommands. */ ) { - if (buf->b_fnum == top_file_num - 1) - --top_file_num; - - if (!aucmd) /* Don't trigger BufDelete autocommands here. */ + if (!aucmd) { + // Don't trigger BufDelete autocommands here. block_autocmds(); - close_buffer(NULL, buf, DOBUF_WIPE, FALSE); - if (!aucmd) + } + close_buffer(NULL, buf, DOBUF_WIPE, false); + if (!aucmd) { unblock_autocmds(); + } } diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 46687f344c..ab5987612c 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -461,9 +461,10 @@ typedef struct { */ struct file_buffer { - uint64_t handle; // unique identifier for the buffer - memline_T b_ml; /* associated memline (also contains line - count) */ + handle_T handle; // unique id for the buffer (buffer number) +#define b_fnum handle + + memline_T b_ml; // associated memline (also contains line count buf_T *b_next; /* links in list of buffers */ buf_T *b_prev; @@ -487,8 +488,6 @@ struct file_buffer { bool file_id_valid; FileID file_id; - int b_fnum; /* buffer number for this file. */ - bool b_changed; /* 'modified': Set to true if something in the file has been changed and not written out. */ int b_changedtick; /* incremented for each change, also for undo */ @@ -799,28 +798,27 @@ struct diffblock_S { # define SNAP_AUCMD_IDX 1 # define SNAP_COUNT 2 -/* - * Tab pages point to the top frame of each tab page. - * Note: Most values are NOT valid for the current tab page! Use "curwin", - * "firstwin", etc. for that. "tp_topframe" is always valid and can be - * compared against "topframe" to find the current tab page. - */ +/// Tab pages point to the top frame of each tab page. +/// Note: Most values are NOT valid for the current tab page! Use "curwin", +/// "firstwin", etc. for that. "tp_topframe" is always valid and can be +/// compared against "topframe" to find the current tab page. typedef struct tabpage_S tabpage_T; struct tabpage_S { - uint64_t handle; - tabpage_T *tp_next; /* next tabpage or NULL */ - frame_T *tp_topframe; /* topframe for the windows */ - win_T *tp_curwin; /* current window in this Tab page */ - win_T *tp_prevwin; /* previous window in this Tab page */ - win_T *tp_firstwin; /* first window in this Tab page */ - win_T *tp_lastwin; /* last window in this Tab page */ - long tp_old_Rows; /* Rows when Tab page was left */ - long tp_old_Columns; /* Columns when Tab page was left */ - long tp_ch_used; /* value of 'cmdheight' when frame size - was set */ + handle_T handle; + tabpage_T *tp_next; ///< next tabpage or NULL + frame_T *tp_topframe; ///< topframe for the windows + win_T *tp_curwin; ///< current window in this Tab page + win_T *tp_prevwin; ///< previous window in this Tab page + win_T *tp_firstwin; ///< first window in this Tab page + win_T *tp_lastwin; ///< last window in this Tab page + long tp_old_Rows; ///< Rows when Tab page was left + long tp_old_Columns; ///< Columns when Tab page was left + long tp_ch_used; ///< value of 'cmdheight' when frame size + ///< was set + diff_T *tp_first_diff; buf_T *(tp_diffbuf[DB_COUNT]); - int tp_diff_invalid; ///< list of diffs is outdated */ + int tp_diff_invalid; ///< list of diffs is outdated frame_T *(tp_snapshot[SNAP_COUNT]); ///< window layout snapshots dictitem_T tp_winvar; ///< variable for "t:" Dictionary dict_T *tp_vars; ///< internal variables, local to tab page @@ -936,8 +934,8 @@ struct matchitem { * All row numbers are relative to the start of the window, except w_winrow. */ struct window_S { - uint64_t handle; - int w_id; ///< unique window ID + handle_T handle; ///< unique identifier for the window + buf_T *w_buffer; ///< buffer we are a window into (used ///< often, keep it the first item!) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index bb46898135..bfe4707dab 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -90,6 +90,8 @@ #include "nvim/os/dl.h" #include "nvim/os/input.h" #include "nvim/event/loop.h" +#include "nvim/lib/kvec.h" +#include "nvim/lib/khash.h" #include "nvim/lib/queue.h" #include "nvim/eval/typval_encode.h" @@ -442,6 +444,22 @@ typedef struct { ufunc_T *callback; } timer_T; +typedef void (*FunPtr)(void); + +/// Prototype of C function that implements VimL function +typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data); + +/// Structure holding VimL function definition +typedef struct fst { + char *name; ///< Name of the function. + uint8_t min_argc; ///< Minimal number of arguments. + uint8_t max_argc; ///< Maximal number of arguments. + VimLFunc func; ///< Function implementation. + FunPtr data; ///< Userdata for function implementation. +} VimLFuncDef; + +KHASH_MAP_INIT_STR(functions, VimLFuncDef) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.c.generated.h" #endif @@ -6681,331 +6699,9 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) return OK; } -/* - * Array with names and number of arguments of all internal functions - * MUST BE KEPT SORTED IN strcmp() ORDER FOR BINARY SEARCH! - */ -static struct fst { - char *f_name; /* function name */ - char f_min_argc; /* minimal number of arguments */ - char f_max_argc; /* maximal number of arguments */ - void (*f_func)(typval_T *args, typval_T *rvar); - /* implementation of function */ -} functions[] = -{ - { "abs", 1, 1, f_abs }, - { "acos", 1, 1, f_acos }, // WJMc - { "add", 2, 2, f_add }, - { "and", 2, 2, f_and }, - { "api_info", 0, 0, f_api_info }, - { "append", 2, 2, f_append }, - { "argc", 0, 0, f_argc }, - { "argidx", 0, 0, f_argidx }, - { "arglistid", 0, 2, f_arglistid }, - { "argv", 0, 1, f_argv }, - { "asin", 1, 1, f_asin }, // WJMc - { "assert_equal", 2, 3, f_assert_equal }, - { "assert_exception", 1, 2, f_assert_exception }, - { "assert_fails", 1, 2, f_assert_fails }, - { "assert_false", 1, 2, f_assert_false }, - { "assert_match", 2, 3, f_assert_match }, - { "assert_notequal", 2, 3, f_assert_notequal }, - { "assert_notmatch", 2, 3, f_assert_notmatch }, - { "assert_true", 1, 2, f_assert_true }, - { "atan", 1, 1, f_atan }, - { "atan2", 2, 2, f_atan2 }, - { "browse", 4, 4, f_browse }, - { "browsedir", 2, 2, f_browsedir }, - { "bufexists", 1, 1, f_bufexists }, - { "buffer_exists", 1, 1, f_bufexists }, // obsolete - { "buffer_name", 1, 1, f_bufname }, // obsolete - { "buffer_number", 1, 1, f_bufnr }, // obsolete - { "buflisted", 1, 1, f_buflisted }, - { "bufloaded", 1, 1, f_bufloaded }, - { "bufname", 1, 1, f_bufname }, - { "bufnr", 1, 2, f_bufnr }, - { "bufwinnr", 1, 1, f_bufwinnr }, - { "byte2line", 1, 1, f_byte2line }, - { "byteidx", 2, 2, f_byteidx }, - { "byteidxcomp", 2, 2, f_byteidxcomp }, - { "call", 2, 3, f_call }, - { "ceil", 1, 1, f_ceil }, - { "changenr", 0, 0, f_changenr }, - { "char2nr", 1, 2, f_char2nr }, - { "cindent", 1, 1, f_cindent }, - { "clearmatches", 0, 0, f_clearmatches }, - { "col", 1, 1, f_col }, - { "complete", 2, 2, f_complete }, - { "complete_add", 1, 1, f_complete_add }, - { "complete_check", 0, 0, f_complete_check }, - { "confirm", 1, 4, f_confirm }, - { "copy", 1, 1, f_copy }, - { "cos", 1, 1, f_cos }, - { "cosh", 1, 1, f_cosh }, - { "count", 2, 4, f_count }, - { "cscope_connection", 0, 3, f_cscope_connection }, - { "cursor", 1, 3, f_cursor }, - { "deepcopy", 1, 2, f_deepcopy }, - { "delete", 1, 2, f_delete }, - { "dictwatcheradd", 3, 3, f_dictwatcheradd }, - { "dictwatcherdel", 3, 3, f_dictwatcherdel }, - { "did_filetype", 0, 0, f_did_filetype }, - { "diff_filler", 1, 1, f_diff_filler }, - { "diff_hlID", 2, 2, f_diff_hlID }, - { "empty", 1, 1, f_empty }, - { "escape", 2, 2, f_escape }, - { "eval", 1, 1, f_eval }, - { "eventhandler", 0, 0, f_eventhandler }, - { "executable", 1, 1, f_executable }, - { "execute", 1, 1, f_execute }, - { "exepath", 1, 1, f_exepath }, - { "exists", 1, 1, f_exists }, - { "exp", 1, 1, f_exp }, - { "expand", 1, 3, f_expand }, - { "extend", 2, 3, f_extend }, - { "feedkeys", 1, 2, f_feedkeys }, - { "file_readable", 1, 1, f_filereadable }, // obsolete - { "filereadable", 1, 1, f_filereadable }, - { "filewritable", 1, 1, f_filewritable }, - { "filter", 2, 2, f_filter }, - { "finddir", 1, 3, f_finddir }, - { "findfile", 1, 3, f_findfile }, - { "float2nr", 1, 1, f_float2nr }, - { "floor", 1, 1, f_floor }, - { "fmod", 2, 2, f_fmod }, - { "fnameescape", 1, 1, f_fnameescape }, - { "fnamemodify", 2, 2, f_fnamemodify }, - { "foldclosed", 1, 1, f_foldclosed }, - { "foldclosedend", 1, 1, f_foldclosedend }, - { "foldlevel", 1, 1, f_foldlevel }, - { "foldtext", 0, 0, f_foldtext }, - { "foldtextresult", 1, 1, f_foldtextresult }, - { "foreground", 0, 0, f_foreground }, - { "function", 1, 1, f_function }, - { "garbagecollect", 0, 1, f_garbagecollect }, - { "get", 2, 3, f_get }, - { "getbufline", 2, 3, f_getbufline }, - { "getbufvar", 2, 3, f_getbufvar }, - { "getchar", 0, 1, f_getchar }, - { "getcharmod", 0, 0, f_getcharmod }, - { "getcharsearch", 0, 0, f_getcharsearch }, - { "getcmdline", 0, 0, f_getcmdline }, - { "getcmdpos", 0, 0, f_getcmdpos }, - { "getcmdtype", 0, 0, f_getcmdtype }, - { "getcmdwintype", 0, 0, f_getcmdwintype }, - { "getcompletion", 2, 2, f_getcompletion }, - { "getcurpos", 0, 0, f_getcurpos }, - { "getcwd", 0, 2, f_getcwd }, - { "getfontname", 0, 1, f_getfontname }, - { "getfperm", 1, 1, f_getfperm }, - { "getfsize", 1, 1, f_getfsize }, - { "getftime", 1, 1, f_getftime }, - { "getftype", 1, 1, f_getftype }, - { "getline", 1, 2, f_getline }, - { "getloclist", 1, 1, f_getqflist }, - { "getmatches", 0, 0, f_getmatches }, - { "getpid", 0, 0, f_getpid }, - { "getpos", 1, 1, f_getpos }, - { "getqflist", 0, 0, f_getqflist }, - { "getreg", 0, 3, f_getreg }, - { "getregtype", 0, 1, f_getregtype }, - { "gettabvar", 2, 3, f_gettabvar }, - { "gettabwinvar", 3, 4, f_gettabwinvar }, - { "getwinposx", 0, 0, f_getwinposx }, - { "getwinposy", 0, 0, f_getwinposy }, - { "getwinvar", 2, 3, f_getwinvar }, - { "glob", 1, 4, f_glob }, - { "glob2regpat", 1, 1, f_glob2regpat }, - { "globpath", 2, 5, f_globpath }, - { "has", 1, 1, f_has }, - { "has_key", 2, 2, f_has_key }, - { "haslocaldir", 0, 2, f_haslocaldir }, - { "hasmapto", 1, 3, f_hasmapto }, - { "highlightID", 1, 1, f_hlID }, // obsolete - { "highlight_exists", 1, 1, f_hlexists }, // obsolete - { "histadd", 2, 2, f_histadd }, - { "histdel", 1, 2, f_histdel }, - { "histget", 1, 2, f_histget }, - { "histnr", 1, 1, f_histnr }, - { "hlID", 1, 1, f_hlID }, - { "hlexists", 1, 1, f_hlexists }, - { "hostname", 0, 0, f_hostname }, - { "iconv", 3, 3, f_iconv }, - { "indent", 1, 1, f_indent }, - { "index", 2, 4, f_index }, - { "input", 1, 3, f_input }, - { "inputdialog", 1, 3, f_inputdialog }, - { "inputlist", 1, 1, f_inputlist }, - { "inputrestore", 0, 0, f_inputrestore }, - { "inputsave", 0, 0, f_inputsave }, - { "inputsecret", 1, 2, f_inputsecret }, - { "insert", 2, 3, f_insert }, - { "invert", 1, 1, f_invert }, - { "isdirectory", 1, 1, f_isdirectory }, - { "islocked", 1, 1, f_islocked }, - { "items", 1, 1, f_items }, - { "jobclose", 1, 2, f_jobclose }, - { "jobpid", 1, 1, f_jobpid }, - { "jobresize", 3, 3, f_jobresize }, - { "jobsend", 2, 2, f_jobsend }, - { "jobstart", 1, 2, f_jobstart }, - { "jobstop", 1, 1, f_jobstop }, - { "jobwait", 1, 2, f_jobwait }, - { "join", 1, 2, f_join }, - { "json_decode", 1, 1, f_json_decode }, - { "json_encode", 1, 1, f_json_encode }, - { "keys", 1, 1, f_keys }, - { "last_buffer_nr", 0, 0, f_last_buffer_nr }, // obsolete - { "len", 1, 1, f_len }, - { "libcall", 3, 3, f_libcall }, - { "libcallnr", 3, 3, f_libcallnr }, - { "line", 1, 1, f_line }, - { "line2byte", 1, 1, f_line2byte }, - { "lispindent", 1, 1, f_lispindent }, - { "localtime", 0, 0, f_localtime }, - { "log", 1, 1, f_log }, - { "log10", 1, 1, f_log10 }, - { "map", 2, 2, f_map }, - { "maparg", 1, 4, f_maparg }, - { "mapcheck", 1, 3, f_mapcheck }, - { "match", 2, 4, f_match }, - { "matchadd", 2, 5, f_matchadd }, - { "matchaddpos", 2, 5, f_matchaddpos }, - { "matcharg", 1, 1, f_matcharg }, - { "matchdelete", 1, 1, f_matchdelete }, - { "matchend", 2, 4, f_matchend }, - { "matchlist", 2, 4, f_matchlist }, - { "matchstr", 2, 4, f_matchstr }, - { "max", 1, 1, f_max }, - { "min", 1, 1, f_min }, - { "mkdir", 1, 3, f_mkdir }, - { "mode", 0, 1, f_mode }, - { "msgpackdump", 1, 1, f_msgpackdump }, - { "msgpackparse", 1, 1, f_msgpackparse }, - { "nextnonblank", 1, 1, f_nextnonblank }, - { "nr2char", 1, 2, f_nr2char }, - { "or", 2, 2, f_or }, - { "pathshorten", 1, 1, f_pathshorten }, - { "pow", 2, 2, f_pow }, - { "prevnonblank", 1, 1, f_prevnonblank }, - { "printf", 2, MAX_FUNC_ARGS, f_printf }, - { "pumvisible", 0, 0, f_pumvisible }, - { "py3eval", 1, 1, f_py3eval }, - { "pyeval", 1, 1, f_pyeval }, - { "range", 1, 3, f_range }, - { "readfile", 1, 3, f_readfile }, - { "reltime", 0, 2, f_reltime }, - { "reltimefloat", 1, 1, f_reltimefloat }, - { "reltimestr", 1, 1, f_reltimestr }, - { "remove", 2, 3, f_remove }, - { "rename", 2, 2, f_rename }, - { "repeat", 2, 2, f_repeat }, - { "resolve", 1, 1, f_resolve }, - { "reverse", 1, 1, f_reverse }, - { "round", 1, 1, f_round }, - { "rpcnotify", 2, MAX_FUNC_ARGS, f_rpcnotify }, - { "rpcrequest", 2, MAX_FUNC_ARGS, f_rpcrequest }, - { "rpcstart", 1, 2, f_rpcstart }, - { "rpcstop", 1, 1, f_rpcstop }, - { "screenattr", 2, 2, f_screenattr }, - { "screenchar", 2, 2, f_screenchar }, - { "screencol", 0, 0, f_screencol }, - { "screenrow", 0, 0, f_screenrow }, - { "search", 1, 4, f_search }, - { "searchdecl", 1, 3, f_searchdecl }, - { "searchpair", 3, 7, f_searchpair }, - { "searchpairpos", 3, 7, f_searchpairpos }, - { "searchpos", 1, 4, f_searchpos }, - { "serverlist", 0, 0, f_serverlist }, - { "serverstart", 0, 1, f_serverstart }, - { "serverstop", 1, 1, f_serverstop }, - { "setbufvar", 3, 3, f_setbufvar }, - { "setcharsearch", 1, 1, f_setcharsearch }, - { "setcmdpos", 1, 1, f_setcmdpos }, - { "setfperm", 2, 2, f_setfperm }, - { "setline", 2, 2, f_setline }, - { "setloclist", 2, 4, f_setloclist }, - { "setmatches", 1, 1, f_setmatches }, - { "setpos", 2, 2, f_setpos }, - { "setqflist", 1, 3, f_setqflist }, - { "setreg", 2, 3, f_setreg }, - { "settabvar", 3, 3, f_settabvar }, - { "settabwinvar", 4, 4, f_settabwinvar }, - { "setwinvar", 3, 3, f_setwinvar }, - { "sha256", 1, 1, f_sha256 }, - { "shellescape", 1, 2, f_shellescape }, - { "shiftwidth", 0, 0, f_shiftwidth }, - { "simplify", 1, 1, f_simplify }, - { "sin", 1, 1, f_sin }, - { "sinh", 1, 1, f_sinh }, - { "sort", 1, 3, f_sort }, - { "soundfold", 1, 1, f_soundfold }, - { "spellbadword", 0, 1, f_spellbadword }, - { "spellsuggest", 1, 3, f_spellsuggest }, - { "split", 1, 3, f_split }, - { "sqrt", 1, 1, f_sqrt }, - { "str2float", 1, 1, f_str2float }, - { "str2nr", 1, 2, f_str2nr }, - { "strchars", 1, 2, f_strchars }, - { "strdisplaywidth", 1, 2, f_strdisplaywidth }, - { "strftime", 1, 2, f_strftime }, - { "stridx", 2, 3, f_stridx }, - { "string", 1, 1, f_string }, - { "strlen", 1, 1, f_strlen }, - { "strpart", 2, 3, f_strpart }, - { "strridx", 2, 3, f_strridx }, - { "strtrans", 1, 1, f_strtrans }, - { "strwidth", 1, 1, f_strwidth }, - { "submatch", 1, 2, f_submatch }, - { "substitute", 4, 4, f_substitute }, - { "synID", 3, 3, f_synID }, - { "synIDattr", 2, 3, f_synIDattr }, - { "synIDtrans", 1, 1, f_synIDtrans }, - { "synconcealed", 2, 2, f_synconcealed }, - { "synstack", 2, 2, f_synstack }, - { "system", 1, 2, f_system }, - { "systemlist", 1, 3, f_systemlist }, - { "tabpagebuflist", 0, 1, f_tabpagebuflist }, - { "tabpagenr", 0, 1, f_tabpagenr }, - { "tabpagewinnr", 1, 2, f_tabpagewinnr }, - { "tagfiles", 0, 0, f_tagfiles }, - { "taglist", 1, 1, f_taglist }, - { "tan", 1, 1, f_tan }, - { "tanh", 1, 1, f_tanh }, - { "tempname", 0, 0, f_tempname }, - { "termopen", 1, 2, f_termopen }, - { "test", 1, 1, f_test }, - { "timer_start", 2, 3, f_timer_start }, - { "timer_stop", 1, 1, f_timer_stop }, - { "tolower", 1, 1, f_tolower }, - { "toupper", 1, 1, f_toupper }, - { "tr", 3, 3, f_tr }, - { "trunc", 1, 1, f_trunc }, - { "type", 1, 1, f_type }, - { "undofile", 1, 1, f_undofile }, - { "undotree", 0, 0, f_undotree }, - { "uniq", 1, 3, f_uniq }, - { "values", 1, 1, f_values }, - { "virtcol", 1, 1, f_virtcol }, - { "visualmode", 0, 1, f_visualmode }, - { "wildmenumode", 0, 0, f_wildmenumode }, - { "win_getid", 0, 2, f_win_getid }, - { "win_gotoid", 1, 1, f_win_gotoid }, - { "win_id2tabwin", 1, 1, f_win_id2tabwin }, - { "win_id2win", 1, 1, f_win_id2win }, - { "winbufnr", 1, 1, f_winbufnr }, - { "wincol", 0, 0, f_wincol }, - { "winheight", 1, 1, f_winheight }, - { "winline", 0, 0, f_winline }, - { "winnr", 0, 1, f_winnr }, - { "winrestcmd", 0, 0, f_winrestcmd }, - { "winrestview", 1, 1, f_winrestview }, - { "winsaveview", 0, 0, f_winsaveview }, - { "winwidth", 1, 1, f_winwidth }, - { "wordcount", 0, 0, f_wordcount }, - { "writefile", 2, 3, f_writefile }, - { "xor", 2, 2, f_xor }, -}; +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "funcs.generated.h" +#endif /* @@ -7024,15 +6720,25 @@ char_u *get_function_name(expand_T *xp, int idx) if (name != NULL) return name; } - if (++intidx < (int)ARRAY_SIZE(functions)) { - STRCPY(IObuff, functions[intidx].f_name); - STRCAT(IObuff, "("); - if (functions[intidx].f_max_argc == 0) - STRCAT(IObuff, ")"); - return IObuff; + while ( (size_t)++intidx < ARRAY_SIZE(functions) + && functions[intidx].name[0] == '\0') { } - return NULL; + if ((size_t)intidx >= ARRAY_SIZE(functions)) { + return NULL; + } + + const char *const key = functions[intidx].name; + const size_t key_len = strlen(key); + memcpy(IObuff, key, key_len); + IObuff[key_len] = '('; + if (functions[intidx].max_argc == 0) { + IObuff[key_len + 1] = ')'; + IObuff[key_len + 2] = NUL; + } else { + IObuff[key_len + 1] = NUL; + } + return IObuff; } /* @@ -7057,32 +6763,16 @@ char_u *get_expr_name(expand_T *xp, int idx) -/* - * Find internal function in table above. - * Return index, or -1 if not found - */ -static int -find_internal_func ( - char_u *name /* name of the function */ -) +/// Find internal function in hash functions +/// +/// @param[in] name Name of the function. +/// +/// Returns pointer to the function definition or NULL if not found. +static VimLFuncDef *find_internal_func(const char *const name) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL { - int first = 0; - int last = (int)ARRAY_SIZE(functions) - 1; - - /* - * Find the function name in the table. Binary search. - */ - while (first <= last) { - int x = first + ((unsigned)(last - first)) / 2; - int cmp = STRCMP(name, functions[x].f_name); - if (cmp < 0) - last = x - 1; - else if (cmp > 0) - first = x + 1; - else - return x; - } - return -1; + size_t len = strlen(name); + return find_internal_func_gperf(name, len); } /* @@ -7200,7 +6890,6 @@ call_func ( #define ERROR_NONE 5 #define ERROR_OTHER 6 int error = ERROR_NONE; - int i; int llen; ufunc_T *fp; #define FLEN_FIXED 40 @@ -7222,12 +6911,13 @@ call_func ( fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; - i = 3; - if (eval_fname_sid(name)) { /* "<SID>" or "s:" */ - if (current_SID <= 0) + int i = 3; + if (eval_fname_sid(name)) { // "<SID>" or "s:" + if (current_SID <= 0) { error = ERROR_SCRIPT; - else { - sprintf((char *)fname_buf + 3, "%" PRId64 "_", (int64_t)current_SID); + } else { + vim_snprintf((char *)fname_buf + 3, ARRAY_SIZE(fname_buf) - 3, + "%" PRId64 "_", (int64_t)current_SID); i = (int)STRLEN(fname_buf); } } @@ -7294,18 +6984,16 @@ call_func ( } } } else { - /* - * Find the function name in the table, call its implementation. - */ - i = find_internal_func(fname); - if (i >= 0) { - if (argcount < functions[i].f_min_argc) + // Find the function name in the table, call its implementation. + VimLFuncDef *const fdef = find_internal_func((char *)fname); + if (fdef != NULL) { + if (argcount < fdef->min_argc) { error = ERROR_TOOFEW; - else if (argcount > functions[i].f_max_argc) + } else if (argcount > fdef->max_argc) { error = ERROR_TOOMANY; - else { + } else { argvars[argcount].v_type = VAR_UNKNOWN; - functions[i].f_func(argvars, rettv); + fdef->func(argvars, rettv, fdef->data); error = ERROR_NONE; } } @@ -7416,13 +7104,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, FunPtr fptr) { float_T f; + float_T (*function)(float_T) = (float_T (*)(float_T))fptr; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) { @@ -7432,13 +7117,40 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, } } +static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr; + + 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(INVALID_CHANNEL, NO_RESPONSE, args, &err); + + if (err.set) { + nvim_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: + api_free_array(args); + api_free_object(result); +} + /* * "abs(expr)" function */ -static void f_abs(typval_T *argvars, typval_T *rettv) +static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type == VAR_FLOAT) { - float_op_wrapper(argvars, rettv, &fabs); + float_op_wrapper(argvars, rettv, (FunPtr)&fabs); } else { varnumber_T n; int error = FALSE; @@ -7454,17 +7166,9 @@ static void f_abs(typval_T *argvars, typval_T *rettv) } /* - * "acos()" function - */ -static void f_acos(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &acos); -} - -/* * "add(list, item)" function */ -static void f_add(typval_T *argvars, typval_T *rettv) +static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; @@ -7483,7 +7187,7 @@ static void f_add(typval_T *argvars, typval_T *rettv) /* * "and(expr, expr)" function */ -static void f_and(typval_T *argvars, typval_T *rettv) +static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) & get_tv_number_chk(&argvars[1], NULL); @@ -7491,7 +7195,7 @@ static void f_and(typval_T *argvars, typval_T *rettv) /// "api_info()" function -static void f_api_info(typval_T *argvars, typval_T *rettv) +static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) { Dictionary metadata = api_metadata(); (void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); @@ -7501,7 +7205,7 @@ static void f_api_info(typval_T *argvars, typval_T *rettv) /* * "append(lnum, string/list)" function */ -static void f_append(typval_T *argvars, typval_T *rettv) +static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long lnum; char_u *line; @@ -7556,7 +7260,7 @@ static void f_append(typval_T *argvars, typval_T *rettv) /* * "argc()" function */ -static void f_argc(typval_T *argvars, typval_T *rettv) +static void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ARGCOUNT; } @@ -7564,13 +7268,13 @@ static void f_argc(typval_T *argvars, typval_T *rettv) /* * "argidx()" function */ -static void f_argidx(typval_T *argvars, typval_T *rettv) +static void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = curwin->w_arg_idx; } /// "arglistid" function -static void f_arglistid(typval_T *argvars, typval_T *rettv) +static void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; win_T *wp = find_tabwin(&argvars[0], &argvars[1]); @@ -7582,7 +7286,7 @@ static void f_arglistid(typval_T *argvars, typval_T *rettv) /* * "argv(nr)" function */ -static void f_argv(typval_T *argvars, typval_T *rettv) +static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int idx; @@ -7689,19 +7393,19 @@ static void assert_equal_common(typval_T *argvars, assert_type_T atype) } // "assert_equal(expected, actual[, msg])" function -static void f_assert_equal(typval_T *argvars, typval_T *rettv) +static void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_equal_common(argvars, ASSERT_EQUAL); } // "assert_notequal(expected, actual[, msg])" function -static void f_assert_notequal(typval_T *argvars, typval_T *rettv) +static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_equal_common(argvars, ASSERT_NOTEQUAL); } /// "assert_exception(string[, msg])" function -static void f_assert_exception(typval_T *argvars, typval_T *rettv) +static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; @@ -7722,7 +7426,7 @@ static void f_assert_exception(typval_T *argvars, typval_T *rettv) } /// "assert_fails(cmd [, error])" function -static void f_assert_fails(typval_T *argvars, typval_T *rettv) +static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *cmd = get_tv_string_chk(&argvars[0]); garray_T ga; @@ -7782,7 +7486,7 @@ static void assert_bool(typval_T *argvars, bool is_true) } // "assert_false(actual[, msg])" function -static void f_assert_false(typval_T *argvars, typval_T *rettv) +static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_bool(argvars, false); } @@ -7806,43 +7510,27 @@ static void assert_match_common(typval_T *argvars, assert_type_T atype) } /// "assert_match(pattern, actual[, msg])" function -static void f_assert_match(typval_T *argvars, typval_T *rettv) +static void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_match_common(argvars, ASSERT_MATCH); } /// "assert_notmatch(pattern, actual[, msg])" function -static void f_assert_notmatch(typval_T *argvars, typval_T *rettv) +static void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_match_common(argvars, ASSERT_NOTMATCH); } // "assert_true(actual[, msg])" function -static void f_assert_true(typval_T *argvars, typval_T *rettv) +static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr) { assert_bool(argvars, true); } /* - * "asin()" function - */ -static void f_asin(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &asin); -} - -/* - * "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) +static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx, fy; @@ -7857,7 +7545,7 @@ static void f_atan2(typval_T *argvars, typval_T *rettv) /* * "browse(save, title, initdir, default)" function */ -static void f_browse(typval_T *argvars, typval_T *rettv) +static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; @@ -7866,9 +7554,9 @@ static void f_browse(typval_T *argvars, typval_T *rettv) /* * "browsedir(title, initdir)" function */ -static void f_browsedir(typval_T *argvars, typval_T *rettv) +static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - f_browse(argvars, rettv); + f_browse(argvars, rettv, NULL); } @@ -7904,7 +7592,7 @@ static buf_T *find_buffer(typval_T *avar) /* * "bufexists(expr)" function */ -static void f_bufexists(typval_T *argvars, typval_T *rettv) +static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); } @@ -7912,7 +7600,7 @@ static void f_bufexists(typval_T *argvars, typval_T *rettv) /* * "buflisted(expr)" function */ -static void f_buflisted(typval_T *argvars, typval_T *rettv) +static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -7923,7 +7611,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv) /* * "bufloaded(expr)" function */ -static void f_bufloaded(typval_T *argvars, typval_T *rettv) +static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -7973,7 +7661,7 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only) /* * "bufname(expr)" function */ -static void f_bufname(typval_T *argvars, typval_T *rettv) +static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -7991,7 +7679,7 @@ static void f_bufname(typval_T *argvars, typval_T *rettv) /* * "bufnr(expr)" function */ -static void f_bufnr(typval_T *argvars, typval_T *rettv) +static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; int error = FALSE; @@ -8021,7 +7709,7 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv) /* * "bufwinnr(nr)" function */ -static void f_bufwinnr(typval_T *argvars, typval_T *rettv) +static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */ ++emsg_off; @@ -8043,7 +7731,7 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv) /* * "byte2line(byte)" function */ -static void f_byte2line(typval_T *argvars, typval_T *rettv) +static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long boff = 0; @@ -8082,7 +7770,7 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp) /* * "byteidx()" function */ -static void f_byteidx(typval_T *argvars, typval_T *rettv) +static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { byteidx(argvars, rettv, FALSE); } @@ -8090,7 +7778,7 @@ static void f_byteidx(typval_T *argvars, typval_T *rettv) /* * "byteidxcomp()" function */ -static void f_byteidxcomp(typval_T *argvars, typval_T *rettv) +static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr) { byteidx(argvars, rettv, TRUE); } @@ -8130,7 +7818,7 @@ int func_call(char_u *name, typval_T *args, dict_T *selfdict, typval_T *rettv) /* * "call(func, arglist)" function */ -static void f_call(typval_T *argvars, typval_T *rettv) +static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *func; dict_T *selfdict = NULL; @@ -8161,17 +7849,9 @@ static void f_call(typval_T *argvars, typval_T *rettv) } /* - * "ceil({float})" function - */ -static void f_ceil(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &ceil); -} - -/* * "changenr()" function */ -static void f_changenr(typval_T *argvars, typval_T *rettv) +static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = curbuf->b_u_seq_cur; } @@ -8179,7 +7859,7 @@ static void f_changenr(typval_T *argvars, typval_T *rettv) /* * "char2nr(string)" function */ -static void f_char2nr(typval_T *argvars, typval_T *rettv) +static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (has_mbyte) { int utf8 = 0; @@ -8198,7 +7878,7 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv) /* * "cindent(lnum)" function */ -static void f_cindent(typval_T *argvars, typval_T *rettv) +static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; linenr_T lnum; @@ -8216,7 +7896,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv) /* * "clearmatches()" function */ -static void f_clearmatches(typval_T *argvars, typval_T *rettv) +static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) { clear_matches(curwin); } @@ -8224,7 +7904,7 @@ static void f_clearmatches(typval_T *argvars, typval_T *rettv) /* * "col(string)" function */ -static void f_col(typval_T *argvars, typval_T *rettv) +static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) { colnr_T col = 0; pos_T *fp; @@ -8261,7 +7941,7 @@ static void f_col(typval_T *argvars, typval_T *rettv) /* * "complete()" function */ -static void f_complete(typval_T *argvars, typval_T *rettv) +static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int startcol; @@ -8290,7 +7970,7 @@ static void f_complete(typval_T *argvars, typval_T *rettv) /* * "complete_add()" function */ -static void f_complete_add(typval_T *argvars, typval_T *rettv) +static void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0); } @@ -8298,7 +7978,7 @@ static void f_complete_add(typval_T *argvars, typval_T *rettv) /* * "complete_check()" function */ -static void f_complete_check(typval_T *argvars, typval_T *rettv) +static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int saved = RedrawingDisabled; @@ -8311,7 +7991,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv) /* * "confirm(message, buttons[, default [, type]])" function */ -static void f_confirm(typval_T *argvars, typval_T *rettv) +static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *message; char_u *buttons = NULL; @@ -8359,31 +8039,15 @@ static void f_confirm(typval_T *argvars, typval_T *rettv) /* * "copy()" function */ -static void f_copy(typval_T *argvars, typval_T *rettv) +static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { var_item_copy(NULL, &argvars[0], rettv, false, 0); } /* - * "cos()" function - */ -static void f_cos(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &cos); -} - -/* - * "cosh()" function - */ -static void f_cosh(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &cosh); -} - -/* * "count()" function */ -static void f_count(typval_T *argvars, typval_T *rettv) +static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long n = 0; int ic = FALSE; @@ -8448,7 +8112,7 @@ static void f_count(typval_T *argvars, typval_T *rettv) * * Checks the existence of a cscope connection. */ -static void f_cscope_connection(typval_T *argvars, typval_T *rettv) +static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int num = 0; char_u *dbpath = NULL; @@ -8472,7 +8136,7 @@ static void f_cscope_connection(typval_T *argvars, typval_T *rettv) /// Moves the cursor to the specified line and column. /// /// @returns 0 when the position could be set, -1 otherwise. -static void f_cursor(typval_T *argvars, typval_T *rettv) +static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long line, col; long coladd = 0; @@ -8528,7 +8192,7 @@ static void f_cursor(typval_T *argvars, typval_T *rettv) /* * "deepcopy()" function */ -static void f_deepcopy(typval_T *argvars, typval_T *rettv) +static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int noref = 0; @@ -8544,7 +8208,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv) } // "delete()" function -static void f_delete(typval_T *argvars, typval_T *rettv) +static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u nbuf[NUMBUFLEN]; char_u *name; @@ -8582,7 +8246,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv) } // dictwatcheradd(dict, key, funcref) function -static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv) +static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_restricted() || check_secure()) { return; @@ -8627,7 +8291,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv) } // dictwatcherdel(dict, key, funcref) function -static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv) +static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_restricted() || check_secure()) { return; @@ -8688,7 +8352,7 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv) /* * "did_filetype()" function */ -static void f_did_filetype(typval_T *argvars, typval_T *rettv) +static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = did_filetype; } @@ -8696,7 +8360,7 @@ static void f_did_filetype(typval_T *argvars, typval_T *rettv) /* * "diff_filler()" function */ -static void f_diff_filler(typval_T *argvars, typval_T *rettv) +static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = diff_check_fill(curwin, get_tv_lnum(argvars)); } @@ -8704,7 +8368,7 @@ static void f_diff_filler(typval_T *argvars, typval_T *rettv) /* * "diff_hlID()" function */ -static void f_diff_hlID(typval_T *argvars, typval_T *rettv) +static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = get_tv_lnum(argvars); static linenr_T prev_lnum = 0; @@ -8753,7 +8417,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv) /* * "empty({expr})" function */ -static void f_empty(typval_T *argvars, typval_T *rettv) +static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool n = true; @@ -8791,7 +8455,7 @@ static void f_empty(typval_T *argvars, typval_T *rettv) /* * "escape({string}, {chars})" function */ -static void f_escape(typval_T *argvars, typval_T *rettv) +static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; @@ -8803,7 +8467,7 @@ static void f_escape(typval_T *argvars, typval_T *rettv) /* * "eval()" function */ -static void f_eval(typval_T *argvars, typval_T *rettv) +static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s; @@ -8827,7 +8491,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv) /* * "eventhandler()" function */ -static void f_eventhandler(typval_T *argvars, typval_T *rettv) +static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = vgetc_busy; } @@ -8835,7 +8499,7 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv) /* * "executable()" function */ -static void f_executable(typval_T *argvars, typval_T *rettv) +static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *name = get_tv_string(&argvars[0]); @@ -8845,7 +8509,7 @@ static void f_executable(typval_T *argvars, typval_T *rettv) } // "execute(command)" function -static void f_execute(typval_T *argvars, typval_T *rettv) +static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int save_msg_silent = msg_silent; garray_T *save_capture_ga = capture_ga; @@ -8877,7 +8541,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv) } /// "exepath()" function -static void f_exepath(typval_T *argvars, typval_T *rettv) +static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *arg = get_tv_string(&argvars[0]); char_u *path = NULL; @@ -8891,7 +8555,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv) /* * "exists()" function */ -static void f_exists(typval_T *argvars, typval_T *rettv) +static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p; char_u *name; @@ -8952,17 +8616,9 @@ static void f_exists(typval_T *argvars, typval_T *rettv) } /* - * "exp()" function - */ -static void f_exp(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &exp); -} - -/* * "expand()" function */ -static void f_expand(typval_T *argvars, typval_T *rettv) +static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s; size_t len; @@ -9091,7 +8747,7 @@ void dict_extend(dict_T *d1, dict_T *d2, char_u *action) * "extend(list, list [, idx])" function * "extend(dict, dict [, action])" function */ -static void f_extend(typval_T *argvars, typval_T *rettv) +static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *arg_errmsg = (char_u *)N_("extend() argument"); @@ -9163,7 +8819,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv) /* * "feedkeys()" function */ -static void f_feedkeys(typval_T *argvars, typval_T *rettv) +static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *keys, *flags = NULL; char_u nbuf[NUMBUFLEN]; @@ -9180,13 +8836,13 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv) flags = get_tv_string_buf(&argvars[1], nbuf); } - vim_feedkeys(cstr_as_string((char *)keys), - cstr_as_string((char *)flags), true); + nvim_feedkeys(cstr_as_string((char *)keys), + cstr_as_string((char *)flags), true); } } /// "filereadable()" function -static void f_filereadable(typval_T *argvars, typval_T *rettv) +static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = get_tv_string(&argvars[0]); rettv->vval.v_number = @@ -9197,7 +8853,7 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv) * Return 0 for not writable, 1 for writable file, 2 for a dir which we have * rights to write into. */ -static void f_filewritable(typval_T *argvars, typval_T *rettv) +static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *filename = (char *)get_tv_string(&argvars[0]); rettv->vval.v_number = os_file_is_writable(filename); @@ -9412,7 +9068,7 @@ theend: /* * "filter()" function */ -static void f_filter(typval_T *argvars, typval_T *rettv) +static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr) { filter_map(argvars, rettv, FALSE); } @@ -9420,7 +9076,7 @@ static void f_filter(typval_T *argvars, typval_T *rettv) /* * "finddir({fname}[, {path}[, {count}]])" function */ -static void f_finddir(typval_T *argvars, typval_T *rettv) +static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { findfilendir(argvars, rettv, FINDFILE_DIR); } @@ -9428,7 +9084,7 @@ static void f_finddir(typval_T *argvars, typval_T *rettv) /* * "findfile({fname}[, {path}[, {count}]])" function */ -static void f_findfile(typval_T *argvars, typval_T *rettv) +static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { findfilendir(argvars, rettv, FINDFILE_FILE); } @@ -9436,7 +9092,7 @@ static void f_findfile(typval_T *argvars, typval_T *rettv) /* * "float2nr({float})" function */ -static void f_float2nr(typval_T *argvars, typval_T *rettv) +static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; @@ -9451,17 +9107,9 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv) } /* - * "floor({float})" function - */ -static void f_floor(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &floor); -} - -/* * "fmod()" function */ -static void f_fmod(typval_T *argvars, typval_T *rettv) +static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx, fy; @@ -9476,7 +9124,7 @@ static void f_fmod(typval_T *argvars, typval_T *rettv) /* * "fnameescape({string})" function */ -static void f_fnameescape(typval_T *argvars, typval_T *rettv) +static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = vim_strsave_fnameescape( get_tv_string(&argvars[0]), FALSE); @@ -9486,7 +9134,7 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv) /* * "fnamemodify({fname}, {mods})" function */ -static void f_fnamemodify(typval_T *argvars, typval_T *rettv) +static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *fname; char_u *mods; @@ -9537,7 +9185,7 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end) /* * "foldclosed()" function */ -static void f_foldclosed(typval_T *argvars, typval_T *rettv) +static void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { foldclosed_both(argvars, rettv, FALSE); } @@ -9545,7 +9193,7 @@ static void f_foldclosed(typval_T *argvars, typval_T *rettv) /* * "foldclosedend()" function */ -static void f_foldclosedend(typval_T *argvars, typval_T *rettv) +static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { foldclosed_both(argvars, rettv, TRUE); } @@ -9553,7 +9201,7 @@ static void f_foldclosedend(typval_T *argvars, typval_T *rettv) /* * "foldlevel()" function */ -static void f_foldlevel(typval_T *argvars, typval_T *rettv) +static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -9565,7 +9213,7 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv) /* * "foldtext()" function */ -static void f_foldtext(typval_T *argvars, typval_T *rettv) +static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; char_u *s; @@ -9618,7 +9266,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv) /* * "foldtextresult(lnum)" function */ -static void f_foldtextresult(typval_T *argvars, typval_T *rettv) +static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; char_u *text; @@ -9645,14 +9293,14 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv) /* * "foreground()" function */ -static void f_foreground(typval_T *argvars, typval_T *rettv) +static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr) { } /* * "function()" function */ -static void f_function(typval_T *argvars, typval_T *rettv) +static void f_function(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s; @@ -9684,7 +9332,7 @@ static void f_function(typval_T *argvars, typval_T *rettv) /* * "garbagecollect()" function */ -static void f_garbagecollect(typval_T *argvars, typval_T *rettv) +static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr) { /* This is postponed until we are back at the toplevel, because we may be * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */ @@ -9697,7 +9345,7 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv) /* * "get()" function */ -static void f_get(typval_T *argvars, typval_T *rettv) +static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) { listitem_T *li; list_T *l; @@ -9773,7 +9421,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli /* * "getbufline()" function */ -static void f_getbufline(typval_T *argvars, typval_T *rettv) +static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; linenr_T end; @@ -9796,7 +9444,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv) /* * "getbufvar()" function */ -static void f_getbufvar(typval_T *argvars, typval_T *rettv) +static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; buf_T *save_curbuf; @@ -9849,7 +9497,7 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv) /* * "getchar()" function */ -static void f_getchar(typval_T *argvars, typval_T *rettv) +static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { varnumber_T n; int error = FALSE; @@ -9933,7 +9581,7 @@ static void f_getchar(typval_T *argvars, typval_T *rettv) /* * "getcharmod()" function */ -static void f_getcharmod(typval_T *argvars, typval_T *rettv) +static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = mod_mask; } @@ -9941,7 +9589,7 @@ static void f_getcharmod(typval_T *argvars, typval_T *rettv) /* * "getcharsearch()" function */ -static void f_getcharsearch(typval_T *argvars, typval_T *rettv) +static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv_dict_alloc(rettv); @@ -9955,7 +9603,7 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv) /* * "getcmdline()" function */ -static void f_getcmdline(typval_T *argvars, typval_T *rettv) +static void f_getcmdline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = get_cmdline_str(); @@ -9964,7 +9612,7 @@ static void f_getcmdline(typval_T *argvars, typval_T *rettv) /* * "getcmdpos()" function */ -static void f_getcmdpos(typval_T *argvars, typval_T *rettv) +static void f_getcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_cmdline_pos() + 1; } @@ -9972,7 +9620,7 @@ static void f_getcmdpos(typval_T *argvars, typval_T *rettv) /* * "getcmdtype()" function */ -static void f_getcmdtype(typval_T *argvars, typval_T *rettv) +static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = xmallocz(1); @@ -9982,7 +9630,7 @@ static void f_getcmdtype(typval_T *argvars, typval_T *rettv) /* * "getcmdwintype()" function */ -static void f_getcmdwintype(typval_T *argvars, typval_T *rettv) +static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -9991,7 +9639,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv) } // "getcompletion()" function -static void f_getcompletion(typval_T *argvars, typval_T *rettv) +static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *pat; expand_T xpc; @@ -10043,7 +9691,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv) /// @pre An argument may not be -1 if preceding arguments are not all -1. /// /// @post The return value will be a string. -static void f_getcwd(typval_T *argvars, typval_T *rettv) +static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { // Possible scope of working directory to return. CdScope scope = kCdScopeInvalid; @@ -10166,7 +9814,7 @@ end: /* * "getfontname()" function */ -static void f_getfontname(typval_T *argvars, typval_T *rettv) +static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -10175,7 +9823,7 @@ static void f_getfontname(typval_T *argvars, typval_T *rettv) /* * "getfperm({fname})" function */ -static void f_getfperm(typval_T *argvars, typval_T *rettv) +static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *perm = NULL; char_u flags[] = "rwx"; @@ -10196,7 +9844,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv) /* * "getfsize({fname})" function */ -static void f_getfsize(typval_T *argvars, typval_T *rettv) +static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *fname = (char *)get_tv_string(&argvars[0]); @@ -10223,7 +9871,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv) /* * "getftime({fname})" function */ -static void f_getftime(typval_T *argvars, typval_T *rettv) +static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *fname = (char *)get_tv_string(&argvars[0]); @@ -10238,7 +9886,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv) /* * "getftype({fname})" function */ -static void f_getftype(typval_T *argvars, typval_T *rettv) +static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *fname; char_u *type = NULL; @@ -10314,7 +9962,7 @@ static void f_getftype(typval_T *argvars, typval_T *rettv) /* * "getline(lnum, [end])" function */ -static void f_getline(typval_T *argvars, typval_T *rettv) +static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; linenr_T end; @@ -10335,7 +9983,7 @@ static void f_getline(typval_T *argvars, typval_T *rettv) /* * "getmatches()" function */ -static void f_getmatches(typval_T *argvars, typval_T *rettv) +static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) { matchitem_T *cur = curwin->w_match_head; int i; @@ -10384,7 +10032,7 @@ static void f_getmatches(typval_T *argvars, typval_T *rettv) /* * "getpid()" function */ -static void f_getpid(typval_T *argvars, typval_T *rettv) +static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = os_get_pid(); } @@ -10420,7 +10068,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) /* * "getcurpos(string)" function */ -static void f_getcurpos(typval_T *argvars, typval_T *rettv) +static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getpos_both(argvars, rettv, true); } @@ -10428,7 +10076,7 @@ static void f_getcurpos(typval_T *argvars, typval_T *rettv) /* * "getpos(string)" function */ -static void f_getpos(typval_T *argvars, typval_T *rettv) +static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getpos_both(argvars, rettv, false); } @@ -10436,7 +10084,7 @@ static void f_getpos(typval_T *argvars, typval_T *rettv) /* * "getqflist()" and "getloclist()" functions */ -static void f_getqflist(typval_T *argvars, typval_T *rettv) +static void f_getqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv_list_alloc(rettv); win_T *wp = NULL; @@ -10450,7 +10098,7 @@ static void f_getqflist(typval_T *argvars, typval_T *rettv) } /// "getreg()" function -static void f_getreg(typval_T *argvars, typval_T *rettv) +static void f_getreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *strregname; int regname; @@ -10496,7 +10144,7 @@ static void f_getreg(typval_T *argvars, typval_T *rettv) /* * "getregtype()" function */ -static void f_getregtype(typval_T *argvars, typval_T *rettv) +static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *strregname; int regname; @@ -10528,7 +10176,7 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv) /* * "gettabvar()" function */ -static void f_gettabvar(typval_T *argvars, typval_T *rettv) +static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *oldcurwin; tabpage_T *tp, *oldtabpage; @@ -10567,7 +10215,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv) /* * "gettabwinvar()" function */ -static void f_gettabwinvar(typval_T *argvars, typval_T *rettv) +static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getwinvar(argvars, rettv, 1); } @@ -10575,7 +10223,7 @@ static void f_gettabwinvar(typval_T *argvars, typval_T *rettv) /* * "getwinposx()" function */ -static void f_getwinposx(typval_T *argvars, typval_T *rettv) +static void f_getwinposx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; } @@ -10583,7 +10231,7 @@ static void f_getwinposx(typval_T *argvars, typval_T *rettv) /* * "getwinposy()" function */ -static void f_getwinposy(typval_T *argvars, typval_T *rettv) +static void f_getwinposy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; } @@ -10647,7 +10295,7 @@ static win_T *find_tabwin(typval_T *wvp, typval_T *tvp) } /// "getwinvar()" function -static void f_getwinvar(typval_T *argvars, typval_T *rettv) +static void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getwinvar(argvars, rettv, 0); } @@ -10718,7 +10366,7 @@ getwinvar ( /* * "glob()" function */ -static void f_glob(typval_T *argvars, typval_T *rettv) +static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int options = WILD_SILENT|WILD_USE_NL; expand_T xpc; @@ -10762,7 +10410,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv) } /// "globpath()" function -static void f_globpath(typval_T *argvars, typval_T *rettv) +static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int flags = 0; // Flags for globpath. int error = false; @@ -10813,7 +10461,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv) } // "glob2regpat()" function -static void f_glob2regpat(typval_T *argvars, typval_T *rettv) +static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *pat = get_tv_string_chk(&argvars[0]); // NULL on type error @@ -10826,7 +10474,7 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv) /* * "has()" function */ -static void f_has(typval_T *argvars, typval_T *rettv) +static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int i; char_u *name; @@ -10994,7 +10642,7 @@ static void f_has(typval_T *argvars, typval_T *rettv) /* * "has_key()" function */ -static void f_has_key(typval_T *argvars, typval_T *rettv) +static void f_has_key(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_DICT) { EMSG(_(e_dictreq)); @@ -11018,7 +10666,7 @@ static void f_has_key(typval_T *argvars, typval_T *rettv) /// @pre An argument may not be -1 if preceding arguments are not all -1. /// /// @post The return value will be either the number `1` or `0`. -static void f_haslocaldir(typval_T *argvars, typval_T *rettv) +static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { // Possible scope of working directory to return. CdScope scope = kCdScopeInvalid; @@ -11111,7 +10759,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv) /* * "hasmapto()" function */ -static void f_hasmapto(typval_T *argvars, typval_T *rettv) +static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *name; char_u *mode; @@ -11136,7 +10784,7 @@ static void f_hasmapto(typval_T *argvars, typval_T *rettv) /* * "histadd()" function */ -static void f_histadd(typval_T *argvars, typval_T *rettv) +static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType histype; char_u *str; @@ -11162,7 +10810,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv) /* * "histdel()" function */ -static void f_histdel(typval_T *argvars, typval_T *rettv) +static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n; char_u buf[NUMBUFLEN]; @@ -11189,7 +10837,7 @@ static void f_histdel(typval_T *argvars, typval_T *rettv) /* * "histget()" function */ -static void f_histget(typval_T *argvars, typval_T *rettv) +static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType type; int idx; @@ -11214,7 +10862,7 @@ static void f_histget(typval_T *argvars, typval_T *rettv) /* * "histnr()" function */ -static void f_histnr(typval_T *argvars, typval_T *rettv) +static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int i; @@ -11233,7 +10881,7 @@ static void f_histnr(typval_T *argvars, typval_T *rettv) /* * "highlightID(name)" function */ -static void f_hlID(typval_T *argvars, typval_T *rettv) +static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = syn_name2id(get_tv_string(&argvars[0])); } @@ -11241,7 +10889,7 @@ static void f_hlID(typval_T *argvars, typval_T *rettv) /* * "highlight_exists()" function */ -static void f_hlexists(typval_T *argvars, typval_T *rettv) +static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = highlight_exists(get_tv_string(&argvars[0])); } @@ -11249,7 +10897,7 @@ static void f_hlexists(typval_T *argvars, typval_T *rettv) /* * "hostname()" function */ -static void f_hostname(typval_T *argvars, typval_T *rettv) +static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char hostname[256]; @@ -11261,7 +10909,7 @@ static void f_hostname(typval_T *argvars, typval_T *rettv) /* * iconv() function */ -static void f_iconv(typval_T *argvars, typval_T *rettv) +static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf1[NUMBUFLEN]; char_u buf2[NUMBUFLEN]; @@ -11291,7 +10939,7 @@ static void f_iconv(typval_T *argvars, typval_T *rettv) /* * "indent()" function */ -static void f_indent(typval_T *argvars, typval_T *rettv) +static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -11305,7 +10953,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv) /* * "index()" function */ -static void f_index(typval_T *argvars, typval_T *rettv) +static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; listitem_T *item; @@ -11436,7 +11084,7 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) * "input()" function * Also handles inputsecret() when inputsecret is set. */ -static void f_input(typval_T *argvars, typval_T *rettv) +static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_user_input(argvars, rettv, FALSE); } @@ -11444,7 +11092,7 @@ static void f_input(typval_T *argvars, typval_T *rettv) /* * "inputdialog()" function */ -static void f_inputdialog(typval_T *argvars, typval_T *rettv) +static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_user_input(argvars, rettv, TRUE); } @@ -11452,7 +11100,7 @@ static void f_inputdialog(typval_T *argvars, typval_T *rettv) /* * "inputlist()" function */ -static void f_inputlist(typval_T *argvars, typval_T *rettv) +static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { listitem_T *li; int selected; @@ -11488,7 +11136,7 @@ static garray_T ga_userinput = {0, 0, sizeof(tasave_T), 4, NULL}; /* * "inputrestore()" function */ -static void f_inputrestore(typval_T *argvars, typval_T *rettv) +static void f_inputrestore(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (!GA_EMPTY(&ga_userinput)) { --ga_userinput.ga_len; @@ -11504,7 +11152,7 @@ static void f_inputrestore(typval_T *argvars, typval_T *rettv) /* * "inputsave()" function */ -static void f_inputsave(typval_T *argvars, typval_T *rettv) +static void f_inputsave(typval_T *argvars, typval_T *rettv, FunPtr fptr) { // Add an entry to the stack of typeahead storage. tasave_T *p = GA_APPEND_VIA_PTR(tasave_T, &ga_userinput); @@ -11514,19 +11162,19 @@ static void f_inputsave(typval_T *argvars, typval_T *rettv) /* * "inputsecret()" function */ -static void f_inputsecret(typval_T *argvars, typval_T *rettv) +static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - ++cmdline_star; - ++inputsecret_flag; - f_input(argvars, rettv); - --cmdline_star; - --inputsecret_flag; + cmdline_star++; + inputsecret_flag++; + f_input(argvars, rettv, NULL); + cmdline_star--; + inputsecret_flag--; } /* * "insert()" function */ -static void f_insert(typval_T *argvars, typval_T *rettv) +static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long before = 0; listitem_T *item; @@ -11565,7 +11213,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv) /* * "invert(expr)" function */ -static void f_invert(typval_T *argvars, typval_T *rettv) +static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ~get_tv_number_chk(&argvars[0], NULL); } @@ -11573,7 +11221,7 @@ static void f_invert(typval_T *argvars, typval_T *rettv) /* * "isdirectory()" function */ -static void f_isdirectory(typval_T *argvars, typval_T *rettv) +static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = os_isdir(get_tv_string(&argvars[0])); } @@ -11581,7 +11229,7 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv) /* * "islocked()" function */ -static void f_islocked(typval_T *argvars, typval_T *rettv) +static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) { lval_T lv; char_u *end; @@ -11693,13 +11341,13 @@ static void dict_list(typval_T *argvars, typval_T *rettv, int what) /* * "items(dict)" function */ -static void f_items(typval_T *argvars, typval_T *rettv) +static void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 2); } // "jobclose(id[, stream])" function -static void f_jobclose(typval_T *argvars, typval_T *rettv) +static void f_jobclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -11758,7 +11406,7 @@ static void f_jobclose(typval_T *argvars, typval_T *rettv) } // "jobpid(id)" function -static void f_jobpid(typval_T *argvars, typval_T *rettv) +static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -11783,7 +11431,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv) } // "jobsend()" function -static void f_jobsend(typval_T *argvars, typval_T *rettv) +static void f_jobsend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -11828,7 +11476,7 @@ static void f_jobsend(typval_T *argvars, typval_T *rettv) } // "jobresize(job, width, height)" function -static void f_jobresize(typval_T *argvars, typval_T *rettv) +static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -11915,7 +11563,7 @@ static char **tv_to_argv(typval_T *cmd_tv, char **cmd) } // "jobstart()" function -static void f_jobstart(typval_T *argvars, typval_T *rettv) +static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -11999,7 +11647,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv) } // "jobstop()" function -static void f_jobstop(typval_T *argvars, typval_T *rettv) +static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -12027,7 +11675,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv) } // "jobwait(ids[, timeout])" function -static void f_jobwait(typval_T *argvars, typval_T *rettv) +static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -12137,7 +11785,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv) /* * "join()" function */ -static void f_join(typval_T *argvars, typval_T *rettv) +static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; char_u *sep; @@ -12165,7 +11813,7 @@ static void f_join(typval_T *argvars, typval_T *rettv) } /// json_decode() function -static void f_json_decode(typval_T *argvars, typval_T *rettv) +static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char numbuf[NUMBUFLEN]; char *s = NULL; @@ -12199,7 +11847,7 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv) } /// json_encode() function -static void f_json_encode(typval_T *argvars, typval_T *rettv) +static void f_json_encode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = (char_u *) encode_tv2json(&argvars[0], NULL); @@ -12208,7 +11856,7 @@ static void f_json_encode(typval_T *argvars, typval_T *rettv) /* * "keys()" function */ -static void f_keys(typval_T *argvars, typval_T *rettv) +static void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 0); } @@ -12216,7 +11864,7 @@ static void f_keys(typval_T *argvars, typval_T *rettv) /* * "last_buffer_nr()" function. */ -static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv) +static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n = 0; @@ -12232,7 +11880,7 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv) /* * "len()" function */ -static void f_len(typval_T *argvars, typval_T *rettv) +static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) { switch (argvars[0].v_type) { case VAR_STRING: @@ -12303,7 +11951,7 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) /* * "libcall()" function */ -static void f_libcall(typval_T *argvars, typval_T *rettv) +static void f_libcall(typval_T *argvars, typval_T *rettv, FunPtr fptr) { libcall_common(argvars, rettv, VAR_STRING); } @@ -12311,7 +11959,7 @@ static void f_libcall(typval_T *argvars, typval_T *rettv) /* * "libcallnr()" function */ -static void f_libcallnr(typval_T *argvars, typval_T *rettv) +static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { libcall_common(argvars, rettv, VAR_NUMBER); } @@ -12319,7 +11967,7 @@ static void f_libcallnr(typval_T *argvars, typval_T *rettv) /* * "line(string)" function */ -static void f_line(typval_T *argvars, typval_T *rettv) +static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = 0; pos_T *fp; @@ -12334,7 +11982,7 @@ static void f_line(typval_T *argvars, typval_T *rettv) /* * "line2byte(lnum)" function */ -static void f_line2byte(typval_T *argvars, typval_T *rettv) +static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -12350,7 +11998,7 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv) /* * "lispindent(lnum)" function */ -static void f_lispindent(typval_T *argvars, typval_T *rettv) +static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; linenr_T lnum; @@ -12368,7 +12016,7 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv) /* * "localtime()" function */ -static void f_localtime(typval_T *argvars, typval_T *rettv) +static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (varnumber_T)time(NULL); } @@ -12444,26 +12092,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) } /* - * "log()" function - */ -static void f_log(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &log); -} - -/* - * "log10()" function - */ -static void f_log10(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &log10); -} - - -/* * "map()" function */ -static void f_map(typval_T *argvars, typval_T *rettv) +static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr) { filter_map(argvars, rettv, TRUE); } @@ -12471,7 +12102,7 @@ static void f_map(typval_T *argvars, typval_T *rettv) /* * "maparg()" function */ -static void f_maparg(typval_T *argvars, typval_T *rettv) +static void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_maparg(argvars, rettv, TRUE); } @@ -12479,7 +12110,7 @@ static void f_maparg(typval_T *argvars, typval_T *rettv) /* * "mapcheck()" function */ -static void f_mapcheck(typval_T *argvars, typval_T *rettv) +static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_maparg(argvars, rettv, FALSE); } @@ -12644,7 +12275,7 @@ theend: /* * "match()" function */ -static void f_match(typval_T *argvars, typval_T *rettv) +static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, 1); } @@ -12652,7 +12283,7 @@ static void f_match(typval_T *argvars, typval_T *rettv) /* * "matchadd()" function */ -static void f_matchadd(typval_T *argvars, typval_T *rettv) +static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; char_u *grp = get_tv_string_buf_chk(&argvars[0], buf); /* group */ @@ -12695,7 +12326,7 @@ static void f_matchadd(typval_T *argvars, typval_T *rettv) conceal_char); } -static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL +static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -12756,7 +12387,7 @@ static void f_matchaddpos(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ /* * "matcharg()" function */ -static void f_matcharg(typval_T *argvars, typval_T *rettv) +static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv_list_alloc(rettv); @@ -12778,7 +12409,7 @@ static void f_matcharg(typval_T *argvars, typval_T *rettv) /* * "matchdelete()" function */ -static void f_matchdelete(typval_T *argvars, typval_T *rettv) +static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = match_delete(curwin, (int)get_tv_number(&argvars[0]), TRUE); @@ -12787,7 +12418,7 @@ static void f_matchdelete(typval_T *argvars, typval_T *rettv) /* * "matchend()" function */ -static void f_matchend(typval_T *argvars, typval_T *rettv) +static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, 0); } @@ -12795,7 +12426,7 @@ static void f_matchend(typval_T *argvars, typval_T *rettv) /* * "matchlist()" function */ -static void f_matchlist(typval_T *argvars, typval_T *rettv) +static void f_matchlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, 3); } @@ -12803,7 +12434,7 @@ static void f_matchlist(typval_T *argvars, typval_T *rettv) /* * "matchstr()" function */ -static void f_matchstr(typval_T *argvars, typval_T *rettv) +static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, 2); } @@ -12863,7 +12494,7 @@ static void max_min(typval_T *argvars, typval_T *rettv, int domax) /* * "max()" function */ -static void f_max(typval_T *argvars, typval_T *rettv) +static void f_max(typval_T *argvars, typval_T *rettv, FunPtr fptr) { max_min(argvars, rettv, TRUE); } @@ -12871,7 +12502,7 @@ static void f_max(typval_T *argvars, typval_T *rettv) /* * "min()" function */ -static void f_min(typval_T *argvars, typval_T *rettv) +static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr) { max_min(argvars, rettv, FALSE); } @@ -12879,7 +12510,7 @@ static void f_min(typval_T *argvars, typval_T *rettv) /* * "mkdir()" function */ -static void f_mkdir(typval_T *argvars, typval_T *rettv) +static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *dir; char_u buf[NUMBUFLEN]; @@ -12921,7 +12552,7 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv) /* * "mode()" function */ -static void f_mode(typval_T *argvars, typval_T *rettv) +static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[3]; @@ -12975,7 +12606,7 @@ static void f_mode(typval_T *argvars, typval_T *rettv) } /// "msgpackdump()" function -static void f_msgpackdump(typval_T *argvars, typval_T *rettv) +static void f_msgpackdump(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { if (argvars[0].v_type != VAR_LIST) { @@ -13003,7 +12634,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv) } /// "msgpackparse" function -static void f_msgpackparse(typval_T *argvars, typval_T *rettv) +static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { if (argvars[0].v_type != VAR_LIST) { @@ -13084,7 +12715,7 @@ f_msgpackparse_exit: /* * "nextnonblank()" function */ -static void f_nextnonblank(typval_T *argvars, typval_T *rettv) +static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -13102,7 +12733,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv) /* * "nr2char()" function */ -static void f_nr2char(typval_T *argvars, typval_T *rettv) +static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; @@ -13126,7 +12757,7 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv) /* * "or(expr, expr)" function */ -static void f_or(typval_T *argvars, typval_T *rettv) +static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) | get_tv_number_chk(&argvars[1], NULL); @@ -13135,7 +12766,7 @@ static void f_or(typval_T *argvars, typval_T *rettv) /* * "pathshorten()" function */ -static void f_pathshorten(typval_T *argvars, typval_T *rettv) +static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = get_tv_string_chk(&argvars[0]); @@ -13148,7 +12779,7 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv) /* * "pow()" function */ -static void f_pow(typval_T *argvars, typval_T *rettv) +static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx, fy; @@ -13163,7 +12794,7 @@ static void f_pow(typval_T *argvars, typval_T *rettv) /* * "prevnonblank()" function */ -static void f_prevnonblank(typval_T *argvars, typval_T *rettv) +static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -13185,7 +12816,7 @@ static va_list ap; /* * "printf()" function */ -static void f_printf(typval_T *argvars, typval_T *rettv) +static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; @@ -13211,7 +12842,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv) /* * "pumvisible()" function */ -static void f_pumvisible(typval_T *argvars, typval_T *rettv) +static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (pum_visible()) rettv->vval.v_number = 1; @@ -13220,7 +12851,7 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv) /* * "pyeval()" function */ -static void f_pyeval(typval_T *argvars, typval_T *rettv) +static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { script_host_eval("python", argvars, rettv); } @@ -13228,7 +12859,7 @@ static void f_pyeval(typval_T *argvars, typval_T *rettv) /* * "py3eval()" function */ -static void f_py3eval(typval_T *argvars, typval_T *rettv) +static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { script_host_eval("python3", argvars, rettv); } @@ -13236,7 +12867,7 @@ static void f_py3eval(typval_T *argvars, typval_T *rettv) /* * "range()" function */ -static void f_range(typval_T *argvars, typval_T *rettv) +static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long start; long end; @@ -13271,7 +12902,7 @@ static void f_range(typval_T *argvars, typval_T *rettv) /* * "readfile()" function */ -static void f_readfile(typval_T *argvars, typval_T *rettv) +static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int binary = FALSE; char_u *fname; @@ -13470,7 +13101,7 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL /// one argument it returns the time passed since the argument. /// With two arguments it returns the time passed between /// the two arguments. -static void f_reltime(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL +static void f_reltime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { proftime_T res; proftime_T start; @@ -13516,7 +13147,7 @@ static void f_reltime(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL /// @return The string representation of the argument, the format is the /// number of seconds followed by a dot, followed by the number /// of microseconds. -static void f_reltimestr(typval_T *argvars, typval_T *rettv) +static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { proftime_T tm; @@ -13531,7 +13162,7 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv) /* * "remove()" function */ -static void f_remove(typval_T *argvars, typval_T *rettv) +static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; listitem_T *item, *item2; @@ -13616,7 +13247,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv) /* * "rename({from}, {to})" function */ -static void f_rename(typval_T *argvars, typval_T *rettv) +static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; @@ -13630,7 +13261,7 @@ static void f_rename(typval_T *argvars, typval_T *rettv) /* * "repeat()" function */ -static void f_repeat(typval_T *argvars, typval_T *rettv) +static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p; int n; @@ -13664,7 +13295,7 @@ static void f_repeat(typval_T *argvars, typval_T *rettv) /* * "resolve()" function */ -static void f_resolve(typval_T *argvars, typval_T *rettv) +static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p; #ifdef HAVE_READLINK @@ -13838,7 +13469,7 @@ fail: /* * "reverse({list})" function */ -static void f_reverse(typval_T *argvars, typval_T *rettv) +static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; listitem_T *li, *ni; @@ -14009,16 +13640,8 @@ theend: return retval; } -/* - * "round({float})" function - */ -static void f_round(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &round); -} - // "rpcnotify()" function -static void f_rpcnotify(typval_T *argvars, typval_T *rettv) +static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -14054,7 +13677,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv) } // "rpcrequest()" function -static void f_rpcrequest(typval_T *argvars, typval_T *rettv) +static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -14127,7 +13750,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv) } if (err.set) { - vim_report_error(cstr_as_string(err.msg)); + nvim_report_error(cstr_as_string(err.msg)); goto end; } @@ -14140,7 +13763,7 @@ end: } // "rpcstart()" function (DEPRECATED) -static void f_rpcstart(typval_T *argvars, typval_T *rettv) +static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; @@ -14199,8 +13822,15 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv) } // "rpcstop()" function -static void f_rpcstop(typval_T *argvars, typval_T *rettv) +static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = 0; + + if (check_restricted() || check_secure()) { + return; + } + if (argvars[0].v_type != VAR_NUMBER) { // Wrong argument types EMSG(_(e_invarg)); @@ -14209,7 +13839,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv) // if called with a job, stop it, else closes the channel if (pmap_get(uint64_t)(jobs, argvars[0].vval.v_number)) { - f_jobstop(argvars, rettv); + f_jobstop(argvars, rettv, NULL); } else { rettv->vval.v_number = channel_close(argvars[0].vval.v_number); } @@ -14218,7 +13848,7 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv) /* * "screenattr()" function */ -static void f_screenattr(typval_T *argvars, typval_T *rettv) +static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int row; int col; @@ -14237,7 +13867,7 @@ static void f_screenattr(typval_T *argvars, typval_T *rettv) /* * "screenchar()" function */ -static void f_screenchar(typval_T *argvars, typval_T *rettv) +static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int row; int col; @@ -14264,7 +13894,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv) * * First column is 1 to be consistent with virtcol(). */ -static void f_screencol(typval_T *argvars, typval_T *rettv) +static void f_screencol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ui_current_col() + 1; } @@ -14272,7 +13902,7 @@ static void f_screencol(typval_T *argvars, typval_T *rettv) /* * "screenrow()" function */ -static void f_screenrow(typval_T *argvars, typval_T *rettv) +static void f_screenrow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ui_current_row() + 1; } @@ -14280,7 +13910,7 @@ static void f_screenrow(typval_T *argvars, typval_T *rettv) /* * "search()" function */ -static void f_search(typval_T *argvars, typval_T *rettv) +static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int flags = 0; @@ -14290,7 +13920,7 @@ static void f_search(typval_T *argvars, typval_T *rettv) /* * "searchdecl()" function */ -static void f_searchdecl(typval_T *argvars, typval_T *rettv) +static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int locally = 1; int thisblock = 0; @@ -14383,7 +14013,7 @@ theend: /* * "searchpair()" function */ -static void f_searchpair(typval_T *argvars, typval_T *rettv) +static void f_searchpair(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = searchpair_cmn(argvars, NULL); } @@ -14391,7 +14021,7 @@ static void f_searchpair(typval_T *argvars, typval_T *rettv) /* * "searchpairpos()" function */ -static void f_searchpairpos(typval_T *argvars, typval_T *rettv) +static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T match_pos; int lnum = 0; @@ -14556,7 +14186,7 @@ do_searchpair ( /* * "searchpos()" function */ -static void f_searchpos(typval_T *argvars, typval_T *rettv) +static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T match_pos; int lnum = 0; @@ -14579,7 +14209,7 @@ static void f_searchpos(typval_T *argvars, typval_T *rettv) } /// "serverlist()" function -static void f_serverlist(typval_T *argvars, typval_T *rettv) +static void f_serverlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { size_t n; char **addrs = server_address_list(&n); @@ -14597,7 +14227,7 @@ static void f_serverlist(typval_T *argvars, typval_T *rettv) } /// "serverstart()" function -static void f_serverstart(typval_T *argvars, typval_T *rettv) +static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; // Address of the new server @@ -14625,7 +14255,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv) } /// "serverstop()" function -static void f_serverstop(typval_T *argvars, typval_T *rettv) +static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_restricted() || check_secure()) { return; @@ -14644,7 +14274,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv) /* * "setbufvar()" function */ -static void f_setbufvar(typval_T *argvars, typval_T *rettv) +static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; aco_save_T aco; @@ -14686,7 +14316,7 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv) } } -static void f_setcharsearch(typval_T *argvars, typval_T *rettv) +static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *d; dictitem_T *di; @@ -14723,7 +14353,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv) /* * "setcmdpos()" function */ -static void f_setcmdpos(typval_T *argvars, typval_T *rettv) +static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int pos = (int)get_tv_number(&argvars[0]) - 1; @@ -14733,7 +14363,7 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv) /// "setfperm({fname}, {mode})" function -static void f_setfperm(typval_T *argvars, typval_T *rettv) +static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; @@ -14766,7 +14396,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv) /* * "setline()" function */ -static void f_setline(typval_T *argvars, typval_T *rettv) +static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; char_u *line = NULL; @@ -14891,7 +14521,7 @@ skip_args: /* * "setloclist()" function */ -static void f_setloclist(typval_T *argvars, typval_T *rettv) +static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *win; @@ -14906,7 +14536,7 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv) /* * "setmatches()" function */ -static void f_setmatches(typval_T *argvars, typval_T *rettv) +static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; listitem_T *li; @@ -14997,7 +14627,7 @@ static void f_setmatches(typval_T *argvars, typval_T *rettv) /* * "setpos()" function */ -static void f_setpos(typval_T *argvars, typval_T *rettv) +static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; int fnum; @@ -15039,7 +14669,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv) /* * "setqflist()" function */ -static void f_setqflist(typval_T *argvars, typval_T *rettv) +static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { set_qf_ll_list(NULL, argvars, rettv); } @@ -15047,7 +14677,7 @@ static void f_setqflist(typval_T *argvars, typval_T *rettv) /* * "setreg()" function */ -static void f_setreg(typval_T *argvars, typval_T *rettv) +static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int regname; char_u *strregname; @@ -15142,7 +14772,7 @@ free_lstval: /* * "settabvar()" function */ -static void f_settabvar(typval_T *argvars, typval_T *rettv) +static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tabpage_T *save_curtab; tabpage_T *tp; @@ -15179,7 +14809,7 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv) /* * "settabwinvar()" function */ -static void f_settabwinvar(typval_T *argvars, typval_T *rettv) +static void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { setwinvar(argvars, rettv, 1); } @@ -15187,7 +14817,7 @@ static void f_settabwinvar(typval_T *argvars, typval_T *rettv) /* * "setwinvar()" function */ -static void f_setwinvar(typval_T *argvars, typval_T *rettv) +static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { setwinvar(argvars, rettv, 0); } @@ -15247,7 +14877,7 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) } /// f_sha256 - sha256({string}) function -static void f_sha256(typval_T *argvars, typval_T *rettv) +static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = get_tv_string(&argvars[0]); const char_u *hash = sha256_bytes(p, (int) STRLEN(p) , NULL, 0); @@ -15260,7 +14890,7 @@ static void f_sha256(typval_T *argvars, typval_T *rettv) /* * "shellescape({string})" function */ -static void f_shellescape(typval_T *argvars, typval_T *rettv) +static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = vim_strsave_shellescape( get_tv_string(&argvars[0]), non_zero_arg(&argvars[1]), true); @@ -15270,7 +14900,7 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv) /* * shiftwidth() function */ -static void f_shiftwidth(typval_T *argvars, typval_T *rettv) +static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_sw_value(curbuf); } @@ -15278,7 +14908,7 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv) /* * "simplify()" function */ -static void f_simplify(typval_T *argvars, typval_T *rettv) +static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p; @@ -15288,22 +14918,6 @@ static void f_simplify(typval_T *argvars, typval_T *rettv) rettv->v_type = VAR_STRING; } -/* - * "sin()" function - */ -static void f_sin(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &sin); -} - -/* - * "sinh()" function - */ -static void f_sinh(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &sinh); -} - /// struct used in the array that's given to qsort() typedef struct { listitem_T *item; @@ -15651,13 +15265,13 @@ theend: } /// "sort"({list})" function -static void f_sort(typval_T *argvars, typval_T *rettv) +static void f_sort(typval_T *argvars, typval_T *rettv, FunPtr fptr) { do_sort_uniq(argvars, rettv, true); } /// "uniq({list})" function -static void f_uniq(typval_T *argvars, typval_T *rettv) +static void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr) { do_sort_uniq(argvars, rettv, false); } @@ -15665,7 +15279,7 @@ static void f_uniq(typval_T *argvars, typval_T *rettv) // // "reltimefloat()" function // -static void f_reltimefloat(typval_T *argvars , typval_T *rettv) +static void f_reltimefloat(typval_T *argvars , typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { proftime_T tm; @@ -15680,7 +15294,7 @@ static void f_reltimefloat(typval_T *argvars , typval_T *rettv) /* * "soundfold({word})" function */ -static void f_soundfold(typval_T *argvars, typval_T *rettv) +static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s; @@ -15692,7 +15306,7 @@ static void f_soundfold(typval_T *argvars, typval_T *rettv) /* * "spellbadword()" function */ -static void f_spellbadword(typval_T *argvars, typval_T *rettv) +static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *word = (char_u *)""; hlf_T attr = HLF_COUNT; @@ -15736,7 +15350,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv) /* * "spellsuggest()" function */ -static void f_spellsuggest(typval_T *argvars, typval_T *rettv) +static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *str; int typeerr = FALSE; @@ -15776,7 +15390,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv) } } -static void f_split(typval_T *argvars, typval_T *rettv) +static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *str; char_u *end; @@ -15845,17 +15459,9 @@ static void f_split(typval_T *argvars, typval_T *rettv) } /* - * "sqrt()" function - */ -static void f_sqrt(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &sqrt); -} - -/* * "str2float()" function */ -static void f_str2float(typval_T *argvars, typval_T *rettv) +static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = skipwhite(get_tv_string(&argvars[0])); @@ -15866,7 +15472,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv) } // "str2nr()" function -static void f_str2nr(typval_T *argvars, typval_T *rettv) +static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int base = 10; char_u *p; @@ -15905,7 +15511,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv) /* * "strftime({format}[, {time}])" function */ -static void f_strftime(typval_T *argvars, typval_T *rettv) +static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u result_buf[256]; time_t seconds; @@ -15956,7 +15562,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv) /* * "stridx()" function */ -static void f_stridx(typval_T *argvars, typval_T *rettv) +static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; char_u *needle; @@ -15989,7 +15595,7 @@ static void f_stridx(typval_T *argvars, typval_T *rettv) /* * "string()" function */ -static void f_string(typval_T *argvars, typval_T *rettv) +static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = (char_u *) encode_tv2string(&argvars[0], NULL); @@ -15998,7 +15604,7 @@ static void f_string(typval_T *argvars, typval_T *rettv) /* * "strlen()" function */ -static void f_strlen(typval_T *argvars, typval_T *rettv) +static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (varnumber_T)(STRLEN( get_tv_string(&argvars[0]))); @@ -16007,7 +15613,7 @@ static void f_strlen(typval_T *argvars, typval_T *rettv) /* * "strchars()" function */ -static void f_strchars(typval_T *argvars, typval_T *rettv) +static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s = get_tv_string(&argvars[0]); int skipcc = 0; @@ -16032,7 +15638,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv) /* * "strdisplaywidth()" function */ -static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv) +static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s = get_tv_string(&argvars[0]); int col = 0; @@ -16046,7 +15652,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv) /* * "strwidth()" function */ -static void f_strwidth(typval_T *argvars, typval_T *rettv) +static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *s = get_tv_string(&argvars[0]); @@ -16056,7 +15662,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv) /* * "strpart()" function */ -static void f_strpart(typval_T *argvars, typval_T *rettv) +static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p; int n; @@ -16096,7 +15702,7 @@ static void f_strpart(typval_T *argvars, typval_T *rettv) /* * "strridx()" function */ -static void f_strridx(typval_T *argvars, typval_T *rettv) +static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u buf[NUMBUFLEN]; char_u *needle; @@ -16142,7 +15748,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv) /* * "strtrans()" function */ -static void f_strtrans(typval_T *argvars, typval_T *rettv) +static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = transstr(get_tv_string(&argvars[0])); @@ -16151,7 +15757,7 @@ static void f_strtrans(typval_T *argvars, typval_T *rettv) /* * "submatch()" function */ -static void f_submatch(typval_T *argvars, typval_T *rettv) +static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int error = FALSE; int no = (int)get_tv_number_chk(&argvars[0], &error); @@ -16180,7 +15786,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv) /* * "substitute()" function */ -static void f_substitute(typval_T *argvars, typval_T *rettv) +static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u patbuf[NUMBUFLEN]; char_u subbuf[NUMBUFLEN]; @@ -16201,7 +15807,7 @@ static void f_substitute(typval_T *argvars, typval_T *rettv) /* * "synID(lnum, col, trans)" function */ -static void f_synID(typval_T *argvars, typval_T *rettv) +static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int id = 0; long lnum; @@ -16223,7 +15829,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv) /* * "synIDattr(id, what [, mode])" function */ -static void f_synIDattr(typval_T *argvars, typval_T *rettv) +static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = NULL; int id; @@ -16299,7 +15905,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv) /* * "synIDtrans(id)" function */ -static void f_synIDtrans(typval_T *argvars, typval_T *rettv) +static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int id; @@ -16316,7 +15922,7 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv) /* * "synconcealed(lnum, col)" function */ -static void f_synconcealed(typval_T *argvars, typval_T *rettv) +static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long lnum; long col; @@ -16363,7 +15969,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv) /* * "synstack(lnum, col)" function */ -static void f_synstack(typval_T *argvars, typval_T *rettv) +static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long lnum; long col; @@ -16494,12 +16100,12 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, } /// f_system - the VimL system() function -static void f_system(typval_T *argvars, typval_T *rettv) +static void f_system(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_system_output_as_rettv(argvars, rettv, false); } -static void f_systemlist(typval_T *argvars, typval_T *rettv) +static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_system_output_as_rettv(argvars, rettv, true); } @@ -16508,7 +16114,7 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv) /* * "tabpagebuflist()" function */ -static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv) +static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tabpage_T *tp; win_T *wp = NULL; @@ -16533,7 +16139,7 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv) /* * "tabpagenr()" function */ -static void f_tabpagenr(typval_T *argvars, typval_T *rettv) +static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; char_u *arg; @@ -16597,7 +16203,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) /* * "tabpagewinnr()" function */ -static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv) +static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; tabpage_T *tp; @@ -16614,7 +16220,7 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv) /* * "tagfiles()" function */ -static void f_tagfiles(typval_T *argvars, typval_T *rettv) +static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *fname; tagname_T tn; @@ -16635,7 +16241,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv) /* * "taglist()" function */ -static void f_taglist(typval_T *argvars, typval_T *rettv) +static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *tag_pattern; @@ -16651,14 +16257,14 @@ static void f_taglist(typval_T *argvars, typval_T *rettv) /* * "tempname()" function */ -static void f_tempname(typval_T *argvars, typval_T *rettv) +static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = vim_tempname(); } // "termopen(cmd[, cwd])" function -static void f_termopen(typval_T *argvars, typval_T *rettv) +static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_restricted() || check_secure()) { return; @@ -16747,30 +16353,13 @@ static void f_termopen(typval_T *argvars, typval_T *rettv) /* * "test(list)" function: Just checking the walls... */ -static void f_test(typval_T *argvars, typval_T *rettv) +static void f_test(typval_T *argvars, typval_T *rettv, FunPtr fptr) { /* Used for unit testing. Change the code below to your liking. */ } -/* - * "tan()" function - */ -static void f_tan(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &tan); -} - -/* - * "tanh()" function - */ -static void f_tanh(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &tanh); -} - - /// "timer_start(timeout, callback, opts)" function -static void f_timer_start(typval_T *argvars, typval_T *rettv) +static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long timeout = get_tv_number(&argvars[0]); timer_T *timer; @@ -16825,7 +16414,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv) // "timer_stop(timerid)" function -static void f_timer_stop(typval_T *argvars, typval_T *rettv) +static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_NUMBER) { EMSG(_(e_number_exp)); @@ -16914,7 +16503,7 @@ void timer_teardown(void) /* * "tolower(string)" function */ -static void f_tolower(typval_T *argvars, typval_T *rettv) +static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *p = vim_strsave(get_tv_string(&argvars[0])); rettv->v_type = VAR_STRING; @@ -16945,7 +16534,7 @@ static void f_tolower(typval_T *argvars, typval_T *rettv) /* * "toupper(string)" function */ -static void f_toupper(typval_T *argvars, typval_T *rettv) +static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = strup_save(get_tv_string(&argvars[0])); @@ -16954,7 +16543,7 @@ static void f_toupper(typval_T *argvars, typval_T *rettv) /* * "tr(string, fromstr, tostr)" function */ -static void f_tr(typval_T *argvars, typval_T *rettv) +static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *in_str; char_u *fromstr; @@ -17052,17 +16641,9 @@ error: } /* - * "trunc({float})" function - */ -static void f_trunc(typval_T *argvars, typval_T *rettv) -{ - float_op_wrapper(argvars, rettv, &trunc); -} - -/* * "type(expr)" function */ -static void f_type(typval_T *argvars, typval_T *rettv) +static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n = -1; @@ -17098,7 +16679,7 @@ static void f_type(typval_T *argvars, typval_T *rettv) /* * "undofile(name)" function */ -static void f_undofile(typval_T *argvars, typval_T *rettv) +static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; { @@ -17121,7 +16702,7 @@ static void f_undofile(typval_T *argvars, typval_T *rettv) /* * "undotree()" function */ -static void f_undotree(typval_T *argvars, typval_T *rettv) +static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv_dict_alloc(rettv); @@ -17144,7 +16725,7 @@ static void f_undotree(typval_T *argvars, typval_T *rettv) /* * "values(dict)" function */ -static void f_values(typval_T *argvars, typval_T *rettv) +static void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 1); } @@ -17152,7 +16733,7 @@ static void f_values(typval_T *argvars, typval_T *rettv) /* * "virtcol(string)" function */ -static void f_virtcol(typval_T *argvars, typval_T *rettv) +static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { colnr_T vcol = 0; pos_T *fp; @@ -17171,7 +16752,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv) /* * "visualmode()" function */ -static void f_visualmode(typval_T *argvars, typval_T *rettv) +static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u str[2]; @@ -17188,26 +16769,26 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv) /* * "wildmenumode()" function */ -static void f_wildmenumode(typval_T *argvars, typval_T *rettv) +static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (wild_menu_showing) rettv->vval.v_number = 1; } /// "win_getid()" function -static void f_win_getid(typval_T *argvars, typval_T *rettv) +static void f_win_getid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = win_getid(argvars); } /// "win_gotoid()" function -static void f_win_gotoid(typval_T *argvars, typval_T *rettv) +static void f_win_gotoid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = win_gotoid(argvars); } /// "win_id2tabwin()" function -static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv) +static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (rettv_list_alloc(rettv) != FAIL) { win_id2tabwin(argvars, rettv->vval.v_list); @@ -17215,7 +16796,7 @@ static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv) } /// "win_id2win()" function -static void f_win_id2win(typval_T *argvars, typval_T *rettv) +static void f_win_id2win(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = win_id2win(argvars); } @@ -17223,7 +16804,7 @@ static void f_win_id2win(typval_T *argvars, typval_T *rettv) /* * "winbufnr(nr)" function */ -static void f_winbufnr(typval_T *argvars, typval_T *rettv) +static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp; @@ -17237,7 +16818,7 @@ static void f_winbufnr(typval_T *argvars, typval_T *rettv) /* * "wincol()" function */ -static void f_wincol(typval_T *argvars, typval_T *rettv) +static void f_wincol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { validate_cursor(); rettv->vval.v_number = curwin->w_wcol + 1; @@ -17246,7 +16827,7 @@ static void f_wincol(typval_T *argvars, typval_T *rettv) /* * "winheight(nr)" function */ -static void f_winheight(typval_T *argvars, typval_T *rettv) +static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp; @@ -17260,7 +16841,7 @@ static void f_winheight(typval_T *argvars, typval_T *rettv) /* * "winline()" function */ -static void f_winline(typval_T *argvars, typval_T *rettv) +static void f_winline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { validate_cursor(); rettv->vval.v_number = curwin->w_wrow + 1; @@ -17269,7 +16850,7 @@ static void f_winline(typval_T *argvars, typval_T *rettv) /* * "winnr()" function */ -static void f_winnr(typval_T *argvars, typval_T *rettv) +static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; @@ -17280,7 +16861,7 @@ static void f_winnr(typval_T *argvars, typval_T *rettv) /* * "winrestcmd()" function */ -static void f_winrestcmd(typval_T *argvars, typval_T *rettv) +static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int winnr = 1; garray_T ga; @@ -17303,7 +16884,7 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv) /* * "winrestview()" function */ -static void f_winrestview(typval_T *argvars, typval_T *rettv) +static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; @@ -17353,7 +16934,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv) /* * "winsaveview()" function */ -static void f_winsaveview(typval_T *argvars, typval_T *rettv) +static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; @@ -17457,7 +17038,7 @@ static char_u *save_tv_as_string(typval_T *tv, ssize_t *len, bool endnl) /* * "winwidth(nr)" function */ -static void f_winwidth(typval_T *argvars, typval_T *rettv) +static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp; @@ -17469,14 +17050,14 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv) } /// "wordcount()" function -static void f_wordcount(typval_T *argvars, typval_T *rettv) +static void f_wordcount(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv_dict_alloc(rettv); cursor_pos_info(rettv->vval.v_dict); } /// "writefile()" function -static void f_writefile(typval_T *argvars, typval_T *rettv) +static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; // Assuming success. @@ -17521,7 +17102,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv) /* * "xor(expr, expr)" function */ -static void f_xor(typval_T *argvars, typval_T *rettv) +static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_tv_number_chk(&argvars[0], NULL) ^ get_tv_number_chk(&argvars[1], NULL); @@ -18603,7 +18184,7 @@ static linenr_T get_tv_lnum(typval_T *argvars) lnum = get_tv_number_chk(&argvars[0], NULL); if (lnum == 0) { /* no valid number, try using line() */ rettv.v_type = VAR_NUMBER; - f_line(argvars, &rettv); + f_line(argvars, &rettv, NULL); lnum = rettv.vval.v_number; clear_tv(&rettv); } @@ -20431,7 +20012,7 @@ void free_all_functions(void) int translated_function_exists(char_u *name) { if (builtin_function(name, -1)) { - return find_internal_func(name) >= 0; + return find_internal_func((char *)name) != NULL; } return find_func(name) != NULL; } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua new file mode 100644 index 0000000000..9a3d73736f --- /dev/null +++ b/src/nvim/eval.lua @@ -0,0 +1,330 @@ +-- File containing table with all functions. +-- +-- Keys: +-- +-- args Number of arguments, list with maximum and minimum number of arguments +-- or list with a minimum number of arguments only. Defaults to zero +-- arguments. +-- func Name of the C function which implements the VimL function. Defaults to +-- `f_{funcname}`. + +local varargs = function(nr) + return {nr} +end + +return { + funcs={ + abs={args=1}, + acos={args=1, func="float_op_wrapper", data="&acos"}, -- WJMc + add={args=2}, + ['and']={args=2}, + api_info={}, + append={args=2}, + argc={}, + argidx={}, + arglistid={args={0, 2}}, + argv={args={0, 1}}, + asin={args=1, func="float_op_wrapper", data="&asin"}, -- WJMc + assert_equal={args={2, 3}}, + assert_exception={args={1, 2}}, + assert_fails={args={1, 2}}, + assert_false={args={1, 2}}, + assert_match={args={2, 3}}, + assert_notequal={args={2, 3}}, + assert_notmatch={args={2, 3}}, + assert_true={args={1, 2}}, + atan={args=1, func="float_op_wrapper", data="&atan"}, + atan2={args=2}, + browse={args=4}, + browsedir={args=2}, + bufexists={args=1}, + buffer_exists={args=1, func='f_bufexists'}, -- obsolete + buffer_name={args=1, func='f_bufname'}, -- obsolete + buffer_number={args=1, func='f_bufnr'}, -- obsolete + buflisted={args=1}, + bufloaded={args=1}, + bufname={args=1}, + bufnr={args={1, 2}}, + bufwinnr={args=1}, + byte2line={args=1}, + byteidx={args=2}, + byteidxcomp={args=2}, + call={args={2, 3}}, + ceil={args=1, func="float_op_wrapper", data="&ceil"}, + changenr={}, + char2nr={args={1, 2}}, + cindent={args=1}, + clearmatches={}, + col={args=1}, + complete={args=2}, + complete_add={args=1}, + complete_check={}, + confirm={args={1, 4}}, + copy={args=1}, + cos={args=1, func="float_op_wrapper", data="&cos"}, + cosh={args=1, func="float_op_wrapper", data="&cosh"}, + count={args={2, 4}}, + cscope_connection={args={0, 3}}, + cursor={args={1, 3}}, + deepcopy={args={1, 2}}, + delete={args={1,2}}, + dictwatcheradd={args=3}, + dictwatcherdel={args=3}, + did_filetype={}, + diff_filler={args=1}, + diff_hlID={args=2}, + empty={args=1}, + escape={args=2}, + eval={args=1}, + eventhandler={}, + executable={args=1}, + execute={args=1}, + exepath={args=1}, + exists={args=1}, + exp={args=1, func="float_op_wrapper", data="&exp"}, + expand={args={1, 3}}, + extend={args={2, 3}}, + feedkeys={args={1, 2}}, + file_readable={args=1, func='f_filereadable'}, -- obsolete + filereadable={args=1}, + filewritable={args=1}, + filter={args=2}, + finddir={args={1, 3}}, + findfile={args={1, 3}}, + float2nr={args=1}, + floor={args=1, func="float_op_wrapper", data="&floor"}, + fmod={args=2}, + fnameescape={args=1}, + fnamemodify={args=2}, + foldclosed={args=1}, + foldclosedend={args=1}, + foldlevel={args=1}, + foldtext={}, + foldtextresult={args=1}, + foreground={}, + ['function']={args=1}, + garbagecollect={args={0, 1}}, + get={args={2, 3}}, + getbufline={args={2, 3}}, + getbufvar={args={2, 3}}, + getchar={args={0, 1}}, + getcharmod={}, + getcharsearch={}, + getcmdline={}, + getcmdpos={}, + getcmdtype={}, + getcmdwintype={}, + getcompletion={args=2}, + getcurpos={}, + getcwd={args={0,2}}, + getfontname={args={0, 1}}, + getfperm={args=1}, + getfsize={args=1}, + getftime={args=1}, + getftype={args=1}, + getline={args={1, 2}}, + getloclist={args=1, func='f_getqflist'}, + getmatches={}, + getpid={}, + getpos={args=1}, + getqflist={}, + getreg={args={0, 3}}, + getregtype={args={0, 1}}, + gettabvar={args={2, 3}}, + gettabwinvar={args={3, 4}}, + getwinposx={}, + getwinposy={}, + getwinvar={args={2, 3}}, + glob={args={1, 4}}, + glob2regpat={args=1}, + globpath={args={2, 5}}, + has={args=1}, + has_key={args=2}, + haslocaldir={args={0,2}}, + hasmapto={args={1, 3}}, + highlightID={args=1, func='f_hlID'}, -- obsolete + highlight_exists={args=1, func='f_hlexists'}, -- obsolete + histadd={args=2}, + histdel={args={1, 2}}, + histget={args={1, 2}}, + histnr={args=1}, + hlID={args=1}, + hlexists={args=1}, + hostname={}, + iconv={args=3}, + indent={args=1}, + index={args={2, 4}}, + input={args={1, 3}}, + inputdialog={args={1, 3}}, + inputlist={args=1}, + inputrestore={}, + inputsave={}, + inputsecret={args={1, 2}}, + insert={args={2, 3}}, + invert={args=1}, + isdirectory={args=1}, + islocked={args=1}, + items={args=1}, + jobclose={args={1, 2}}, + jobpid={args=1}, + jobresize={args=3}, + jobsend={args=2}, + jobstart={args={1, 2}}, + jobstop={args=1}, + jobwait={args={1, 2}}, + join={args={1, 2}}, + json_decode={args=1}, + json_encode={args=1}, + keys={args=1}, + last_buffer_nr={}, -- obsolete + len={args=1}, + libcall={args=3}, + libcallnr={args=3}, + line={args=1}, + line2byte={args=1}, + lispindent={args=1}, + localtime={}, + log={args=1, func="float_op_wrapper", data="&log"}, + log10={args=1, func="float_op_wrapper", data="&log10"}, + map={args=2}, + maparg={args={1, 4}}, + mapcheck={args={1, 3}}, + match={args={2, 4}}, + matchadd={args={2, 5}}, + matchaddpos={args={2, 5}}, + matcharg={args=1}, + matchdelete={args=1}, + matchend={args={2, 4}}, + matchlist={args={2, 4}}, + matchstr={args={2, 4}}, + max={args=1}, + min={args=1}, + mkdir={args={1, 3}}, + mode={args={0, 1}}, + msgpackdump={args=1}, + msgpackparse={args=1}, + nextnonblank={args=1}, + nr2char={args={1, 2}}, + ['or']={args=2}, + pathshorten={args=1}, + pow={args=2}, + prevnonblank={args=1}, + printf={args=varargs(2)}, + pumvisible={}, + py3eval={args=1}, + pyeval={args=1}, + range={args={1, 3}}, + readfile={args={1, 3}}, + reltime={args={0, 2}}, + reltimefloat={args=1}, + reltimestr={args=1}, + remove={args={2, 3}}, + rename={args=2}, + ['repeat']={args=2}, + resolve={args=1}, + reverse={args=1}, + round={args=1, func="float_op_wrapper", data="&round"}, + rpcnotify={args=varargs(2)}, + rpcrequest={args=varargs(2)}, + rpcstart={args={1, 2}}, + rpcstop={args=1}, + screenattr={args=2}, + screenchar={args=2}, + screencol={}, + screenrow={}, + search={args={1, 4}}, + searchdecl={args={1, 3}}, + searchpair={args={3, 7}}, + searchpairpos={args={3, 7}}, + searchpos={args={1, 4}}, + serverlist={}, + serverstart={args={0, 1}}, + serverstop={args=1}, + setbufvar={args=3}, + setcharsearch={args=1}, + setcmdpos={args=1}, + setfperm={args=2}, + setline={args=2}, + setloclist={args={2, 4}}, + setmatches={args=1}, + setpos={args=2}, + setqflist={args={1, 3}}, + setreg={args={2, 3}}, + settabvar={args=3}, + settabwinvar={args=4}, + setwinvar={args=3}, + sha256={args=1}, + shellescape={args={1, 2}}, + shiftwidth={}, + simplify={args=1}, + sin={args=1, func="float_op_wrapper", data="&sin"}, + sinh={args=1, func="float_op_wrapper", data="&sinh"}, + sort={args={1, 3}}, + soundfold={args=1}, + spellbadword={args={0, 1}}, + spellsuggest={args={1, 3}}, + split={args={1, 3}}, + sqrt={args=1, func="float_op_wrapper", data="&sqrt"}, + str2float={args=1}, + str2nr={args={1, 2}}, + strchars={args={1,2}}, + strdisplaywidth={args={1, 2}}, + strftime={args={1, 2}}, + stridx={args={2, 3}}, + string={args=1}, + strlen={args=1}, + strpart={args={2, 3}}, + strridx={args={2, 3}}, + strtrans={args=1}, + strwidth={args=1}, + submatch={args={1, 2}}, + substitute={args=4}, + synID={args=3}, + synIDattr={args={2, 3}}, + synIDtrans={args=1}, + synconcealed={args=2}, + synstack={args=2}, + system={args={1, 2}}, + systemlist={args={1, 3}}, + tabpagebuflist={args={0, 1}}, + tabpagenr={args={0, 1}}, + tabpagewinnr={args={1, 2}}, + tagfiles={}, + taglist={args=1}, + tan={args=1, func="float_op_wrapper", data="&tan"}, + tanh={args=1, func="float_op_wrapper", data="&tanh"}, + tempname={}, + termopen={args={1, 2}}, + test={args=1}, + timer_start={args={2,3}}, + timer_stop={args=1}, + tolower={args=1}, + toupper={args=1}, + tr={args=3}, + trunc={args=1, func="float_op_wrapper", data="&trunc"}, + type={args=1}, + undofile={args=1}, + undotree={}, + uniq={args={1, 3}}, + values={args=1}, + virtcol={args=1}, + visualmode={args={0, 1}}, + wildmenumode={}, + win_getid={args={0,2}}, + win_gotoid={args=1}, + win_id2tabwin={args=1}, + win_id2win={args=1}, + winbufnr={args=1}, + wincol={}, + winheight={args=1}, + winline={}, + winnr={args={0, 1}}, + winrestcmd={}, + winrestview={args=1}, + winsaveview={}, + winwidth={args=1}, + wordcount={}, + writefile={args={2, 3}}, + xor={args=2}, + }, +} diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h index ea017ab0c8..d98fe5b22b 100644 --- a/src/nvim/func_attr.h +++ b/src/nvim/func_attr.h @@ -185,6 +185,7 @@ #ifdef DEFINE_FUNC_ATTRIBUTES # define FUNC_API_ASYNC # define FUNC_API_NOEXPORT +# define FUNC_API_NOEVAL # define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC # define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x) # define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y) diff --git a/src/nvim/main.c b/src/nvim/main.c index b5c51e3444..aa1cddc6ed 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -58,13 +58,13 @@ #include "nvim/event/loop.h" #include "nvim/os/signal.h" #include "nvim/event/process.h" -#include "nvim/msgpack_rpc/defs.h" #include "nvim/msgpack_rpc/helpers.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" #include "nvim/api/private/handle.h" +#include "nvim/api/private/dispatch.h" /* Maximum number of commands from + or -c arguments. */ #define MAX_ARG_CMDS 10 diff --git a/src/nvim/map.c b/src/nvim/map.c index 398e74268f..73af487f90 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -6,7 +6,7 @@ #include "nvim/map_defs.h" #include "nvim/vim.h" #include "nvim/memory.h" -#include "nvim/msgpack_rpc/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/lib/khash.h" @@ -20,6 +20,8 @@ #define int_eq kh_int_hash_equal #define linenr_T_hash kh_int_hash_func #define linenr_T_eq kh_int_hash_equal +#define handle_T_hash kh_int_hash_func +#define handle_T_eq kh_int_hash_equal #if defined(ARCH_64) @@ -141,7 +143,8 @@ MAP_IMPL(cstr_t, uint64_t, DEFAULT_INITIALIZER) MAP_IMPL(cstr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER) MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER) -#define MSGPACK_HANDLER_INITIALIZER {.fn = NULL, .async = false} +MAP_IMPL(handle_T, ptr_t, DEFAULT_INITIALIZER) +#define MSGPACK_HANDLER_INITIALIZER { .fn = NULL, .async = false } MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER) #define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL } MAP_IMPL(linenr_T, bufhl_vec_T, KVEC_INITIALIZER) diff --git a/src/nvim/map.h b/src/nvim/map.h index c7d9894bd1..ba3e84cb31 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -5,7 +5,7 @@ #include "nvim/map_defs.h" #include "nvim/api/private/defs.h" -#include "nvim/msgpack_rpc/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/bufhl_defs.h" #define MAP_DECLS(T, U) \ @@ -29,6 +29,7 @@ MAP_DECLS(cstr_t, uint64_t) MAP_DECLS(cstr_t, ptr_t) MAP_DECLS(ptr_t, ptr_t) MAP_DECLS(uint64_t, ptr_t) +MAP_DECLS(handle_T, ptr_t) MAP_DECLS(String, MsgpackRpcRequestHandler) MAP_DECLS(linenr_T, bufhl_vec_T) diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c index 8b5f212d66..cd12f258b6 100644 --- a/src/nvim/msgpack_rpc/channel.c +++ b/src/nvim/msgpack_rpc/channel.c @@ -465,8 +465,7 @@ static void on_request_event(void **argv) } else { api_free_object(result); } - // All arguments were freed already, but we still need to free the array - xfree(args.items); + api_free_array(args); decref(channel); xfree(e); } diff --git a/src/nvim/msgpack_rpc/defs.h b/src/nvim/msgpack_rpc/defs.h deleted file mode 100644 index 5611636d4f..0000000000 --- a/src/nvim/msgpack_rpc/defs.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef NVIM_MSGPACK_RPC_DEFS_H -#define NVIM_MSGPACK_RPC_DEFS_H - - -/// 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); - 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; - -/// Initializes the msgpack-rpc method table -void msgpack_rpc_init_method_table(void); - -// Add a handler to the method table -void msgpack_rpc_add_method_handler(String method, - MsgpackRpcRequestHandler handler); - -void msgpack_rpc_init_function_metadata(Dictionary *metadata); - -MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, - size_t name_len) - FUNC_ATTR_NONNULL_ARG(1); -#endif // NVIM_MSGPACK_RPC_DEFS_H diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c index 9195b10614..33e9bb1c07 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -4,9 +4,9 @@ #include <msgpack.h> +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/msgpack_rpc/helpers.h" -#include "nvim/msgpack_rpc/defs.h" #include "nvim/lib/kvec.h" #include "nvim/vim.h" #include "nvim/log.h" @@ -40,7 +40,7 @@ static msgpack_sbuffer sbuffer; return false; \ } \ \ - *arg = data.via.u64; \ + *arg = (handle_T)data.via.i64; \ return true; \ } \ \ @@ -49,7 +49,7 @@ static msgpack_sbuffer sbuffer; { \ msgpack_packer pac; \ msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write); \ - msgpack_pack_uint64(&pac, o); \ + msgpack_pack_int64(&pac, o); \ msgpack_pack_ext(res, sbuffer.size, kObjectType##t); \ msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size); \ msgpack_sbuffer_clear(&sbuffer); \ diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index 90636326a5..6f35cdc35a 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -127,7 +127,7 @@ struct terminal { // we can't store a direct reference to the buffer because the // refresh_timer_cb may be called after the buffer was freed, and there's // no way to know if the memory was reused. - uint64_t buf_handle; + handle_T buf_handle; // program exited bool closed, destroy; // some vterm properties diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c index 3ef4d34c9a..44521c5ae6 100644 --- a/src/nvim/tui/input.c +++ b/src/nvim/tui/input.c @@ -216,8 +216,8 @@ static int get_key_code_timeout(void) // Check 'ttimeout' to determine if we should send ESC after 'ttimeoutlen'. // See :help 'ttimeout' for more information Error err = ERROR_INIT; - if (vim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) { - ms = vim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer; + if (nvim_get_option(cstr_as_string("ttimeout"), &err).data.boolean) { + ms = nvim_get_option(cstr_as_string("ttimeoutlen"), &err).data.integer; } return (int)ms; diff --git a/src/nvim/window.c b/src/nvim/window.c index 350b54d595..ee99dd5d68 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2926,7 +2926,9 @@ void win_init_size(void) */ static tabpage_T *alloc_tabpage(void) { + static int last_tp_handle = 0; tabpage_T *tp = xcalloc(1, sizeof(tabpage_T)); + tp->handle = ++last_tp_handle; handle_register_tabpage(tp); /* init t: variables */ @@ -3683,21 +3685,20 @@ win_T *buf_jump_open_tab(buf_T *buf) return NULL; } -static int last_win_id = 0; - /* * Allocate a window structure and link it in the window list when "hidden" is * FALSE. */ static win_T *win_alloc(win_T *after, int hidden) { - /* - * allocate window structure and linesizes arrays - */ + static int last_win_id = 0; + + // allocate window structure and linesizes arrays win_T *new_wp = xcalloc(1, sizeof(win_T)); - handle_register_window(new_wp); win_alloc_lines(new_wp); - new_wp->w_id = ++last_win_id; + + new_wp->handle = ++last_win_id; + handle_register_window(new_wp); /* init w: variables */ new_wp->w_vars = dict_alloc(); @@ -5681,7 +5682,7 @@ static bool frame_check_width(frame_T *topfrp, int width) int win_getid(typval_T *argvars) { if (argvars[0].v_type == VAR_UNKNOWN) { - return curwin->w_id; + return curwin->handle; } int winnr = get_tv_number(&argvars[0]); win_T *wp; @@ -5703,7 +5704,7 @@ int win_getid(typval_T *argvars) } for ( ; wp != NULL; wp = wp->w_next) { if (--winnr == 0) { - return wp->w_id; + return wp->handle; } } } @@ -5719,7 +5720,7 @@ int win_gotoid(typval_T *argvars) for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) { for (wp = tp == curtab ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next) { - if (wp->w_id == id) { + if (wp->handle == id) { goto_tabpage_win(tp, wp); return 1; } @@ -5739,7 +5740,7 @@ void win_id2tabwin(typval_T *argvars, list_T *list) for (tp = first_tabpage; tp != NULL; tp = tp->tp_next) { for (wp = tp == curtab ? firstwin : tp->tp_firstwin; wp != NULL; wp = wp->w_next) { - if (wp->w_id == id) { + if (wp->handle == id) { list_append_number(list, tabnr); list_append_number(list, winnr); return; @@ -5760,7 +5761,7 @@ int win_id2win(typval_T *argvars) int id = get_tv_number(&argvars[0]); for (wp = firstwin; wp != NULL; wp = wp->w_next) { - if (wp->w_id == id) { + if (wp->handle == id) { return nr; } nr++; diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua index cf8a83ad81..2cc803da52 100644 --- a/test/functional/api/buffer_spec.lua +++ b/test/functional/api/buffer_spec.lua @@ -3,105 +3,111 @@ local helpers = require('test.functional.helpers')(after_each) local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq local curbufmeths, ok = helpers.curbufmeths, helpers.ok -local funcs = helpers.funcs +local funcs, request = helpers.funcs, helpers.request describe('buffer_* functions', function() before_each(clear) + -- access deprecated functions + local function curbuf_depr(method, ...) + return request('buffer_'..method, 0, ...) + end + + describe('line_count, insert and del_line', function() it('works', function() - eq(1, curbuf('line_count')) - curbuf('insert', -1, {'line'}) - eq(2, curbuf('line_count')) - curbuf('insert', -1, {'line'}) - eq(3, curbuf('line_count')) - curbuf('del_line', -1) - eq(2, curbuf('line_count')) - curbuf('del_line', -1) - curbuf('del_line', -1) + eq(1, curbuf_depr('line_count')) + curbuf_depr('insert', -1, {'line'}) + eq(2, curbuf_depr('line_count')) + curbuf_depr('insert', -1, {'line'}) + eq(3, curbuf_depr('line_count')) + curbuf_depr('del_line', -1) + eq(2, curbuf_depr('line_count')) + curbuf_depr('del_line', -1) + curbuf_depr('del_line', -1) -- There's always at least one line - eq(1, curbuf('line_count')) + eq(1, curbuf_depr('line_count')) end) end) describe('{get,set,del}_line', function() it('works', function() - eq('', curbuf('get_line', 0)) - curbuf('set_line', 0, 'line1') - eq('line1', curbuf('get_line', 0)) - curbuf('set_line', 0, 'line2') - eq('line2', curbuf('get_line', 0)) - curbuf('del_line', 0) - eq('', curbuf('get_line', 0)) + eq('', curbuf_depr('get_line', 0)) + curbuf_depr('set_line', 0, 'line1') + eq('line1', curbuf_depr('get_line', 0)) + curbuf_depr('set_line', 0, 'line2') + eq('line2', curbuf_depr('get_line', 0)) + curbuf_depr('del_line', 0) + eq('', curbuf_depr('get_line', 0)) end) it('get_line: out-of-bounds is an error', function() - curbuf('set_line', 0, 'line1.a') - eq(1, curbuf('line_count')) -- sanity - eq(false, pcall(curbuf, 'get_line', 1)) - eq(false, pcall(curbuf, 'get_line', -2)) + curbuf_depr('set_line', 0, 'line1.a') + eq(1, curbuf_depr('line_count')) -- sanity + eq(false, pcall(curbuf_depr, 'get_line', 1)) + eq(false, pcall(curbuf_depr, 'get_line', -2)) end) it('set_line, del_line: out-of-bounds is an error', function() - curbuf('set_line', 0, 'line1.a') - eq(false, pcall(curbuf, 'set_line', 1, 'line1.b')) - eq(false, pcall(curbuf, 'set_line', -2, 'line1.b')) - eq(false, pcall(curbuf, 'del_line', 2)) - eq(false, pcall(curbuf, 'del_line', -3)) + curbuf_depr('set_line', 0, 'line1.a') + eq(false, pcall(curbuf_depr, 'set_line', 1, 'line1.b')) + eq(false, pcall(curbuf_depr, 'set_line', -2, 'line1.b')) + eq(false, pcall(curbuf_depr, 'del_line', 2)) + eq(false, pcall(curbuf_depr, 'del_line', -3)) end) it('can handle NULs', function() - curbuf('set_line', 0, 'ab\0cd') - eq('ab\0cd', curbuf('get_line', 0)) + curbuf_depr('set_line', 0, 'ab\0cd') + eq('ab\0cd', curbuf_depr('get_line', 0)) end) end) describe('{get,set}_line_slice', function() it('get_line_slice: out-of-bounds returns empty array', function() - curbuf('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 2, true, true)) --sanity - - eq({}, curbuf('get_line_slice', 2, 3, false, true)) - eq({}, curbuf('get_line_slice', 3, 9, true, true)) - eq({}, curbuf('get_line_slice', 3, -1, true, true)) - eq({}, curbuf('get_line_slice', -3, -4, false, true)) - eq({}, curbuf('get_line_slice', -4, -5, true, true)) + curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) + eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity + + eq({}, curbuf_depr('get_line_slice', 2, 3, false, true)) + eq({}, curbuf_depr('get_line_slice', 3, 9, true, true)) + eq({}, curbuf_depr('get_line_slice', 3, -1, true, true)) + eq({}, curbuf_depr('get_line_slice', -3, -4, false, true)) + eq({}, curbuf_depr('get_line_slice', -4, -5, true, true)) end) it('set_line_slice: out-of-bounds extends past end', function() - curbuf('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 2, true, true)) --sanity - - eq({'c'}, curbuf('get_line_slice', -1, 4, true, true)) - eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, 5, true, true)) - curbuf('set_line_slice', 4, 5, true, true, {'d'}) - eq({'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true)) - curbuf('set_line_slice', -4, -5, true, true, {'e'}) - eq({'e', 'a', 'b', 'c', 'd'}, curbuf('get_line_slice', 0, 5, true, true)) + curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'}) + eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity + + eq({'c'}, curbuf_depr('get_line_slice', -1, 4, true, true)) + eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 5, true, true)) + curbuf_depr('set_line_slice', 4, 5, true, true, {'d'}) + eq({'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true)) + curbuf_depr('set_line_slice', -4, -5, true, true, {'e'}) + eq({'e', 'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true)) end) it('works', function() - eq({''}, curbuf('get_line_slice', 0, -1, true, true)) + eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true)) -- Replace buffer - curbuf('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'}) - eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, -1, true, true)) - eq({'b', 'c'}, curbuf('get_line_slice', 1, -1, true, true)) - eq({'b'}, curbuf('get_line_slice', 1, 2, true, false)) - eq({}, curbuf('get_line_slice', 1, 1, true, false)) - eq({'a', 'b'}, curbuf('get_line_slice', 0, -1, true, false)) - eq({'b'}, curbuf('get_line_slice', 1, -1, true, false)) - eq({'b', 'c'}, curbuf('get_line_slice', -2, -1, true, true)) - curbuf('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'}) - eq({'a', 'a', 'b', 'c', 'c'}, curbuf('get_line_slice', 0, -1, true, true)) - curbuf('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'}) + curbuf_depr('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'}) + eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) + eq({'b', 'c'}, curbuf_depr('get_line_slice', 1, -1, true, true)) + eq({'b'}, curbuf_depr('get_line_slice', 1, 2, true, false)) + eq({}, curbuf_depr('get_line_slice', 1, 1, true, false)) + eq({'a', 'b'}, curbuf_depr('get_line_slice', 0, -1, true, false)) + eq({'b'}, curbuf_depr('get_line_slice', 1, -1, true, false)) + eq({'b', 'c'}, curbuf_depr('get_line_slice', -2, -1, true, true)) + curbuf_depr('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'}) + eq({'a', 'a', 'b', 'c', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) + curbuf_depr('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'}) eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'}, - curbuf('get_line_slice', 0, -1, true, true)) - curbuf('set_line_slice', 0, -3, true, false, {}) - eq({'a', 'b', 'c'}, curbuf('get_line_slice', 0, -1, true, true)) - curbuf('set_line_slice', 0, -1, true, true, {}) - eq({''}, curbuf('get_line_slice', 0, -1, true, true)) + curbuf_depr('get_line_slice', 0, -1, true, true)) + curbuf_depr('set_line_slice', 0, -3, true, false, {}) + eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true)) + curbuf_depr('set_line_slice', 0, -1, true, true, {}) + eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true)) end) end) @@ -286,7 +292,7 @@ describe('buffer_* functions', function() describe('get_mark', function() it('works', function() - curbuf('insert', -1, {'a', 'bit of', 'text'}) + curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'}) curwin('set_cursor', {3, 4}) nvim('command', 'mark V') eq({3, 0}, curbuf('get_mark', 'V')) diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua index 6fe87a358c..b668b5ba86 100644 --- a/test/functional/api/server_requests_spec.lua +++ b/test/functional/api/server_requests_spec.lua @@ -163,11 +163,11 @@ describe('server -> client', function() end) it('can communicate buffers, tabpages, and windows', function() - eq({3}, eval("rpcrequest(vim, 'vim_get_tabpages')")) + eq({1}, eval("rpcrequest(vim, 'vim_get_tabpages')")) eq({1}, eval("rpcrequest(vim, 'vim_get_windows')")) local buf = eval("rpcrequest(vim, 'vim_get_buffers')")[1] - eq(2, buf) + eq(1, buf) eval("rpcnotify(vim, 'buffer_set_line', "..buf..", 0, 'SOME TEXT')") nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 848935fc0f..351094567a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -7,6 +7,7 @@ local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed local os_name = helpers.os_name local meths = helpers.meths local funcs = helpers.funcs +local request = helpers.request describe('vim_* functions', function() before_each(clear) @@ -41,6 +42,10 @@ describe('vim_* functions', function() eq(1, nvim('eval',"matcharg(1) == ['', '']")) eq({'', ''}, nvim('eval','matcharg(1)')) end) + + it('works under deprecated name', function() + eq(2, request("vim_eval", "1+1")) + end) end) describe('call_function', function() @@ -298,4 +303,11 @@ describe('vim_* functions', function() eq(false, status) ok(err:match('Invalid option name') ~= nil) end) + + it("doesn't leak memory on incorrect argument types", function() + local status, err = pcall(nvim, 'change_directory',{'not', 'a', 'dir'}) + eq(false, status) + ok(err:match(': Wrong type for argument 1, expecting String') ~= nil) + end) + end) diff --git a/test/functional/eval/api_functions_spec.lua b/test/functional/eval/api_functions_spec.lua new file mode 100644 index 0000000000..d88f6977f1 --- /dev/null +++ b/test/functional/eval/api_functions_spec.lua @@ -0,0 +1,148 @@ +local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') +local lfs = require('lfs') +local neq, eq, execute = helpers.neq, helpers.eq, helpers.execute +local clear, curbufmeths = helpers.clear, helpers.curbufmeths +local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval +local insert = helpers.insert + +describe('api functions', function() + before_each(clear) + + it("work", function() + execute("call nvim_command('let g:test = 1')") + eq(1, eval("nvim_get_var('test')")) + + local buf = eval("nvim_get_current_buffer()") + execute("call nvim_buf_set_lines("..buf..", 0, -1, v:true, ['aa', 'bb'])") + expect([[ + aa + bb]]) + + execute("call nvim_win_set_cursor(0, [1, 1])") + execute("call nvim_input('ax<esc>')") + expect([[ + aax + bb]]) + end) + + it("throw errors for invalid arguments", function() + local err = exc_exec('call nvim_get_current_buffer("foo")') + eq('Vim(call):E118: Too many arguments for function: nvim_get_current_buffer', err) + + err = exc_exec('call nvim_set_option("hlsearch")') + eq('Vim(call):E119: Not enough arguments for function: nvim_set_option', err) + + err = exc_exec('call nvim_buf_set_lines(1, 0, -1, [], ["list"])') + eq('Vim(call):Wrong type for argument 4, expecting Boolean', err) + + err = exc_exec('call nvim_buf_set_lines(0, 0, -1, v:true, "string")') + eq('Vim(call):Wrong type for argument 5, expecting ArrayOf(String)', err) + + err = exc_exec('call nvim_buf_get_number("0")') + eq('Vim(call):Wrong type for argument 1, expecting Buffer', err) + + err = exc_exec('call nvim_buf_line_count(17)') + eq('Vim(call):Invalid buffer id', err) + end) + + + it("use buffer numbers and windows ids as handles", function() + local screen = Screen.new(40, 8) + screen:attach() + local bnr = eval("bufnr('')") + local bhnd = eval("nvim_get_current_buffer()") + local wid = eval("win_getid()") + local whnd = eval("nvim_get_current_window()") + eq(bnr, bhnd) + eq(wid, whnd) + + execute("new") -- creates new buffer and new window + local bnr2 = eval("bufnr('')") + local bhnd2 = eval("nvim_get_current_buffer()") + local wid2 = eval("win_getid()") + local whnd2 = eval("nvim_get_current_window()") + eq(bnr2, bhnd2) + eq(wid2, whnd2) + neq(bnr, bnr2) + neq(wid, wid2) + -- 0 is synonymous to the current buffer + eq(bnr2, eval("nvim_buf_get_number(0)")) + + execute("bn") -- show old buffer in new window + eq(bnr, eval("nvim_get_current_buffer()")) + eq(bnr, eval("bufnr('')")) + eq(bnr, eval("nvim_buf_get_number(0)")) + eq(wid2, eval("win_getid()")) + eq(whnd2, eval("nvim_get_current_window()")) + end) + + it("get_lines and set_lines use NL to represent NUL", function() + curbufmeths.set_lines(0, -1, true, {"aa\0", "b\0b"}) + eq({'aa\n', 'b\nb'}, eval("nvim_buf_get_lines(0, 0, -1, 1)")) + + execute('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])') + eq({'aa\0', 'xx', '\0yy'}, curbufmeths.get_lines(0, -1, 1)) + end) + + it("that are FUNC_ATTR_NOEVAL cannot be called", function() + -- Deprecated vim_ prefix is not exported. + local err = exc_exec('call vim_get_current_buffer("foo")') + eq('Vim(call):E117: Unknown function: vim_get_current_buffer', err) + + -- Deprecated buffer_ prefix is not exported. + err = exc_exec('call buffer_line_count(0)') + eq('Vim(call):E117: Unknown function: buffer_line_count', err) + + -- Functions deprecated before the api functions became available + -- in vimscript are not exported. + err = exc_exec('call buffer_get_line(0, 1)') + eq('Vim(call):E117: Unknown function: buffer_get_line', err) + + -- some api functions are only useful from a msgpack-rpc channel + err = exc_exec('call nvim_subscribe("fancyevent")') + eq('Vim(call):E117: Unknown function: nvim_subscribe', err) + end) + + it('have metadata accessible with api_info()', function() + local api_keys = eval("sort(keys(api_info()))") + eq({'error_types', 'functions', 'types'}, api_keys) + end) + + it('are highlighted by vim.vim syntax file', function() + if lfs.attributes("build/runtime/syntax/vim/generated.vim",'uid') == nil then + pending("runtime was not built, skipping test") + return + end + local screen = Screen.new(40, 8) + screen:attach() + screen:set_default_attr_ids({ + [1] = {bold = true, foreground = Screen.colors.Brown}, + [2] = {foreground = Screen.colors.DarkCyan}, + [3] = {foreground = Screen.colors.SlateBlue}, + [4] = {foreground = Screen.colors.Fuchsia}, + [5] = {bold = true, foreground = Screen.colors.Blue}, + }) + + execute("set ft=vim") + execute("let &rtp='build/runtime/,'.&rtp") + execute("syntax on") + insert([[ + call bufnr('%') + call nvim_input('typing...') + call not_a_function(42)]]) + + screen:expect([[ + {1:call} {2:bufnr}{3:(}{4:'%'}{3:)} | + {1:call} {2:nvim_input}{3:(}{4:'typing...'}{3:)} | + {1:call} not_a_function{3:(}{4:42}{3:^)} | + {5:~ }| + {5:~ }| + {5:~ }| + {5:~ }| + | + ]]) + screen:detach() + end) + +end) diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index 8dca4c5bbe..65da278f9e 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -133,11 +133,11 @@ local function stop() end local function nvim_command(cmd) - request('vim_command', cmd) + request('nvim_command', cmd) end local function nvim_eval(expr) - return request('vim_eval', expr) + return request('nvim_eval', expr) end local os_name = (function() @@ -157,12 +157,12 @@ local os_name = (function() end)() local function nvim_call(name, ...) - return request('vim_call_function', name, {...}) + return request('nvim_call_function', name, {...}) end local function nvim_feed(input) while #input > 0 do - local written = request('vim_input', input) + local written = request('nvim_input', input) input = input:sub(written + 1) end end @@ -339,7 +339,7 @@ local function source(code) end local function nvim(method, ...) - return request('vim_'..method, ...) + return request('nvim_'..method, ...) end local function ui(method, ...) @@ -347,27 +347,26 @@ local function ui(method, ...) end local function nvim_async(method, ...) - session:notify('vim_'..method, ...) + session:notify('nvim_'..method, ...) end local function buffer(method, ...) - return request('buffer_'..method, ...) + return request('nvim_buf_'..method, ...) end local function window(method, ...) - return request('window_'..method, ...) + return request('nvim_win_'..method, ...) end local function tabpage(method, ...) - return request('tabpage_'..method, ...) + return request('nvim_tabpage_'..method, ...) end local function curbuf(method, ...) - local buf = nvim('get_current_buffer') if not method then - return buf + return nvim('get_current_buffer') end - return buffer(method, buf, ...) + return buffer(method, 0, ...) end local function wait() @@ -387,19 +386,17 @@ local function curbuf_contents() end local function curwin(method, ...) - local win = nvim('get_current_window') if not method then - return win + return nvim('get_current_window') end - return window(method, win, ...) + return window(method, 0, ...) end local function curtab(method, ...) - local tab = nvim('get_current_tabpage') if not method then - return tab + return nvim('get_current_tabpage') end - return tabpage(method, tab, ...) + return tabpage(method, 0, ...) end local function expect(contents) diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua index 2595f22929..b1209a22e9 100644 --- a/test/functional/plugin/shada_spec.lua +++ b/test/functional/plugin/shada_spec.lua @@ -2463,17 +2463,17 @@ describe('ftplugin/shada.vim', function() nvim_command('setlocal filetype=shada') funcs.setline(1, ' Replacement with timestamp ' .. epoch) nvim_feed('ggA:\027') - eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_line', 0)) + eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_lines', 0, 1, true)[1]) nvim_feed('o-\027') - eq(' -', curbuf('get_line', 1)) + eq({' -'}, curbuf('get_lines', 1, 2, true)) nvim_feed('ggO+\027') - eq('+', curbuf('get_line', 0)) + eq({'+'}, curbuf('get_lines', 0, 1, true)) nvim_feed('GO*\027') - eq(' *', curbuf('get_line', 2)) + eq({' *'}, curbuf('get_lines', 2, 3, true)) nvim_feed('ggO /\027') - eq(' /', curbuf('get_line', 0)) + eq({' /'}, curbuf('get_lines', 0, 1, true)) nvim_feed('ggOx\027') - eq('x', curbuf('get_line', 0)) + eq({'x'}, curbuf('get_lines', 0, 1, true)) end) end) diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua index 6694e736dc..01952560d6 100644 --- a/test/functional/shada/buffers_spec.lua +++ b/test/functional/shada/buffers_spec.lua @@ -80,9 +80,9 @@ describe('ShaDa support code', function() it('does not dump unnamed buffers', function() set_additional_cmd('set shada+=% hidden') reset() - curbufmeths.set_line(0, 'foo') + curbufmeths.set_lines(0, 1, true, {'foo'}) nvim_command('enew') - curbufmeths.set_line(0, 'bar') + curbufmeths.set_lines(0, 1, true, {'bar'}) eq(2, funcs.bufnr('$')) nvim_command('qall!') reset() diff --git a/test/functional/viml/function_spec.lua b/test/functional/viml/function_spec.lua index f0a4406593..776e760aaf 100644 --- a/test/functional/viml/function_spec.lua +++ b/test/functional/viml/function_spec.lua @@ -2,7 +2,6 @@ local helpers = require('test.functional.helpers')(after_each) local clear = helpers.clear local eq = helpers.eq -local eval = helpers.eval local exc_exec = helpers.exc_exec describe('Up to MAX_FUNC_ARGS arguments are handled by', function() @@ -28,11 +27,3 @@ describe('Up to MAX_FUNC_ARGS arguments are handled by', function() eq('Vim(call):E740: Too many arguments for function rpcnotify', ret) end) end) - -describe('api_info()', function() - before_each(clear) - it('has the right keys', function() - local api_keys = eval("sort(keys(api_info()))") - eq({'error_types', 'functions', 'types'}, api_keys) - end) -end) diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua index 317c9be6e7..49a4d84279 100644 --- a/test/unit/buffer_spec.lua +++ b/test/unit/buffer_spec.lua @@ -87,7 +87,7 @@ describe('buffer functions', function() it('should find exact matches', function() local buf = buflist_new(path1, buffer.BLN_LISTED) - eq(buf.b_fnum, buflist_findpat(path1, ONLY_LISTED)) + eq(buf.handle, buflist_findpat(path1, ONLY_LISTED)) close_buffer(NULL, buf, buffer.DOBUF_WIPE, 0) end) @@ -97,9 +97,9 @@ describe('buffer functions', function() local buf2 = buflist_new(path2, buffer.BLN_LISTED) local buf3 = buflist_new(path3, buffer.BLN_LISTED) - eq(buf1.b_fnum, buflist_findpat("test", ONLY_LISTED)) - eq(buf2.b_fnum, buflist_findpat("file", ONLY_LISTED)) - eq(buf3.b_fnum, buflist_findpat("path", ONLY_LISTED)) + eq(buf1.handle, buflist_findpat("test", ONLY_LISTED)) + eq(buf2.handle, buflist_findpat("file", ONLY_LISTED)) + eq(buf3.handle, buflist_findpat("path", ONLY_LISTED)) close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0) close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0) @@ -113,7 +113,7 @@ describe('buffer functions', function() local buf3 = buflist_new(path3, buffer.BLN_LISTED) -- Then: buf2 is the buffer that is found - eq(buf2.b_fnum, buflist_findpat("test", ONLY_LISTED)) + eq(buf2.handle, buflist_findpat("test", ONLY_LISTED)) --} --{ When: We close buf2 @@ -123,7 +123,7 @@ describe('buffer functions', function() local buf1 = buflist_new(path1, buffer.BLN_LISTED) -- Then: buf3 is found since 'file' appears at the end of the name - eq(buf3.b_fnum, buflist_findpat("file", ONLY_LISTED)) + eq(buf3.handle, buflist_findpat("file", ONLY_LISTED)) --} close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0) @@ -135,7 +135,7 @@ describe('buffer functions', function() local buf2 = buflist_new(path2, buffer.BLN_LISTED) local buf3 = buflist_new(path3, buffer.BLN_LISTED) - eq(buf3.b_fnum, buflist_findpat("_test_", ONLY_LISTED)) + eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED)) close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0) close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0) @@ -147,7 +147,7 @@ describe('buffer functions', function() local buf3 = buflist_new(path3, buffer.BLN_LISTED) -- Then: We should find the buffer when it is given a unique pattern - eq(buf3.b_fnum, buflist_findpat("_test_", ONLY_LISTED)) + eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED)) --} --{ When: We unlist the buffer @@ -157,7 +157,7 @@ describe('buffer functions', function() eq(-1, buflist_findpat("_test_", ONLY_LISTED)) -- And: It should find the buffer when including unlisted buffers - eq(buf3.b_fnum, buflist_findpat("_test_", ALLOW_UNLISTED)) + eq(buf3.handle, buflist_findpat("_test_", ALLOW_UNLISTED)) --} --{ When: We wipe the buffer @@ -175,7 +175,7 @@ describe('buffer functions', function() local buf2 = buflist_new(path2, buffer.BLN_LISTED) -- Then: The first buffer is preferred when both are listed - eq(buf1.b_fnum, buflist_findpat("test", ONLY_LISTED)) + eq(buf1.handle, buflist_findpat("test", ONLY_LISTED)) --} --{ When: The first buffer is unlisted @@ -183,13 +183,13 @@ describe('buffer functions', function() -- Then: The second buffer is preferred because -- unlisted buffers are not allowed - eq(buf2.b_fnum, buflist_findpat("test", ONLY_LISTED)) + eq(buf2.handle, buflist_findpat("test", ONLY_LISTED)) --} --{ When: We allow unlisted buffers -- Then: The second buffer is still preferred -- because listed buffers are preferred to unlisted - eq(buf2.b_fnum, buflist_findpat("test", ALLOW_UNLISTED)) + eq(buf2.handle, buflist_findpat("test", ALLOW_UNLISTED)) --} --{ When: We unlist the second buffer @@ -198,7 +198,7 @@ describe('buffer functions', function() -- Then: The first buffer is preferred again -- because buf1 matches better which takes precedence -- when both buffers have the same listing status. - eq(buf1.b_fnum, buflist_findpat("test", ALLOW_UNLISTED)) + eq(buf1.handle, buflist_findpat("test", ALLOW_UNLISTED)) -- And: Neither buffer is returned when ignoring unlisted eq(-1, buflist_findpat("test", ONLY_LISTED)) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 2e41d745d7..823e9719d1 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -32,6 +32,12 @@ option(USE_BUNDLED_LUV "Use the bundled version of luv." ${USE_BUNDLED}) # build it unless explicitly requested option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF) +if(USE_BUNDLED AND (NOT WIN32)) + option(USE_BUNDLED_GPERF "Use the bundled version of gperf." ON) +else() + option(USE_BUNDLED_GPERF "Use the bundled version of gperf." OFF) +endif() + option(USE_EXISTING_SRC_DIR "Skip download of deps sources in case of existing source directory." OFF) if(UNIX) @@ -111,6 +117,9 @@ set(JEMALLOC_SHA256 5630650d5c1caab95d2f0898de4fe5ab8519dc680b04963b38bb425ef6a4 set(LUV_URL https://github.com/luvit/luv/archive/146f1ce4c08c3b67f604c9ee1e124b1cf5c15cf3.tar.gz) set(LUV_SHA256 3d537f8eb9fa5adb146a083eae22af886aee324ec268e2aa0fa75f2f1c52ca7a) +set(GPERF_URL http://ftp.gnu.org/pub/gnu/gperf/gperf-3.0.4.tar.gz) +set(GPERF_SHA256 767112a204407e62dbc3106647cf839ed544f3cf5d0f0523aaa2508623aad63e) + if(USE_BUNDLED_UNIBILIUM) include(BuildUnibilium) endif() @@ -151,6 +160,10 @@ if(USE_BUNDLED_LUV) include(BuildLuv) endif() +if(USE_BUNDLED_GPERF) + include(BuildGperf) +endif() + add_custom_target(clean-shared-libraries COMMAND ${CMAKE_COMMAND} -DREMOVE_FILE_GLOB=${DEPS_INSTALL_DIR}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}*${CMAKE_SHARED_LIBRARY_SUFFIX}* diff --git a/third-party/cmake/BuildGperf.cmake b/third-party/cmake/BuildGperf.cmake new file mode 100644 index 0000000000..494d0d9717 --- /dev/null +++ b/third-party/cmake/BuildGperf.cmake @@ -0,0 +1,51 @@ +# Gperf recipe. Gperf is only required when building Neovim, when +# cross compiling we still want to build for the HOST system, whenever +# writing a recipe that is meant for cross-compile, use the HOSTDEPS_* variables +# instead of DEPS_* - check the main CMakeLists.txt for a list. + +# BuildGperf(CONFIGURE_COMMAND ... BUILD_COMMAND ... INSTALL_COMMAND ...) +# Reusable function to build Gperf, wraps ExternalProject_Add. +# Failing to pass a command argument will result in no command being run +function(BuildGperf) + cmake_parse_arguments(_gperf + "" + "" + "CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND" + ${ARGN}) + + if(NOT _gperf_CONFIGURE_COMMAND AND NOT _gperf_BUILD_COMMAND + AND NOT _gperf_INSTALL_COMMAND) + message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND") + endif() + + ExternalProject_Add(gperf + PREFIX ${DEPS_BUILD_DIR} + URL ${GPERF_URL} + DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/gperf + DOWNLOAD_COMMAND ${CMAKE_COMMAND} + -DPREFIX=${DEPS_BUILD_DIR} + -DDOWNLOAD_DIR=${DEPS_DOWNLOAD_DIR}/gperf + -DURL=${GPERF_URL} + -DEXPECTED_SHA256=${GPERF_SHA256} + -DTARGET=gperf + -DUSE_EXISTING_SRC_DIR=${USE_EXISTING_SRC_DIR} + -P ${CMAKE_CURRENT_SOURCE_DIR}/cmake/DownloadAndExtractFile.cmake + BUILD_IN_SOURCE 1 + CONFIGURE_COMMAND "${_gperf_CONFIGURE_COMMAND}" + BUILD_COMMAND "${_gperf_BUILD_COMMAND}" + INSTALL_COMMAND "${_gperf_INSTALL_COMMAND}") +endfunction() + +set(GPERF_BUILDARGS CC=${HOSTDEPS_C_COMPILER} LD=${HOSTDEPS_C_COMPILER}) + +if(UNIX OR (MINGW AND CMAKE_CROSSCOMPILING)) + + BuildGperf( + CONFIGURE_COMMAND ${DEPS_BUILD_DIR}/src/gperf/configure + --prefix=${HOSTDEPS_INSTALL_DIR} + INSTALL_COMMAND ${MAKE_PRG} install) + +else() + message(FATAL_ERROR "Trying to build gperf in an unsupported system ${CMAKE_SYSTEM_NAME}/${CMAKE_C_COMPILER_ID}") +endif() + |