From 8fb7273ac0b981eeb9afdc82675b908c1600d34f Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 1 Jan 2016 12:17:22 +0300 Subject: eval: Move VimL functions list to a lua file Removes all kinds of problems with sorting, provides a ready-to-use function list representation for genvimvim.lua, does not require specifying function name twice (VimL function name (string) + f_ function name). --- scripts/geneval.lua | 42 ++++++ scripts/genvimvim.lua | 22 +--- src/nvim/CMakeLists.txt | 10 ++ src/nvim/eval.c | 339 ++---------------------------------------------- src/nvim/eval.lua | 307 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 379 insertions(+), 341 deletions(-) create mode 100644 scripts/geneval.lua create mode 100644 src/nvim/eval.lua diff --git a/scripts/geneval.lua b/scripts/geneval.lua new file mode 100644 index 0000000000..1f8a14d27b --- /dev/null +++ b/scripts/geneval.lua @@ -0,0 +1,42 @@ +local nvimsrcdir = arg[1] +local autodir = arg[2] + +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 funcsfile = io.open(funcsfname, 'w') + +local funcs = require('eval') + +local sorted_funcs = {} +for name, def in pairs(funcs.funcs) do + def.name = name + def.args = def.args or 0 + if type(def.args) == 'number' then + def.args = {def.args, def.args} + elseif #def.args == 1 then + def.args[2] = 'MAX_FUNC_ARGS' + end + def.func = def.func or ('f_' .. def.name) + sorted_funcs[#sorted_funcs + 1] = def +end +table.sort(sorted_funcs, function(a, b) return a.name < b.name end) + +funcsfile:write('static const VimLFuncDef functions[] = {\n') +for _, def in ipairs(sorted_funcs) do + funcsfile:write((' { "%s", %s, %s, &%s },\n'):format( + def.name, def.args[1], def.args[2], def.func + )) +end +funcsfile:write('};\n') diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 667af7be6c..729749a52f 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -23,6 +23,7 @@ end local options = require('options') local auevents = require('auevents') local ex_cmds = require('ex_cmds') +local eval = require('eval') local cmd_kw = function(prev_cmd, cmd) if not prev_cmd then @@ -113,23 +114,12 @@ local vimfun_start = 'syn keyword vimFuncName contained ' w('\n\n' .. vimfun_start) eval_fd = io.open(nvimsrcdir .. '/eval.c', 'r') 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(eval.funcs) do + if name then + if lld.line_length > 850 then + w('\n' .. vimfun_start) end + w(' ' .. name) end end eval_fd:close() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 5c4df1be0b..3ff34122f0 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -19,14 +19,17 @@ set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) 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 ${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) @@ -200,6 +203,7 @@ list(APPEND NEOVIM_GENERATED_SOURCES "${GENERATED_EVENTS_NAMES_MAP}" "${GENERATED_OPTIONS}" "${GENERATED_UNICODE_TABLES}" + "${GENERATED_FUNCS}" ) add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} @@ -208,6 +212,12 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE} ) +add_custom_command(OUTPUT ${GENERATED_FUNCS} + COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} + DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} +) + 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/eval.c b/src/nvim/eval.c index bb46898135..64f85a2fe5 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6681,331 +6681,20 @@ 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 }, -}; +/// Prototype of C function that implements VimL function +typedef void (*VimLFunc)(typval_T *args, typval_T *rvar); + +/// Structure holding VimL function definition +typedef struct fst { + char *f_name; ///< Function name. + uint8_t f_min_argc; ///< Minimal number of arguments. + uint8_t f_max_argc; ///< Maximal number of arguments. + VimLFunc f_func; ///< Function implementation. +} VimLFuncDef; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "funcs.generated.h" +#endif /* diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua new file mode 100644 index 0000000000..57c58f8f83 --- /dev/null +++ b/src/nvim/eval.lua @@ -0,0 +1,307 @@ +-- 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}, -- WJMc + add={args=2}, + ['and']={args=2}, + append={args=2}, + argc={}, + argidx={}, + arglistid={args={0, 2}}, + argv={args={0, 1}}, + asin={args=1}, -- WJMc + atan={args=1}, + 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}, + 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}, + cosh={args=1}, + count={args={2, 4}}, + cscope_connection={args={0, 3}}, + cursor={args={1, 3}}, + deepcopy={args={1, 2}}, + delete={args=1}, + 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}, + exepath={args=1}, + exists={args=1}, + exp={args=1}, + 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}, + 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={}, + getcurpos={}, + getcwd={}, + 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, 3}}, + glob2regpat={args=1}, + globpath={args={2, 4}}, + has={args=1}, + has_key={args=2}, + haslocaldir={}, + 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}}, + jobresize={args=3}, + jobsend={args=2}, + jobstart={args={1, 2}}, + jobstop={args=1}, + jobwait={args={1, 2}}, + join={args={1, 2}}, + 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}, + log10={args=1}, + map={args=2}, + maparg={args={1, 4}}, + mapcheck={args={1, 3}}, + match={args={2, 4}}, + matchadd={args={2, 4}}, + matchaddpos={args={2, 4}}, + 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}}, + reltimestr={args=1}, + remove={args={2, 3}}, + rename={args=2}, + ['repeat']={args=2}, + resolve={args=1}, + reverse={args=1}, + round={args=1}, + 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}, + setline={args=2}, + setloclist={args={2, 3}}, + setmatches={args=1}, + setpos={args=2}, + setqflist={args={1, 2}}, + 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}, + sinh={args=1}, + sort={args={1, 3}}, + soundfold={args=1}, + spellbadword={args={0, 1}}, + spellsuggest={args={1, 3}}, + split={args={1, 3}}, + sqrt={args=1}, + str2float={args=1}, + str2nr={args={1, 2}}, + strchars={args=1}, + 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}, + tanh={args=1}, + tempname={}, + termopen={args={1, 2}}, + test={args=1}, + tolower={args=1}, + toupper={args=1}, + tr={args=3}, + trunc={args=1}, + type={args=1}, + undofile={args=1}, + undotree={}, + uniq={args={1, 3}}, + values={args=1}, + virtcol={args=1}, + visualmode={args={0, 1}}, + wildmenumode={}, + winbufnr={args=1}, + wincol={}, + winheight={args=1}, + winline={}, + winnr={args={0, 1}}, + winrestcmd={}, + winrestview={args=1}, + winsaveview={}, + winwidth={args=1}, + writefile={args={2, 3}}, + xor={args=2}, + }, +} -- cgit From abe00d583e06a67b9eddbe0aed255a8db06bc725 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 18 Jun 2016 11:39:40 +0200 Subject: eval: add new function entries --- src/nvim/eval.lua | 43 +++++++++++++++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 57c58f8f83..627925cd58 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -18,12 +18,21 @@ return { acos={args=1}, -- 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}, -- 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}, atan2={args=2}, browse={args=4}, @@ -58,7 +67,7 @@ return { cscope_connection={args={0, 3}}, cursor={args={1, 3}}, deepcopy={args={1, 2}}, - delete={args=1}, + delete={args={1,2}}, dictwatcheradd={args=3}, dictwatcherdel={args=3}, did_filetype={}, @@ -69,6 +78,7 @@ return { eval={args=1}, eventhandler={}, executable={args=1}, + execute={args=1}, exepath={args=1}, exists={args=1}, exp={args=1}, @@ -104,8 +114,9 @@ return { getcmdpos={}, getcmdtype={}, getcmdwintype={}, + getcompletion={args=2}, getcurpos={}, - getcwd={}, + getcwd={args={0,2}}, getfontname={args={0, 1}}, getfperm={args=1}, getfsize={args=1}, @@ -124,12 +135,12 @@ return { getwinposx={}, getwinposy={}, getwinvar={args={2, 3}}, - glob={args={1, 3}}, + glob={args={1, 4}}, glob2regpat={args=1}, - globpath={args={2, 4}}, + globpath={args={2, 5}}, has={args=1}, has_key={args=2}, - haslocaldir={}, + haslocaldir={args={0,2}}, hasmapto={args={1, 3}}, highlightID={args=1, func='f_hlID'}, -- obsolete highlight_exists={args=1, func='f_hlexists'}, -- obsolete @@ -155,12 +166,15 @@ return { 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}, @@ -176,8 +190,8 @@ return { maparg={args={1, 4}}, mapcheck={args={1, 3}}, match={args={2, 4}}, - matchadd={args={2, 4}}, - matchaddpos={args={2, 4}}, + matchadd={args={2, 5}}, + matchaddpos={args={2, 5}}, matcharg={args=1}, matchdelete={args=1}, matchend={args={2, 4}}, @@ -202,6 +216,7 @@ return { 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}, @@ -228,11 +243,12 @@ return { setbufvar={args=3}, setcharsearch={args=1}, setcmdpos={args=1}, + setfperm={args=2}, setline={args=2}, - setloclist={args={2, 3}}, + setloclist={args={2, 4}}, setmatches={args=1}, setpos={args=2}, - setqflist={args={1, 2}}, + setqflist={args={1, 3}}, setreg={args={2, 3}}, settabvar={args=3}, settabwinvar={args=4}, @@ -251,7 +267,7 @@ return { sqrt={args=1}, str2float={args=1}, str2nr={args={1, 2}}, - strchars={args=1}, + strchars={args={1,2}}, strdisplaywidth={args={1, 2}}, strftime={args={1, 2}}, stridx={args={2, 3}}, @@ -280,6 +296,8 @@ return { 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}, @@ -292,6 +310,10 @@ return { 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}, @@ -301,6 +323,7 @@ return { winrestview={args=1}, winsaveview={}, winwidth={args=1}, + wordcount={}, writefile={args={2, 3}}, xor={args=2}, }, -- cgit From 5e59916e84933b0b05fda8ed76cf5f24fa3f48b6 Mon Sep 17 00:00:00 2001 From: ZyX Date: Fri, 1 Jan 2016 14:37:20 +0300 Subject: eval: Use generated hash to look up function list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problems: - Disables cross-compiling (alternative: keeps two hash implementations which need to be synchronized with each other). - Puts code-specific name literals into CMakeLists.txt. - Workaround for lua’s absence of bidirectional pipe communication is rather ugly. --- scripts/geneval.lua | 30 +++++--------- src/genhash.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/CMakeLists.txt | 10 ++++- src/nvim/eval.c | 105 +++++++++++++++++++++++------------------------ src/nvim/lib/khash.h | 41 +++++++++++++------ 5 files changed, 204 insertions(+), 88 deletions(-) create mode 100644 src/genhash.c diff --git a/scripts/geneval.lua b/scripts/geneval.lua index 1f8a14d27b..c9533d7908 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -15,28 +15,20 @@ end package.path = nvimsrcdir .. '/?.lua;' .. package.path local funcsfname = autodir .. '/funcs.generated.h' -local funcsfile = io.open(funcsfname, 'w') + +local funcspipe = io.open(funcsfname .. '.hsh', 'w') local funcs = require('eval') -local sorted_funcs = {} for name, def in pairs(funcs.funcs) do - def.name = name - def.args = def.args or 0 - if type(def.args) == 'number' then - def.args = {def.args, def.args} - elseif #def.args == 1 then - def.args[2] = 'MAX_FUNC_ARGS' + args = def.args or 0 + if type(args) == 'number' then + args = {args, args} + elseif #args == 1 then + args[2] = 'MAX_FUNC_ARGS' end - def.func = def.func or ('f_' .. def.name) - sorted_funcs[#sorted_funcs + 1] = def -end -table.sort(sorted_funcs, function(a, b) return a.name < b.name end) - -funcsfile:write('static const VimLFuncDef functions[] = {\n') -for _, def in ipairs(sorted_funcs) do - funcsfile:write((' { "%s", %s, %s, &%s },\n'):format( - def.name, def.args[1], def.args[2], def.func - )) + func = def.func or ('f_' .. name) + local val = ('{ %s, %s, &%s }'):format(args[1], args[2], func) + funcspipe:write(name .. '\n' .. val .. '\n') end -funcsfile:write('};\n') +funcspipe:close() diff --git a/src/genhash.c b/src/genhash.c new file mode 100644 index 0000000000..649b8deb2e --- /dev/null +++ b/src/genhash.c @@ -0,0 +1,106 @@ +// Program used to generate static hashes +// +// Uses hashes from khash.h macros library. + +#include +#include +#include +#include + +#define USE_LIBC_ALLOCATOR +#include "nvim/lib/khash.h" + +KHASH_MAP_INIT_STR(hash, char *) + +#define CHECK_FAIL(cond, ...) \ + do { \ + if (cond) { \ + fprintf(stderr, __VA_ARGS__); \ + putc('\n', stderr); \ + return 1; \ + } \ + } while (0) + +int main(int argc, char **argv) +{ + if (argc == 2 && strcmp(argv[1], "--help") == 0) { + puts("Usage:"); + puts(" genhash SOURCE TARGET TYPE NAME VALTYPE NULLVAL"); + puts("Transforms keys and values in a form \"key\\nval\\n\" into a hash"); + puts("literal."); + puts(""); + puts("SOURCE is the file name to read keys and values from."); + puts("TARGET is the file name to write to."); + puts("TYPE is the name of the hash type (khash_t argument)."); + puts("NAME is the name of the generated hash."); + puts("VALTYPE is the name of the value type."); + puts("NULLVAL is the value used when no value is available."); + return 0; + } + + CHECK_FAIL(argc != 7, "Expecting six arguments, got %i.", argc); + + const char *const source = argv[1]; + const char *const target = argv[2]; + const char *const type = argv[3]; + const char *const name = argv[4]; + const char *const valtype = argv[5]; + const char *const nullval = argv[6]; + + FILE *fin = fopen(source, "r"); + CHECK_FAIL(!fin, "Failed to open source: %s.", strerror(errno)); + + char keybuf[80]; + char valbuf[4096]; + khash_t(hash) hash = KHASH_EMPTY_TABLE(hash); + while (fgets(keybuf, sizeof(keybuf), fin) != NULL) { + CHECK_FAIL(ferror(fin), "Failed to read key %i from source: %s", + (int) kh_size(&hash), strerror(ferror(fin))); + keybuf[strlen(keybuf) - 1] = 0; + CHECK_FAIL(!fgets(valbuf, sizeof(valbuf), fin), + "Failed to read value for key %i (%s): %s", + (int) kh_size(&hash), keybuf, (ferror(fin) + ? strerror(ferror(fin)) + : "EOF found")); + valbuf[strlen(valbuf) - 1] = 0; + char *const key_copy = strdup(keybuf); + CHECK_FAIL(!key_copy, "Failed to allocate memory for a key"); + int put_ret; + const khiter_t k = kh_put(hash, &hash, key_copy, &put_ret); + CHECK_FAIL(put_ret != 1, "Expecting unused non-empty bucket for key %s", + key_copy); + kh_value(&hash, k) = strdup(valbuf); + CHECK_FAIL(!kh_value(&hash, k), "Failed to allocate memory for a value"); + } + CHECK_FAIL(fclose(fin), "Failed to close source: %s", strerror(errno)); + + FILE *f = fopen(target, "w"); + CHECK_FAIL(!f, strerror(errno)); + fprintf(f, "static const khash_t(%s) %s = {", type, name); + fprintf(f, " .n_buckets = %i,\n", (int) hash.n_buckets); + fprintf(f, " .size = %i,\n", (int) hash.size); + fprintf(f, " .n_occupied = %i,\n", (int) hash.n_occupied); + fprintf(f, " .upper_bound = %i,\n", (int) hash.upper_bound); + fprintf(f, " .flags = (khint32_t[]) {\n"); + for (khint_t i = 0; i < kh_end(&hash); i++) { + fprintf(f, " %i,\n", (int) hash.flags[i]); + } + fprintf(f, " },\n"); + fprintf(f, " .keys = (const char*[]) {\n"); + for (khint_t i = 0; i < kh_end(&hash); i++) { + if (kh_exist(&hash, i)) { + fprintf(f, " \"%s\",\n", hash.keys[i]); + } else { + fprintf(f, " NULL,\n"); + } + } + fprintf(f, " },\n"); + fprintf(f, " .vals = (%s[]) {\n", valtype); + for (khint_t i = 0; i < kh_end(&hash); i++) { + fprintf(f, " %s,\n", (kh_exist(&hash, i) ? hash.vals[i] : nullval)); + } + fprintf(f, " },\n"); + fprintf(f, "};\n"); + fclose(f); + return 0; +} diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 3ff34122f0..3385c0e462 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -19,6 +19,7 @@ set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) 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.hsh) 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) @@ -37,6 +38,7 @@ set(UNICODEDATA_FILE ${UNICODE_DIR}/UnicodeData.txt) set(CASEFOLDING_FILE ${UNICODE_DIR}/CaseFolding.txt) set(EASTASIANWIDTH_FILE ${UNICODE_DIR}/EastAsianWidth.txt) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) +set(GENHASH_SOURCE ${PROJECT_SOURCE_DIR}/src/genhash.c) include_directories(${GENERATED_DIR}) include_directories(${GENERATED_INCLUDES_DIR}) @@ -214,8 +216,10 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} add_custom_command(OUTPUT ${GENERATED_FUNCS} COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} + COMMAND $ + ${GENERATED_FUNCS_HASH_INPUT} ${GENERATED_FUNCS} functions functions VimLFuncDef "NOFUNC" + DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} genhash ) add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} @@ -284,6 +288,8 @@ if(WIN32) DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() +add_executable(genhash ${GENHASH_SOURCE} ${NEOVIM_HEADERS}) + if(CLANG_ASAN_UBSAN) message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.") check_c_compiler_flag(-fno-sanitize-recover=all SANITIZE_RECOVER_ALL) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 64f85a2fe5..c5b5866f56 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,18 @@ typedef struct { ufunc_T *callback; } timer_T; +/// Prototype of C function that implements VimL function +typedef void (*VimLFunc)(typval_T *args, typval_T *rvar); + +/// Structure holding VimL function definition +typedef struct fst { + uint8_t min_argc; ///< Minimal number of arguments. + uint8_t max_argc; ///< Maximal number of arguments. + VimLFunc func; ///< Function implementation. +} VimLFuncDef; + +KHASH_MAP_INIT_STR(functions, VimLFuncDef) + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval.c.generated.h" #endif @@ -6681,17 +6695,7 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) return OK; } -/// Prototype of C function that implements VimL function -typedef void (*VimLFunc)(typval_T *args, typval_T *rvar); - -/// Structure holding VimL function definition -typedef struct fst { - char *f_name; ///< Function name. - uint8_t f_min_argc; ///< Minimal number of arguments. - uint8_t f_max_argc; ///< Maximal number of arguments. - VimLFunc f_func; ///< Function implementation. -} VimLFuncDef; - +#define NOFUNC { 0, 0, NULL } #ifdef INCLUDE_GENERATED_DECLARATIONS # include "funcs.generated.h" #endif @@ -6713,15 +6717,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 ((khiter_t) ++intidx < kh_end(&functions) + && !kh_exist(&functions, (khiter_t) intidx)) { } - return NULL; + if ((khiter_t) intidx >= kh_end(&functions)) { + return NULL; + } + + const char *const key = kh_key(&functions, (khiter_t) intidx); + const size_t key_len = strlen(key); + memcpy(IObuff, key, key_len); + IObuff[key_len] = '('; + if (kh_val(&functions, (khiter_t) intidx).max_argc == 0) { + IObuff[key_len + 1] = ')'; + IObuff[key_len + 2] = NUL; + } else { + IObuff[key_len + 1] = NUL; + } + return IObuff; } /* @@ -6746,32 +6760,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; + const khiter_t k = kh_get(functions, &functions, name); + return (k == kh_end(&functions) ? NULL : &kh_val(&functions, k)); } /* @@ -6889,7 +6887,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 @@ -6911,7 +6908,7 @@ call_func ( fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; - i = 3; + int i = 3; if (eval_fname_sid(name)) { /* "" or "s:" */ if (current_SID <= 0) error = ERROR_SCRIPT; @@ -6983,18 +6980,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); error = ERROR_NONE; } } @@ -20120,7 +20115,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/lib/khash.h b/src/nvim/lib/khash.h index 8287cb14da..f8530be79a 100644 --- a/src/nvim/lib/khash.h +++ b/src/nvim/lib/khash.h @@ -130,7 +130,9 @@ int main() { #include #include -#include "nvim/memory.h" +#ifndef USE_LIBC_ALLOCATOR +# include "nvim/memory.h" +#endif #include "nvim/func_attr.h" @@ -171,17 +173,32 @@ typedef khint_t khiter_t; #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) #endif -#ifndef kcalloc -#define kcalloc(N,Z) xcalloc(N,Z) -#endif -#ifndef kmalloc -#define kmalloc(Z) xmalloc(Z) -#endif -#ifndef krealloc -#define krealloc(P,Z) xrealloc(P,Z) -#endif -#ifndef kfree -#define kfree(P) xfree(P) +#ifdef USE_LIBC_ALLOCATOR +# ifndef kcalloc +# define kcalloc(N,Z) calloc(N,Z) +# endif +# ifndef kmalloc +# define kmalloc(Z) malloc(Z) +# endif +# ifndef krealloc +# define krealloc(P,Z) realloc(P,Z) +# endif +# ifndef kfree +# define kfree(P) free(P) +# endif +#else +# ifndef kcalloc +# define kcalloc(N,Z) xcalloc(N,Z) +# endif +# ifndef kmalloc +# define kmalloc(Z) xmalloc(Z) +# endif +# ifndef krealloc +# define krealloc(P,Z) xrealloc(P,Z) +# endif +# ifndef kfree +# define kfree(P) xfree(P) +# endif #endif #define __ac_HASH_UPPER 0.77 -- cgit From de3a515123fa417ecce61efebe4bc117b010c657 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Thu, 16 Jun 2016 13:35:04 +0200 Subject: api: rename "msgpack_rpc/defs.h" to "api/private/dispatch.h" and use the header generator. --- scripts/gendispatch.lua | 313 ++++++++++++++++++++++++++++++++++++++++ scripts/msgpack-gen.lua | 313 ---------------------------------------- src/nvim/CMakeLists.txt | 16 +- src/nvim/api/private/dispatch.h | 21 +++ src/nvim/main.c | 2 +- src/nvim/map.c | 2 +- src/nvim/map.h | 2 +- src/nvim/msgpack_rpc/defs.h | 28 ---- src/nvim/msgpack_rpc/helpers.c | 2 +- 9 files changed, 348 insertions(+), 351 deletions(-) create mode 100644 scripts/gendispatch.lua delete mode 100644 scripts/msgpack-gen.lua create mode 100644 src/nvim/api/private/dispatch.h delete mode 100644 src/nvim/msgpack_rpc/defs.h diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua new file mode 100644 index 0000000000..54bfdab45b --- /dev/null +++ b/scripts/gendispatch.lua @@ -0,0 +1,313 @@ +lpeg = require('lpeg') +mpack = require('mpack') + +-- lpeg grammar for building api metadata from a set of header files. It +-- ignores comments and preprocessor commands and parses a very small subset +-- of C prototypes with a limited set of types +P, R, S = lpeg.P, lpeg.R, lpeg.S +C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg + +any = P(1) -- (consume one character) +letter = R('az', 'AZ') + S('_$') +alpha = letter + R('09') +nl = P('\r\n') + P('\n') +not_nl = any - nl +ws = S(' \t') + nl +fill = ws ^ 0 +c_comment = P('//') * (not_nl ^ 0) +c_preproc = P('#') * (not_nl ^ 0) +typed_container = + (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') +c_id = ( + typed_container + + (letter * (alpha ^ 0)) +) +c_void = P('void') +c_param_type = ( + ((P('Error') * fill * P('*') * fill) * Cc('error')) + + (C(c_id) * (ws ^ 1)) + ) +c_type = (C(c_void) * (ws ^ 1)) + c_param_type +c_param = Ct(c_param_type * C(c_id)) +c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) +c_params = Ct(c_void + c_param_list) +c_proto = Ct( + Cg(c_type, 'return_type') * Cg(c_id, 'name') * + fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * + 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 * 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) +functions = {} + +-- names of all headers relative to the source root (for inclusion in the +-- generated file) +headers = {} +-- output file(dispatch function + metadata serialized with msgpack) +outputf = arg[#arg] + +-- read each input file, parse and append to the api metadata +for i = 1, #arg - 1 do + local full_path = arg[i] + local parts = {} + for part in string.gmatch(full_path, '[^/]+') do + parts[#parts + 1] = part + end + headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] + + local input = io.open(full_path, 'rb') + local tmp = grammar:match(input:read('*all')) + for i = 1, #tmp do + local fn = tmp[i] + if not fn.noexport then + functions[#functions + 1] = tmp[i] + if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then + -- this function should receive the channel id + fn.receives_channel_id = true + -- remove the parameter since it won't be passed by the api client + table.remove(fn.parameters, 1) + end + if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then + -- function can fail if the last parameter type is 'Error' + fn.can_fail = true + -- remove the error parameter, msgpack has it's own special field + -- for specifying errors + fn.parameters[#fn.parameters] = nil + end + end + end + input:close() +end + + +-- start building the output +output = io.open(outputf, 'wb') + +output:write([[ +#include +#include +#include +#include +#include + +#include "nvim/map.h" +#include "nvim/log.h" +#include "nvim/vim.h" +#include "nvim/msgpack_rpc/helpers.h" +#include "nvim/api/private/dispatch.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" +]]) + +for i = 1, #headers do + if headers[i]:sub(-12) ~= '.generated.h' then + output:write('\n#include "nvim/'..headers[i]..'"') + end +end + +output:write([[ + + +static const uint8_t msgpack_metadata[] = { + +]]) +-- serialize the API metadata using msgpack and embed into the resulting +-- binary for easy querying by clients +packed = mpack.pack(functions) +for i = 1, #packed do + output:write(string.byte(packed, i)..', ') + if i % 10 == 0 then + output:write('\n ') + end +end +output:write([[ +}; + +void msgpack_rpc_init_function_metadata(Dictionary *metadata) +{ + msgpack_unpacked unpacked; + msgpack_unpacked_init(&unpacked); + if (msgpack_unpack_next(&unpacked, + (const char *)msgpack_metadata, + sizeof(msgpack_metadata), + NULL) != MSGPACK_UNPACK_SUCCESS) { + abort(); + } + Object functions; + msgpack_rpc_to_object(&unpacked.data, &functions); + msgpack_unpacked_destroy(&unpacked); + PUT(*metadata, "functions", functions); +} + +]]) + +local function real_type(type) + local rv = type + if typed_container:match(rv) then + if rv:match('Array') then + rv = 'Array' + else + rv = 'Dictionary' + end + end + return rv +end + +-- start the handler functions. Visit each function metadata to build the +-- handler function with code generated for validating arguments and calling to +-- 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') + end + + args[#args + 1] = converted + 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 + + -- 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(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') + 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(');\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:'); + + for j = 1, #fn.parameters do + local param = fn.parameters[j] + output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') + end + output:write('\n return ret;\n}\n\n'); +end + +-- Generate a function that initializes method names with handler functions +output:write([[ +static Map(String, MsgpackRpcRequestHandler) *methods = NULL; + +void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler) +{ + map_put(String, MsgpackRpcRequestHandler)(methods, method, handler); +} + +void msgpack_rpc_init_method_table(void) +{ + methods = map_new(String, MsgpackRpcRequestHandler)(); + +]]) + +-- Keep track of the maximum method name length in order to avoid walking +-- strings longer than that when searching for a method handler +local max_fname_len = 0 +for i = 1, #functions do + local fn = functions[i] + output:write(' msgpack_rpc_add_method_handler('.. + '(String) {.data = "'..fn.name..'", '.. + '.size = sizeof("'..fn.name..'") - 1}, '.. + '(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name.. + ', .async = '..tostring(fn.async)..'});\n') + + if #fn.name > max_fname_len then + max_fname_len = #fn.name + end +end + +output:write('\n}\n\n') + +output:write([[ +MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, + size_t name_len) +{ + String m = { + .data=(char *)name, + .size=MIN(name_len, ]]..max_fname_len..[[) + }; + MsgpackRpcRequestHandler rv = + map_get(String, MsgpackRpcRequestHandler)(methods, m); + + if (!rv.fn) { + rv.fn = msgpack_rpc_handle_missing_method; + } + + return rv; +} +]]) + +output:close() diff --git a/scripts/msgpack-gen.lua b/scripts/msgpack-gen.lua deleted file mode 100644 index 2da3c174f9..0000000000 --- a/scripts/msgpack-gen.lua +++ /dev/null @@ -1,313 +0,0 @@ -lpeg = require('lpeg') -mpack = require('mpack') - --- lpeg grammar for building api metadata from a set of header files. It --- ignores comments and preprocessor commands and parses a very small subset --- of C prototypes with a limited set of types -P, R, S = lpeg.P, lpeg.R, lpeg.S -C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg - -any = P(1) -- (consume one character) -letter = R('az', 'AZ') + S('_$') -alpha = letter + R('09') -nl = P('\r\n') + P('\n') -not_nl = any - nl -ws = S(' \t') + nl -fill = ws ^ 0 -c_comment = P('//') * (not_nl ^ 0) -c_preproc = P('#') * (not_nl ^ 0) -typed_container = - (P('ArrayOf(') + P('DictionaryOf(')) * ((any - P(')')) ^ 1) * P(')') -c_id = ( - typed_container + - (letter * (alpha ^ 0)) -) -c_void = P('void') -c_param_type = ( - ((P('Error') * fill * P('*') * fill) * Cc('error')) + - (C(c_id) * (ws ^ 1)) - ) -c_type = (C(c_void) * (ws ^ 1)) + c_param_type -c_param = Ct(c_param_type * C(c_id)) -c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0) -c_params = Ct(c_void + c_param_list) -c_proto = Ct( - Cg(c_type, 'return_type') * Cg(c_id, 'name') * - fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') * - 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 * 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) -functions = {} - --- names of all headers relative to the source root (for inclusion in the --- generated file) -headers = {} --- output file(dispatch function + metadata serialized with msgpack) -outputf = arg[#arg] - --- read each input file, parse and append to the api metadata -for i = 1, #arg - 1 do - local full_path = arg[i] - local parts = {} - for part in string.gmatch(full_path, '[^/]+') do - parts[#parts + 1] = part - end - headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts] - - local input = io.open(full_path, 'rb') - local tmp = grammar:match(input:read('*all')) - for i = 1, #tmp do - local fn = tmp[i] - if not fn.noexport then - functions[#functions + 1] = tmp[i] - if #fn.parameters ~= 0 and fn.parameters[1][2] == 'channel_id' then - -- this function should receive the channel id - fn.receives_channel_id = true - -- remove the parameter since it won't be passed by the api client - table.remove(fn.parameters, 1) - end - if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'error' then - -- function can fail if the last parameter type is 'Error' - fn.can_fail = true - -- remove the error parameter, msgpack has it's own special field - -- for specifying errors - fn.parameters[#fn.parameters] = nil - end - end - end - input:close() -end - - --- start building the output -output = io.open(outputf, 'wb') - -output:write([[ -#include -#include -#include -#include -#include - -#include "nvim/map.h" -#include "nvim/log.h" -#include "nvim/vim.h" -#include "nvim/msgpack_rpc/helpers.h" -#include "nvim/msgpack_rpc/defs.h" -#include "nvim/api/private/helpers.h" -#include "nvim/api/private/defs.h" -]]) - -for i = 1, #headers do - if headers[i]:sub(-12) ~= '.generated.h' then - output:write('\n#include "nvim/'..headers[i]..'"') - end -end - -output:write([[ - - -static const uint8_t msgpack_metadata[] = { - -]]) --- serialize the API metadata using msgpack and embed into the resulting --- binary for easy querying by clients -packed = mpack.pack(functions) -for i = 1, #packed do - output:write(string.byte(packed, i)..', ') - if i % 10 == 0 then - output:write('\n ') - end -end -output:write([[ -}; - -void msgpack_rpc_init_function_metadata(Dictionary *metadata) -{ - msgpack_unpacked unpacked; - msgpack_unpacked_init(&unpacked); - if (msgpack_unpack_next(&unpacked, - (const char *)msgpack_metadata, - sizeof(msgpack_metadata), - NULL) != MSGPACK_UNPACK_SUCCESS) { - abort(); - } - Object functions; - msgpack_rpc_to_object(&unpacked.data, &functions); - msgpack_unpacked_destroy(&unpacked); - PUT(*metadata, "functions", functions); -} - -]]) - -local function real_type(type) - local rv = type - if typed_container:match(rv) then - if rv:match('Array') then - rv = 'Array' - else - rv = 'Dictionary' - end - end - return rv -end - --- start the handler functions. Visit each function metadata to build the --- handler function with code generated for validating arguments and calling to --- 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') - end - - args[#args + 1] = converted - 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 - - -- 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(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') - 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(');\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:'); - - for j = 1, #fn.parameters do - local param = fn.parameters[j] - output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') - end - output:write('\n return ret;\n}\n\n'); -end - --- Generate a function that initializes method names with handler functions -output:write([[ -static Map(String, MsgpackRpcRequestHandler) *methods = NULL; - -void msgpack_rpc_add_method_handler(String method, MsgpackRpcRequestHandler handler) -{ - map_put(String, MsgpackRpcRequestHandler)(methods, method, handler); -} - -void msgpack_rpc_init_method_table(void) -{ - methods = map_new(String, MsgpackRpcRequestHandler)(); - -]]) - --- Keep track of the maximum method name length in order to avoid walking --- strings longer than that when searching for a method handler -local max_fname_len = 0 -for i = 1, #functions do - local fn = functions[i] - output:write(' msgpack_rpc_add_method_handler('.. - '(String) {.data = "'..fn.name..'", '.. - '.size = sizeof("'..fn.name..'") - 1}, '.. - '(MsgpackRpcRequestHandler) {.fn = handle_'.. fn.name.. - ', .async = '..tostring(fn.async)..'});\n') - - if #fn.name > max_fname_len then - max_fname_len = #fn.name - end -end - -output:write('\n}\n\n') - -output:write([[ -MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, - size_t name_len) -{ - String m = { - .data=(char *)name, - .size=MIN(name_len, ]]..max_fname_len..[[) - }; - MsgpackRpcRequestHandler rv = - map_get(String, MsgpackRpcRequestHandler)(methods, m); - - if (!rv.fn) { - rv.fn = msgpack_rpc_handle_missing_method; - } - - return rv; -} -]]) - -output:close() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 3385c0e462..71d48a5df1 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -11,12 +11,12 @@ 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(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.hsh) @@ -143,9 +143,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 ".") @@ -188,8 +192,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} + COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${GENERATED_API_DISPATCH} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} @@ -198,7 +202,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}" diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h new file mode 100644 index 0000000000..9047752026 --- /dev/null +++ b/src/nvim/api/private/dispatch.h @@ -0,0 +1,21 @@ +#ifndef NVIM_API_PRIVATE_DISPATCH_H +#define NVIM_API_PRIVATE_DISPATCH_H + +#include "nvim/api/private/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; + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "api/private/dispatch.h.generated.h" +#endif + +#endif // NVIM_API_PRIVATE_DISPATCH_H 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..ff92043677 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" diff --git a/src/nvim/map.h b/src/nvim/map.h index c7d9894bd1..ff8c1a8ca7 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) \ 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..bf324cbc3a 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -4,9 +4,9 @@ #include +#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" -- cgit From 3bd3b3b76859b3eef80fa4969147efa881b60f40 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 18 Jun 2016 12:06:50 +0200 Subject: api: auto generate api function wrappers for viml --- scripts/gendispatch.lua | 18 +++++++++----- scripts/geneval.lua | 21 ++++++++++++++--- src/nvim/CMakeLists.txt | 9 +++---- src/nvim/api/private/dispatch.h | 10 ++++---- src/nvim/eval.c | 52 +++++++++++++++++++++++++++-------------- src/nvim/eval.lua | 2 +- 6 files changed, 77 insertions(+), 35 deletions(-) diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 54bfdab45b..ce1d8be222 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -41,18 +41,20 @@ c_proto = Ct( ) grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) --- we need at least 2 arguments since the last one is the output file -assert(#arg >= 1) +-- we need at least 3 arguments since the last two are output files +assert(#arg >= 2) functions = {} -- names of all headers relative to the source root (for inclusion in the -- generated file) headers = {} --- output file(dispatch function + metadata serialized with msgpack) -outputf = arg[#arg] +-- output c file(dispatch function + metadata serialized with msgpack) +outputf = arg[#arg-1] +-- output mpack file (metadata) +mpack_outputf = arg[#arg] -- read each input file, parse and append to the api metadata -for i = 1, #arg - 1 do +for i = 1, #arg - 2 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -165,7 +167,7 @@ for i = 1, #functions do local fn = functions[i] local args = {} - output:write('static Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)') + output:write('Object handle_'..fn.name..'(uint64_t channel_id, uint64_t request_id, Array args, Error *error)') output:write('\n{') output:write('\n Object ret = NIL;') -- Declare/initialize variables that will hold converted arguments @@ -311,3 +313,7 @@ MsgpackRpcRequestHandler msgpack_rpc_get_handler_for(const char *name, ]]) output:close() + +mpack_output = io.open(mpack_outputf, 'wb') +mpack_output:write(packed) +mpack_output:close() diff --git a/scripts/geneval.lua b/scripts/geneval.lua index c9533d7908..396e7b81db 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -1,5 +1,8 @@ +mpack = require('mpack') + local nvimsrcdir = arg[1] local autodir = arg[2] +local metadata_file = arg[3] if nvimsrcdir == '--help' then print([[ @@ -18,9 +21,20 @@ local funcsfname = autodir .. '/funcs.generated.h' local funcspipe = io.open(funcsfname .. '.hsh', 'w') -local funcs = require('eval') +local funcs = require('eval').funcs + +local metadata = mpack.unpack(io.open(arg[3], 'rb'):read("*all")) + +for i,fun in ipairs(metadata) do + funcs['api_'..fun.name] = { + args=#fun.parameters, + func='api_wrapper', + data='handle_'..fun.name, + } +end + -for name, def in pairs(funcs.funcs) do +for name, def in pairs(funcs) do args = def.args or 0 if type(args) == 'number' then args = {args, args} @@ -28,7 +42,8 @@ for name, def in pairs(funcs.funcs) do args[2] = 'MAX_FUNC_ARGS' end func = def.func or ('f_' .. name) - local val = ('{ %s, %s, &%s }'):format(args[1], args[2], func) + data = def.data or "NULL" + local val = ('{ %s, %s, &%s, %s }'):format(args[1], args[2], func, data) funcspipe:write(name .. '\n' .. val .. '\n') end funcspipe:close() diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 71d48a5df1..8d0be4190c 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -14,6 +14,7 @@ set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto) set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) file(GLOB API_HEADERS api/*.h) file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) +set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack) set(HEADER_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendeclarations.lua) set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include) set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch.c) @@ -192,8 +193,8 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ${EASTASIANWIDTH_FILE} ) -add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${GENERATED_API_DISPATCH} +add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA} + COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${GENERATED_API_DISPATCH} ${API_METADATA} DEPENDS ${API_HEADERS} ${MSGPACK_RPC_HEADERS} @@ -220,10 +221,10 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} add_custom_command(OUTPUT ${GENERATED_FUNCS} COMMAND ${LUA_PRG} ${FUNCS_GENERATOR} - ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} + ${PROJECT_SOURCE_DIR}/src/nvim ${GENERATED_DIR} ${API_METADATA} COMMAND $ ${GENERATED_FUNCS_HASH_INPUT} ${GENERATED_FUNCS} functions functions VimLFuncDef "NOFUNC" - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} genhash + DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} genhash ) add_custom_command(OUTPUT ${GENERATED_EVENTS_ENUM} ${GENERATED_EVENTS_NAMES_MAP} diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h index 9047752026..d91456c306 100644 --- a/src/nvim/api/private/dispatch.h +++ b/src/nvim/api/private/dispatch.h @@ -3,13 +3,15 @@ #include "nvim/api/private/defs.h" +typedef Object (*ApiDispatchWrapper)(uint64_t channel_id, + uint64_t request_id, + Array args, + Error *error); + /// The rpc_method_handlers table, used in msgpack_rpc_dispatch(), stores /// functions of this type. typedef struct { - Object (*fn)(uint64_t channel_id, - uint64_t request_id, - Array args, - Error *error); + ApiDispatchWrapper fn; bool async; // function is always safe to run immediately instead of being // put in a request queue for handling when nvim waits for input. } MsgpackRpcRequestHandler; diff --git a/src/nvim/eval.c b/src/nvim/eval.c index c5b5866f56..f731d2406a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -445,13 +445,14 @@ typedef struct { } timer_T; /// Prototype of C function that implements VimL function -typedef void (*VimLFunc)(typval_T *args, typval_T *rvar); +typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, void *data); /// Structure holding VimL function definition typedef struct fst { uint8_t min_argc; ///< Minimal number of arguments. uint8_t max_argc; ///< Maximal number of arguments. VimLFunc func; ///< Function implementation. + void *data; ///< Userdata for function implementation. } VimLFuncDef; KHASH_MAP_INIT_STR(functions, VimLFuncDef) @@ -6981,7 +6982,7 @@ call_func ( } } else { // Find the function name in the table, call its implementation. - VimLFuncDef *const fdef = find_internal_func((char *) fname); + VimLFuncDef *const fdef = find_internal_func((char *)fname); if (fdef != NULL) { if (argcount < fdef->min_argc) { error = ERROR_TOOFEW; @@ -6989,7 +6990,7 @@ call_func ( error = ERROR_TOOMANY; } else { argvars[argcount].v_type = VAR_UNKNOWN; - fdef->func(argvars, rettv); + fdef->func(argvars, rettv, fdef->data); error = ERROR_NONE; } } @@ -7100,13 +7101,10 @@ static inline int get_float_arg(typval_T *argvars, float_T *f) // Some versions of glibc on i386 have an optimization that makes it harder to // call math functions indirectly from inside an inlined function, causing // compile-time errors. Avoid `inline` in that case. #3072 -#ifndef ARCH_32 -inline -#endif -static void float_op_wrapper(typval_T *argvars, typval_T *rettv, - float_T (*function)(float_T)) +static void float_op_wrapper(typval_T *argvars, typval_T *rettv, void *data) { float_T f; + float_T (*function)(float_T) = data; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) { @@ -7116,6 +7114,34 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, } } +static void api_wrapper(typval_T *argvars, typval_T *rettv, void *data) +{ + ApiDispatchWrapper fn = data; + + Array args = ARRAY_DICT_INIT; + + for (typval_T *tv = argvars; tv->v_type != VAR_UNKNOWN; tv++) { + ADD(args, vim_to_object(tv)); + } + + Error err = ERROR_INIT; + Object result = fn(-1, -1, args, &err); + + if (err.set) { + vim_report_error(cstr_as_string(err.msg)); + goto end; + } + + if (!object_to_vim(result, rettv, &err)) { + EMSG2(_("Error converting the call result: %s"), err.msg); + } + +end: + // All arguments were freed already, but we still need to free the array + xfree(args.items); + api_free_object(result); +} + /* * "abs(expr)" function */ @@ -7515,14 +7541,6 @@ 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 */ @@ -20115,7 +20133,7 @@ void free_all_functions(void) int translated_function_exists(char_u *name) { if (builtin_function(name, -1)) { - return find_internal_func((char *) name) != NULL; + return find_internal_func((char *)name) != NULL; } return find_func(name) != NULL; } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 627925cd58..bbac27c7db 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -33,7 +33,7 @@ return { assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, assert_true={args={1, 2}}, - atan={args=1}, + atan={args=1, func="float_op_wrapper", data="atan"}, atan2={args=2}, browse={args=4}, browsedir={args=2}, -- cgit From a2d25b7bf81728d913e7b317d33997c8b8268af2 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 19 Jun 2016 21:06:03 +0200 Subject: api: unify buffer numbers and window ids with handles also allow handle==0 meaning curbuf/curwin/curtab --- scripts/gendispatch.lua | 6 ++-- src/nvim/api/private/defs.h | 4 ++- src/nvim/api/private/handle.c | 16 ++++------ src/nvim/api/private/handle.h | 3 +- src/nvim/api/private/helpers.c | 12 +++++++ src/nvim/api/vim.c | 6 ++-- src/nvim/buffer.c | 20 ++++++------ src/nvim/buffer_defs.h | 48 +++++++++++++--------------- src/nvim/map.c | 5 ++- src/nvim/map.h | 1 + src/nvim/msgpack_rpc/helpers.c | 4 +-- src/nvim/terminal.c | 2 +- src/nvim/window.c | 25 ++++++++------- test/functional/api/server_requests_spec.lua | 4 +-- test/unit/buffer_spec.lua | 26 +++++++-------- 15 files changed, 98 insertions(+), 84 deletions(-) diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index ce1d8be222..9178996a56 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -193,9 +193,9 @@ for i = 1, #functions do 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;') + -- 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]..'");') diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 5fb95a163f..3e0819ba3a 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, 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..32cdb03130 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) { diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index ac7cc65ee4..d4d2b72429 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -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); } } @@ -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); } } @@ -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); } } 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/map.c b/src/nvim/map.c index ff92043677..73af487f90 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -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 ff8c1a8ca7..ba3e84cb31 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -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/helpers.c b/src/nvim/msgpack_rpc/helpers.c index bf324cbc3a..33e9bb1c07 100644 --- a/src/nvim/msgpack_rpc/helpers.c +++ b/src/nvim/msgpack_rpc/helpers.c @@ -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/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/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/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)) -- cgit From 87e054bb24cd4ba8cd06eb1a65f956c6bcce222d Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 18 Jun 2016 13:45:39 +0200 Subject: api: When calling get/set_lines from vimL, don't convert between "\n" and "\0". --- src/nvim/api/buffer.c | 24 ++++++++++++++---------- src/nvim/api/private/defs.h | 3 +++ src/nvim/eval.c | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index c3bc1f52af..029b645d3a 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -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 = buffer_get_lines(0, buffer, index, index+1, true, err); if (!err->set && slice.size) { rv = slice.items[0].data.string; @@ -88,7 +88,7 @@ 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); + buffer_set_lines(0, buffer, index, index+1, true, array, err); } /// Deletes a buffer line @@ -105,7 +105,7 @@ 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); + buffer_set_lines(0, buffer, index, index+1, true, array, err); } /// Retrieves a line range from the buffer @@ -130,7 +130,7 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - return buffer_get_lines(buffer, start , end, false, err); + return buffer_get_lines(0, buffer, start , end, false, err); } @@ -149,7 +149,8 @@ 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, +ArrayOf(String) buffer_get_lines(uint64_t channel_id, + Buffer buffer, Integer start, Integer end, Boolean strict_indexing, @@ -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; } @@ -235,7 +238,7 @@ void buffer_set_line_slice(Buffer buffer, { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - buffer_set_lines(buffer, start, end, false, replacement, err); + buffer_set_lines(0, buffer, start, end, false, replacement, err); } @@ -257,7 +260,8 @@ 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, +void buffer_set_lines(uint64_t channel_id, + Buffer buffer, Integer start, Integer end, Boolean strict_indexing, @@ -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; @@ -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); + buffer_set_lines(0, buffer, lnum, lnum, true, lines, err); } /// Return a tuple (row,col) representing the position of the named mark diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h index 3e0819ba3a..a6710193ff 100644 --- a/src/nvim/api/private/defs.h +++ b/src/nvim/api/private/defs.h @@ -33,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/eval.c b/src/nvim/eval.c index f731d2406a..46fc94006c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7125,7 +7125,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, void *data) } Error err = ERROR_INIT; - Object result = fn(-1, -1, args, &err); + Object result = fn(INVALID_CHANNEL, NO_RESPONSE, args, &err); if (err.set) { vim_report_error(cstr_as_string(err.msg)); -- cgit From 7e2348f2b1b487c875bbcf6c6711a276f9063040 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sun, 19 Jun 2016 16:41:08 +0200 Subject: eval: use gperf to generate the hash of builtin functions make api functions highlighted as builtins in vim.vim --- .ci/build.bat | 4 +- CMakeLists.txt | 2 + runtime/CMakeLists.txt | 4 +- scripts/geneval.lua | 29 +- scripts/genvimvim.lua | 9 +- src/genhash.c | 106 ----- src/nvim/CMakeLists.txt | 27 +- src/nvim/eval.c | 772 ++++++++++++++++--------------------- src/nvim/eval.lua | 34 +- src/nvim/lib/khash.h | 41 +- third-party/CMakeLists.txt | 13 + third-party/cmake/BuildGperf.cmake | 51 +++ 12 files changed, 470 insertions(+), 622 deletions(-) delete mode 100644 src/genhash.c create mode 100644 third-party/cmake/BuildGperf.cmake 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/scripts/geneval.lua b/scripts/geneval.lua index 396e7b81db..75a8bdfab3 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -3,6 +3,7 @@ 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([[ @@ -19,20 +20,34 @@ package.path = nvimsrcdir .. '/?.lua;' .. package.path local funcsfname = autodir .. '/funcs.generated.h' -local funcspipe = io.open(funcsfname .. '.hsh', 'w') +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 funcs['api_'..fun.name] = { args=#fun.parameters, func='api_wrapper', - data='handle_'..fun.name, + data='&handle_'..fun.name, } 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 @@ -43,7 +58,7 @@ for name, def in pairs(funcs) do end func = def.func or ('f_' .. name) data = def.data or "NULL" - local val = ('{ %s, %s, &%s, %s }'):format(args[1], args[2], func, data) - funcspipe:write(name .. '\n' .. val .. '\n') + gperfpipe:write(('%s, %s, %s, &%s, (FunPtr)%s\n') + :format(name, args[1], args[2], func, data)) end -funcspipe:close() +gperfpipe:close() diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 729749a52f..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 @@ -23,7 +26,6 @@ end local options = require('options') local auevents = require('auevents') local ex_cmds = require('ex_cmds') -local eval = require('eval') local cmd_kw = function(prev_cmd, cmd) if not prev_cmd then @@ -112,9 +114,9 @@ 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 name, def in pairs(eval.funcs) do +for name, def in pairs(funcs) do if name then if lld.line_length > 850 then w('\n' .. vimfun_start) @@ -122,7 +124,6 @@ for name, def in pairs(eval.funcs) do w(' ' .. name) end end -eval_fd:close() w('\n') syn_fd:close() diff --git a/src/genhash.c b/src/genhash.c deleted file mode 100644 index 649b8deb2e..0000000000 --- a/src/genhash.c +++ /dev/null @@ -1,106 +0,0 @@ -// Program used to generate static hashes -// -// Uses hashes from khash.h macros library. - -#include -#include -#include -#include - -#define USE_LIBC_ALLOCATOR -#include "nvim/lib/khash.h" - -KHASH_MAP_INIT_STR(hash, char *) - -#define CHECK_FAIL(cond, ...) \ - do { \ - if (cond) { \ - fprintf(stderr, __VA_ARGS__); \ - putc('\n', stderr); \ - return 1; \ - } \ - } while (0) - -int main(int argc, char **argv) -{ - if (argc == 2 && strcmp(argv[1], "--help") == 0) { - puts("Usage:"); - puts(" genhash SOURCE TARGET TYPE NAME VALTYPE NULLVAL"); - puts("Transforms keys and values in a form \"key\\nval\\n\" into a hash"); - puts("literal."); - puts(""); - puts("SOURCE is the file name to read keys and values from."); - puts("TARGET is the file name to write to."); - puts("TYPE is the name of the hash type (khash_t argument)."); - puts("NAME is the name of the generated hash."); - puts("VALTYPE is the name of the value type."); - puts("NULLVAL is the value used when no value is available."); - return 0; - } - - CHECK_FAIL(argc != 7, "Expecting six arguments, got %i.", argc); - - const char *const source = argv[1]; - const char *const target = argv[2]; - const char *const type = argv[3]; - const char *const name = argv[4]; - const char *const valtype = argv[5]; - const char *const nullval = argv[6]; - - FILE *fin = fopen(source, "r"); - CHECK_FAIL(!fin, "Failed to open source: %s.", strerror(errno)); - - char keybuf[80]; - char valbuf[4096]; - khash_t(hash) hash = KHASH_EMPTY_TABLE(hash); - while (fgets(keybuf, sizeof(keybuf), fin) != NULL) { - CHECK_FAIL(ferror(fin), "Failed to read key %i from source: %s", - (int) kh_size(&hash), strerror(ferror(fin))); - keybuf[strlen(keybuf) - 1] = 0; - CHECK_FAIL(!fgets(valbuf, sizeof(valbuf), fin), - "Failed to read value for key %i (%s): %s", - (int) kh_size(&hash), keybuf, (ferror(fin) - ? strerror(ferror(fin)) - : "EOF found")); - valbuf[strlen(valbuf) - 1] = 0; - char *const key_copy = strdup(keybuf); - CHECK_FAIL(!key_copy, "Failed to allocate memory for a key"); - int put_ret; - const khiter_t k = kh_put(hash, &hash, key_copy, &put_ret); - CHECK_FAIL(put_ret != 1, "Expecting unused non-empty bucket for key %s", - key_copy); - kh_value(&hash, k) = strdup(valbuf); - CHECK_FAIL(!kh_value(&hash, k), "Failed to allocate memory for a value"); - } - CHECK_FAIL(fclose(fin), "Failed to close source: %s", strerror(errno)); - - FILE *f = fopen(target, "w"); - CHECK_FAIL(!f, strerror(errno)); - fprintf(f, "static const khash_t(%s) %s = {", type, name); - fprintf(f, " .n_buckets = %i,\n", (int) hash.n_buckets); - fprintf(f, " .size = %i,\n", (int) hash.size); - fprintf(f, " .n_occupied = %i,\n", (int) hash.n_occupied); - fprintf(f, " .upper_bound = %i,\n", (int) hash.upper_bound); - fprintf(f, " .flags = (khint32_t[]) {\n"); - for (khint_t i = 0; i < kh_end(&hash); i++) { - fprintf(f, " %i,\n", (int) hash.flags[i]); - } - fprintf(f, " },\n"); - fprintf(f, " .keys = (const char*[]) {\n"); - for (khint_t i = 0; i < kh_end(&hash); i++) { - if (kh_exist(&hash, i)) { - fprintf(f, " \"%s\",\n", hash.keys[i]); - } else { - fprintf(f, " NULL,\n"); - } - } - fprintf(f, " },\n"); - fprintf(f, " .vals = (%s[]) {\n", valtype); - for (khint_t i = 0; i < kh_end(&hash); i++) { - fprintf(f, " %s,\n", (kh_exist(&hash, i) ? hash.vals[i] : nullval)); - } - fprintf(f, " },\n"); - fprintf(f, "};\n"); - fclose(f); - return 0; -} diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index 8d0be4190c..e36bf400cc 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -15,12 +15,13 @@ set(DISPATCH_GENERATOR ${PROJECT_SOURCE_DIR}/scripts/gendispatch.lua) file(GLOB API_HEADERS api/*.h) file(GLOB MSGPACK_RPC_HEADERS msgpack_rpc/*.h) set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack) +set(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.hsh) +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) @@ -39,9 +40,9 @@ set(UNICODEDATA_FILE ${UNICODE_DIR}/UnicodeData.txt) set(CASEFOLDING_FILE ${UNICODE_DIR}/CaseFolding.txt) set(EASTASIANWIDTH_FILE ${UNICODE_DIR}/EastAsianWidth.txt) set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h) -set(GENHASH_SOURCE ${PROJECT_SOURCE_DIR}/src/genhash.c) include_directories(${GENERATED_DIR}) +include_directories(${CACHED_GENERATED_DIR}) include_directories(${GENERATED_INCLUDES_DIR}) file(MAKE_DIRECTORY ${GENERATED_DIR}) @@ -118,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) @@ -210,7 +215,6 @@ list(APPEND NEOVIM_GENERATED_SOURCES "${GENERATED_EVENTS_NAMES_MAP}" "${GENERATED_OPTIONS}" "${GENERATED_UNICODE_TABLES}" - "${GENERATED_FUNCS}" ) add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} @@ -219,13 +223,18 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS} DEPENDS ${EX_CMDS_GENERATOR} ${EX_CMDS_DEFS_FILE} ) -add_custom_command(OUTPUT ${GENERATED_FUNCS} +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} - COMMAND $ - ${GENERATED_FUNCS_HASH_INPUT} ${GENERATED_FUNCS} functions functions VimLFuncDef "NOFUNC" - DEPENDS ${FUNCS_GENERATOR} ${EVAL_DEFS_FILE} ${API_METADATA} genhash + ${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} @@ -293,8 +302,6 @@ if(WIN32) DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() -add_executable(genhash ${GENHASH_SOURCE} ${NEOVIM_HEADERS}) - if(CLANG_ASAN_UBSAN) message(STATUS "Enabling Clang address sanitizer and undefined behavior sanitizer for nvim.") check_c_compiler_flag(-fno-sanitize-recover=all SANITIZE_RECOVER_ALL) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 46fc94006c..8313d726e7 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -444,15 +444,18 @@ 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, void *data); +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. - void *data; ///< Userdata for function implementation. + FunPtr data; ///< Userdata for function implementation. } VimLFuncDef; KHASH_MAP_INIT_STR(functions, VimLFuncDef) @@ -6696,7 +6699,6 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate) return OK; } -#define NOFUNC { 0, 0, NULL } #ifdef INCLUDE_GENERATED_DECLARATIONS # include "funcs.generated.h" #endif @@ -6718,19 +6720,19 @@ char_u *get_function_name(expand_T *xp, int idx) if (name != NULL) return name; } - while ((khiter_t) ++intidx < kh_end(&functions) - && !kh_exist(&functions, (khiter_t) intidx)) { + while ( (size_t)++intidx < ARRAY_SIZE(functions) + && functions[intidx].name[0] == '\0') { } - if ((khiter_t) intidx >= kh_end(&functions)) { + if ((size_t)intidx >= ARRAY_SIZE(functions)) { return NULL; } - const char *const key = kh_key(&functions, (khiter_t) intidx); + const char *const key = functions[intidx].name; const size_t key_len = strlen(key); memcpy(IObuff, key, key_len); IObuff[key_len] = '('; - if (kh_val(&functions, (khiter_t) intidx).max_argc == 0) { + if (functions[intidx].max_argc == 0) { IObuff[key_len + 1] = ')'; IObuff[key_len + 2] = NUL; } else { @@ -6769,8 +6771,8 @@ char_u *get_expr_name(expand_T *xp, int idx) static VimLFuncDef *find_internal_func(const char *const name) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL { - const khiter_t k = kh_get(functions, &functions, name); - return (k == kh_end(&functions) ? NULL : &kh_val(&functions, k)); + size_t len = strlen(name); + return find_internal_func_gperf(name, len); } /* @@ -6910,11 +6912,12 @@ call_func ( fname_buf[1] = KS_EXTRA; fname_buf[2] = (int)KE_SNR; int i = 3; - if (eval_fname_sid(name)) { /* "" or "s:" */ - if (current_SID <= 0) + if (eval_fname_sid(name)) { // "" 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); } } @@ -7101,10 +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 -static void float_op_wrapper(typval_T *argvars, typval_T *rettv, void *data) +static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; - float_T (*function)(float_T) = data; + float_T (*function)(float_T) = (float_T (*)(float_T))fptr; rettv->v_type = VAR_FLOAT; if (get_float_arg(argvars, &f) == OK) { @@ -7114,9 +7117,9 @@ static void float_op_wrapper(typval_T *argvars, typval_T *rettv, void *data) } } -static void api_wrapper(typval_T *argvars, typval_T *rettv, void *data) +static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - ApiDispatchWrapper fn = data; + ApiDispatchWrapper fn = (ApiDispatchWrapper)fptr; Array args = ARRAY_DICT_INIT; @@ -7145,10 +7148,10 @@ end: /* * "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; @@ -7163,18 +7166,10 @@ 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; @@ -7193,7 +7188,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); @@ -7201,7 +7196,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); @@ -7211,7 +7206,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; @@ -7266,7 +7261,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; } @@ -7274,13 +7269,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]); @@ -7292,7 +7287,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; @@ -7399,19 +7394,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; @@ -7432,7 +7427,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; @@ -7492,7 +7487,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); } @@ -7516,35 +7511,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); -} - /* * "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; @@ -7559,7 +7546,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; @@ -7568,9 +7555,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); } @@ -7606,7 +7593,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); } @@ -7614,7 +7601,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; @@ -7625,7 +7612,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; @@ -7675,7 +7662,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; @@ -7693,7 +7680,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; @@ -7723,7 +7710,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; @@ -7745,7 +7732,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; @@ -7784,7 +7771,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); } @@ -7792,7 +7779,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); } @@ -7832,7 +7819,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; @@ -7862,18 +7849,10 @@ static void f_call(typval_T *argvars, typval_T *rettv) (void)func_call(func, &argvars[1], selfdict, 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; } @@ -7881,7 +7860,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; @@ -7900,7 +7879,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; @@ -7918,7 +7897,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); } @@ -7926,7 +7905,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; @@ -7963,7 +7942,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; @@ -7992,7 +7971,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); } @@ -8000,7 +7979,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; @@ -8013,7 +7992,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; @@ -8061,31 +8040,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; @@ -8150,7 +8113,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; @@ -8174,7 +8137,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; @@ -8230,7 +8193,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; @@ -8246,7 +8209,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; @@ -8284,7 +8247,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; @@ -8329,7 +8292,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; @@ -8390,7 +8353,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; } @@ -8398,7 +8361,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)); } @@ -8406,7 +8369,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; @@ -8455,7 +8418,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; @@ -8493,7 +8456,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]; @@ -8505,7 +8468,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; @@ -8529,7 +8492,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; } @@ -8537,7 +8500,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]); @@ -8547,7 +8510,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; @@ -8579,7 +8542,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; @@ -8593,7 +8556,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; @@ -8653,18 +8616,10 @@ static void f_exists(typval_T *argvars, typval_T *rettv) rettv->vval.v_number = n; } -/* - * "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; @@ -8793,7 +8748,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"); @@ -8865,7 +8820,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]; @@ -8883,12 +8838,12 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv) } vim_feedkeys(cstr_as_string((char *)keys), - cstr_as_string((char *)flags), true); + 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 = @@ -8899,7 +8854,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); @@ -9114,7 +9069,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); } @@ -9122,7 +9077,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); } @@ -9130,7 +9085,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); } @@ -9138,7 +9093,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; @@ -9152,18 +9107,10 @@ 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; @@ -9178,7 +9125,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); @@ -9188,7 +9135,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; @@ -9239,7 +9186,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); } @@ -9247,7 +9194,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); } @@ -9255,7 +9202,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; @@ -9267,7 +9214,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; @@ -9320,7 +9267,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; @@ -9347,14 +9294,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; @@ -9386,7 +9333,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()]". */ @@ -9399,7 +9346,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; @@ -9475,7 +9422,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; @@ -9498,7 +9445,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; @@ -9551,7 +9498,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; @@ -9635,7 +9582,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; } @@ -9643,7 +9590,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); @@ -9657,7 +9604,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(); @@ -9666,7 +9613,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; } @@ -9674,7 +9621,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); @@ -9684,7 +9631,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; @@ -9693,7 +9640,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; @@ -9745,7 +9692,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; @@ -9868,7 +9815,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; @@ -9877,7 +9824,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"; @@ -9898,7 +9845,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]); @@ -9925,7 +9872,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]); @@ -9940,7 +9887,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; @@ -10016,7 +9963,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; @@ -10037,7 +9984,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; @@ -10086,7 +10033,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(); } @@ -10122,7 +10069,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); } @@ -10130,7 +10077,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); } @@ -10138,7 +10085,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; @@ -10152,7 +10099,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; @@ -10198,7 +10145,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; @@ -10230,7 +10177,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; @@ -10269,7 +10216,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); } @@ -10277,7 +10224,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; } @@ -10285,7 +10232,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; } @@ -10349,7 +10296,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); } @@ -10420,7 +10367,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; @@ -10464,7 +10411,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; @@ -10515,7 +10462,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 @@ -10528,7 +10475,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; @@ -10696,7 +10643,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)); @@ -10720,7 +10667,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; @@ -10813,7 +10760,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; @@ -10838,7 +10785,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; @@ -10864,7 +10811,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]; @@ -10891,7 +10838,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; @@ -10916,7 +10863,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; @@ -10935,7 +10882,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])); } @@ -10943,7 +10890,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])); } @@ -10951,7 +10898,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]; @@ -10963,7 +10910,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]; @@ -10993,7 +10940,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; @@ -11007,7 +10954,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; @@ -11138,7 +11085,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); } @@ -11146,7 +11093,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); } @@ -11154,7 +11101,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; @@ -11190,7 +11137,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; @@ -11206,7 +11153,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); @@ -11216,19 +11163,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; @@ -11267,7 +11214,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); } @@ -11275,7 +11222,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])); } @@ -11283,7 +11230,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; @@ -11395,13 +11342,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; @@ -11460,7 +11407,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; @@ -11485,7 +11432,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; @@ -11530,7 +11477,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; @@ -11617,7 +11564,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; @@ -11701,7 +11648,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; @@ -11729,7 +11676,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; @@ -11839,7 +11786,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; @@ -11867,7 +11814,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; @@ -11901,7 +11848,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); @@ -11910,7 +11857,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); } @@ -11918,7 +11865,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; @@ -11934,7 +11881,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: @@ -12005,7 +11952,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); } @@ -12013,7 +11960,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); } @@ -12021,7 +11968,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; @@ -12036,7 +11983,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; @@ -12052,7 +11999,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; @@ -12070,7 +12017,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); } @@ -12145,27 +12092,10 @@ 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); } @@ -12173,7 +12103,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); } @@ -12181,7 +12111,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); } @@ -12346,7 +12276,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); } @@ -12354,7 +12284,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 */ @@ -12397,7 +12327,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; @@ -12458,7 +12388,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); @@ -12480,7 +12410,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); @@ -12489,7 +12419,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); } @@ -12497,7 +12427,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); } @@ -12505,7 +12435,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); } @@ -12565,7 +12495,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); } @@ -12573,7 +12503,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); } @@ -12581,7 +12511,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]; @@ -12623,7 +12553,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]; @@ -12677,7 +12607,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) { @@ -12705,7 +12635,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) { @@ -12786,7 +12716,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; @@ -12804,7 +12734,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]; @@ -12828,7 +12758,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); @@ -12837,7 +12767,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]); @@ -12850,7 +12780,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; @@ -12865,7 +12795,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; @@ -12887,7 +12817,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; @@ -12913,7 +12843,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; @@ -12922,7 +12852,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); } @@ -12930,7 +12860,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); } @@ -12938,7 +12868,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; @@ -12973,7 +12903,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; @@ -13172,7 +13102,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; @@ -13218,7 +13148,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; @@ -13233,7 +13163,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; @@ -13318,7 +13248,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]; @@ -13332,7 +13262,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; @@ -13366,7 +13296,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 @@ -13540,7 +13470,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; @@ -13711,16 +13641,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; @@ -13756,7 +13678,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; @@ -13842,7 +13764,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; @@ -13901,8 +13823,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)); @@ -13911,7 +13840,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); } @@ -13920,7 +13849,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; @@ -13939,7 +13868,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; @@ -13966,7 +13895,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; } @@ -13974,7 +13903,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; } @@ -13982,7 +13911,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; @@ -13992,7 +13921,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; @@ -14085,7 +14014,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); } @@ -14093,7 +14022,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; @@ -14258,7 +14187,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; @@ -14281,7 +14210,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); @@ -14299,7 +14228,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 @@ -14327,7 +14256,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; @@ -14346,7 +14275,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; @@ -14388,7 +14317,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; @@ -14425,7 +14354,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; @@ -14435,7 +14364,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; @@ -14468,7 +14397,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; @@ -14593,7 +14522,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; @@ -14608,7 +14537,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; @@ -14699,7 +14628,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; @@ -14741,7 +14670,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); } @@ -14749,7 +14678,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; @@ -14844,7 +14773,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; @@ -14881,7 +14810,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); } @@ -14889,7 +14818,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); } @@ -14949,7 +14878,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); @@ -14962,7 +14891,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); @@ -14972,7 +14901,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); } @@ -14980,7 +14909,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; @@ -14990,22 +14919,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; @@ -15353,13 +15266,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); } @@ -15367,7 +15280,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; @@ -15382,7 +15295,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; @@ -15394,7 +15307,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; @@ -15438,7 +15351,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; @@ -15478,7 +15391,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; @@ -15546,18 +15459,10 @@ static void f_split(typval_T *argvars, typval_T *rettv) p_cpo = save_cpo; } -/* - * "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])); @@ -15568,7 +15473,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; @@ -15607,7 +15512,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; @@ -15658,7 +15563,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; @@ -15691,7 +15596,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); @@ -15700,7 +15605,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]))); @@ -15709,7 +15614,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; @@ -15734,7 +15639,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; @@ -15748,7 +15653,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]); @@ -15758,7 +15663,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; @@ -15798,7 +15703,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; @@ -15844,7 +15749,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])); @@ -15853,7 +15758,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); @@ -15882,7 +15787,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]; @@ -15903,7 +15808,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; @@ -15925,7 +15830,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; @@ -16001,7 +15906,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; @@ -16018,7 +15923,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; @@ -16065,7 +15970,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; @@ -16196,12 +16101,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); } @@ -16210,7 +16115,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; @@ -16235,7 +16140,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; @@ -16299,7 +16204,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; @@ -16316,7 +16221,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; @@ -16337,7 +16242,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; @@ -16353,14 +16258,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; @@ -16449,30 +16354,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; @@ -16527,7 +16415,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)); @@ -16616,7 +16504,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; @@ -16647,7 +16535,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])); @@ -16656,7 +16544,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; @@ -16753,18 +16641,10 @@ error: rettv->vval.v_string = ga.ga_data; } -/* - * "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; @@ -16800,7 +16680,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; { @@ -16823,7 +16703,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); @@ -16846,7 +16726,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); } @@ -16854,7 +16734,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; @@ -16873,7 +16753,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]; @@ -16890,26 +16770,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); @@ -16917,7 +16797,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); } @@ -16925,7 +16805,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; @@ -16939,7 +16819,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; @@ -16948,7 +16828,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; @@ -16962,7 +16842,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; @@ -16971,7 +16851,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; @@ -16982,7 +16862,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; @@ -17005,7 +16885,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; @@ -17055,7 +16935,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; @@ -17159,7 +17039,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; @@ -17171,14 +17051,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. @@ -17223,7 +17103,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); @@ -18305,7 +18185,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); } diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index bbac27c7db..9a3d73736f 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -15,7 +15,7 @@ end return { funcs={ abs={args=1}, - acos={args=1}, -- WJMc + acos={args=1, func="float_op_wrapper", data="&acos"}, -- WJMc add={args=2}, ['and']={args=2}, api_info={}, @@ -24,7 +24,7 @@ return { argidx={}, arglistid={args={0, 2}}, argv={args={0, 1}}, - asin={args=1}, -- WJMc + 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}}, @@ -33,7 +33,7 @@ return { assert_notequal={args={2, 3}}, assert_notmatch={args={2, 3}}, assert_true={args={1, 2}}, - atan={args=1, func="float_op_wrapper", data="atan"}, + atan={args=1, func="float_op_wrapper", data="&atan"}, atan2={args=2}, browse={args=4}, browsedir={args=2}, @@ -50,7 +50,7 @@ return { byteidx={args=2}, byteidxcomp={args=2}, call={args={2, 3}}, - ceil={args=1}, + ceil={args=1, func="float_op_wrapper", data="&ceil"}, changenr={}, char2nr={args={1, 2}}, cindent={args=1}, @@ -61,8 +61,8 @@ return { complete_check={}, confirm={args={1, 4}}, copy={args=1}, - cos={args=1}, - cosh={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}}, @@ -81,7 +81,7 @@ return { execute={args=1}, exepath={args=1}, exists={args=1}, - exp={args=1}, + exp={args=1, func="float_op_wrapper", data="&exp"}, expand={args={1, 3}}, extend={args={2, 3}}, feedkeys={args={1, 2}}, @@ -92,7 +92,7 @@ return { finddir={args={1, 3}}, findfile={args={1, 3}}, float2nr={args=1}, - floor={args=1}, + floor={args=1, func="float_op_wrapper", data="&floor"}, fmod={args=2}, fnameescape={args=1}, fnamemodify={args=2}, @@ -184,8 +184,8 @@ return { line2byte={args=1}, lispindent={args=1}, localtime={}, - log={args=1}, - log10={args=1}, + 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}}, @@ -223,7 +223,7 @@ return { ['repeat']={args=2}, resolve={args=1}, reverse={args=1}, - round={args=1}, + round={args=1, func="float_op_wrapper", data="&round"}, rpcnotify={args=varargs(2)}, rpcrequest={args=varargs(2)}, rpcstart={args={1, 2}}, @@ -257,14 +257,14 @@ return { shellescape={args={1, 2}}, shiftwidth={}, simplify={args=1}, - sin={args=1}, - sinh={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}, + sqrt={args=1, func="float_op_wrapper", data="&sqrt"}, str2float={args=1}, str2nr={args={1, 2}}, strchars={args={1,2}}, @@ -291,8 +291,8 @@ return { tabpagewinnr={args={1, 2}}, tagfiles={}, taglist={args=1}, - tan={args=1}, - tanh={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}, @@ -301,7 +301,7 @@ return { tolower={args=1}, toupper={args=1}, tr={args=3}, - trunc={args=1}, + trunc={args=1, func="float_op_wrapper", data="&trunc"}, type={args=1}, undofile={args=1}, undotree={}, diff --git a/src/nvim/lib/khash.h b/src/nvim/lib/khash.h index f8530be79a..8287cb14da 100644 --- a/src/nvim/lib/khash.h +++ b/src/nvim/lib/khash.h @@ -130,9 +130,7 @@ int main() { #include #include -#ifndef USE_LIBC_ALLOCATOR -# include "nvim/memory.h" -#endif +#include "nvim/memory.h" #include "nvim/func_attr.h" @@ -173,32 +171,17 @@ typedef khint_t khiter_t; #define kroundup32(x) (--(x), (x)|=(x)>>1, (x)|=(x)>>2, (x)|=(x)>>4, (x)|=(x)>>8, (x)|=(x)>>16, ++(x)) #endif -#ifdef USE_LIBC_ALLOCATOR -# ifndef kcalloc -# define kcalloc(N,Z) calloc(N,Z) -# endif -# ifndef kmalloc -# define kmalloc(Z) malloc(Z) -# endif -# ifndef krealloc -# define krealloc(P,Z) realloc(P,Z) -# endif -# ifndef kfree -# define kfree(P) free(P) -# endif -#else -# ifndef kcalloc -# define kcalloc(N,Z) xcalloc(N,Z) -# endif -# ifndef kmalloc -# define kmalloc(Z) xmalloc(Z) -# endif -# ifndef krealloc -# define krealloc(P,Z) xrealloc(P,Z) -# endif -# ifndef kfree -# define kfree(P) xfree(P) -# endif +#ifndef kcalloc +#define kcalloc(N,Z) xcalloc(N,Z) +#endif +#ifndef kmalloc +#define kmalloc(Z) xmalloc(Z) +#endif +#ifndef krealloc +#define krealloc(P,Z) xrealloc(P,Z) +#endif +#ifndef kfree +#define kfree(P) xfree(P) #endif #define __ac_HASH_UPPER 0.77 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() + -- cgit From e536abc1e1f59d1ac012e1be576bf55175e95443 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Mon, 20 Jun 2016 14:40:57 +0200 Subject: api: Allow blacklist functions that shouldn't be accesible from eval Blacklist deprecated functions and functions depending on channel_id --- scripts/gendispatch.lua | 1 + scripts/geneval.lua | 12 +++++++----- src/nvim/api/buffer.c | 28 +++++++++++++++++----------- src/nvim/api/ui.c | 7 ++++++- src/nvim/api/vim.c | 4 +++- src/nvim/func_attr.h | 1 + 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 9178996a56..68d4d44e2d 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -37,6 +37,7 @@ 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) diff --git a/scripts/geneval.lua b/scripts/geneval.lua index 75a8bdfab3..a6171f0993 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -25,11 +25,13 @@ 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 - funcs['api_'..fun.name] = { - args=#fun.parameters, - func='api_wrapper', - data='&handle_'..fun.name, - } + if not fun.noeval then + funcs['api_'..fun.name] = { + args=#fun.parameters, + func='api_wrapper', + data='&handle_'..fun.name, + } + end end local funcsdata = io.open(funcs_file, 'w') diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 029b645d3a..89fb7feaa9 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -56,6 +56,7 @@ Integer buffer_line_count(Buffer buffer, Error *err) /// @param[out] err Details of an error that may have occurred /// @return The line string String buffer_get_line(Buffer buffer, Integer index, Error *err) + FUNC_API_NOEVAL { String rv = { .size = 0 }; @@ -84,6 +85,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) /// @param line The new line. /// @param[out] err Details of an error that may have occurred void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) + FUNC_API_NOEVAL { Object l = STRING_OBJ(line); Array array = { .items = &l, .size = 1 }; @@ -102,6 +104,7 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) /// @param index The line index /// @param[out] err Details of an error that may have occurred void buffer_del_line(Buffer buffer, Integer index, Error *err) + FUNC_API_NOEVAL { Array array = ARRAY_DICT_INIT; index = convert_index(index); @@ -122,11 +125,12 @@ 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) + FUNC_API_NOEVAL { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; @@ -229,12 +233,13 @@ 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, + Error *err) + FUNC_API_NOEVAL { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; @@ -590,6 +595,7 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err) + FUNC_API_NOEVAL { // "lnum" will be the index of the line after inserting, // no matter if it is negative or not diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index 2b131443d3..5426ccc8aa 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")); @@ -133,6 +135,7 @@ void ui_detach(uint64_t channel_id, Error *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")); @@ -159,7 +162,9 @@ void ui_try_resize(uint64_t channel_id, Integer width, } 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 d4d2b72429..aa86e61e29 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -583,6 +583,7 @@ 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) + FUNC_API_NOEVAL { size_t length = (event.size < METHOD_MAXLEN ? event.size : METHOD_MAXLEN); char e[METHOD_MAXLEN + 1]; @@ -596,6 +597,7 @@ 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) + FUNC_API_NOEVAL { size_t length = (event.size < METHOD_MAXLEN ? event.size : @@ -624,7 +626,7 @@ Dictionary vim_get_color_map(void) Array vim_get_api_info(uint64_t channel_id) - FUNC_API_ASYNC + FUNC_API_ASYNC FUNC_API_NOEVAL { Array rv = ARRAY_DICT_INIT; 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) -- cgit From 1c22cab2fd283db49bfdbeaea490747574a36049 Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Tue, 28 Jun 2016 21:45:19 +0200 Subject: api: consistently use nvim_ prefix and update documentation --- runtime/doc/api.txt | 33 +++-- runtime/doc/eval.txt | 14 ++- runtime/doc/msgpack_rpc.txt | 38 +++--- scripts/dispatch_deprecated.lua | 77 ++++++++++++ scripts/gendispatch.lua | 212 ++++++++++++++++++++------------- scripts/geneval.lua | 2 +- src/nvim/CMakeLists.txt | 2 +- src/nvim/api/buffer.c | 118 +++++++++--------- src/nvim/api/private/helpers.c | 3 + src/nvim/api/tabpage.c | 17 +-- src/nvim/api/ui.c | 12 -- src/nvim/api/vim.c | 82 ++++++------- src/nvim/api/window.c | 30 ++--- src/nvim/eval.c | 8 +- src/nvim/tui/input.c | 4 +- test/functional/api/buffer_spec.lua | 134 +++++++++++---------- test/functional/api/vim_spec.lua | 5 + test/functional/helpers.lua | 33 +++-- test/functional/plugin/shada_spec.lua | 12 +- test/functional/shada/buffers_spec.lua | 4 +- 20 files changed, 492 insertions(+), 348 deletions(-) create mode 100644 scripts/dispatch_deprecated.lua 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/gendispatch.lua b/scripts/gendispatch.lua index 68d4d44e2d..2846aece5d 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -42,10 +42,13 @@ c_proto = Ct( ) grammar = Ct((c_proto + c_comment + c_preproc + ws) ^ 1) --- we need at least 3 arguments since the last two are output files -assert(#arg >= 2) +-- 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 = {} @@ -55,7 +58,7 @@ outputf = arg[#arg-1] mpack_outputf = arg[#arg] -- read each input file, parse and append to the api metadata -for i = 1, #arg - 2 do +for i = 2, #arg - 2 do local full_path = arg[i] local parts = {} for part in string.gmatch(full_path, '[^/]+') do @@ -87,6 +90,45 @@ for i = 1, #arg - 2 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') @@ -166,99 +208,101 @@ end -- the real API. for i = 1, #functions do local fn = functions[i] - 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') - - -- 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') + 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 + -- Now generate the cleanup label for freeing memory allocated for the + -- arguments + 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..');') + for j = 1, #fn.parameters do + local param = fn.parameters[j] + output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') + end + 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 @@ -284,7 +328,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 diff --git a/scripts/geneval.lua b/scripts/geneval.lua index a6171f0993..b1ba76296c 100644 --- a/scripts/geneval.lua +++ b/scripts/geneval.lua @@ -26,7 +26,7 @@ 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['api_'..fun.name] = { + funcs[fun.name] = { args=#fun.parameters, func='api_wrapper', data='&handle_'..fun.name, diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index e36bf400cc..3ae75c01c3 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -199,7 +199,7 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES} ) add_custom_command(OUTPUT ${GENERATED_API_DISPATCH} ${API_METADATA} - COMMAND ${LUA_PRG} ${DISPATCH_GENERATOR} ${API_HEADERS} ${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} diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 89fb7feaa9..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,23 +45,22 @@ 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 /// @param[out] err Details of an error that may have occurred /// @return The line string String buffer_get_line(Buffer buffer, Integer index, Error *err) - FUNC_API_NOEVAL { String rv = { .size = 0 }; index = convert_index(index); - Array slice = buffer_get_lines(0, 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; @@ -74,46 +73,44 @@ 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 /// @param line The new line. /// @param[out] err Details of an error that may have occurred void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) - FUNC_API_NOEVAL { Object l = STRING_OBJ(line); Array array = { .items = &l, .size = 1 }; index = convert_index(index); - buffer_set_lines(0, 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 void buffer_del_line(Buffer buffer, Integer index, Error *err) - FUNC_API_NOEVAL { Array array = ARRAY_DICT_INIT; index = convert_index(index); - buffer_set_lines(0, 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 @@ -130,11 +127,10 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer, Boolean include_start, Boolean include_end, Error *err) - FUNC_API_NOEVAL { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - return buffer_get_lines(0, buffer, start , end, false, err); + return nvim_buf_get_lines(0, buffer, start , end, false, err); } @@ -153,12 +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(uint64_t channel_id, - 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); @@ -219,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 @@ -237,13 +233,12 @@ void buffer_set_line_slice(Buffer buffer, Integer end, Boolean include_start, Boolean include_end, - ArrayOf(String) replacement, + ArrayOf(String) replacement, // NOLINT Error *err) - FUNC_API_NOEVAL { start = convert_index(start) + !include_start; end = convert_index(end) + include_end; - buffer_set_lines(0, buffer, start, end, false, replacement, err); + nvim_buf_set_lines(0, buffer, start, end, false, replacement, err); } @@ -265,13 +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(uint64_t channel_id, - 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); @@ -421,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); @@ -442,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); @@ -462,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); @@ -479,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); @@ -497,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); @@ -513,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); @@ -530,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); @@ -547,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); @@ -576,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; @@ -584,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 @@ -595,11 +590,10 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err) - FUNC_API_NOEVAL { // "lnum" will be the index of the line after inserting, // no matter if it is negative or not - buffer_set_lines(0, 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 @@ -608,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); @@ -658,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 @@ -676,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) { @@ -718,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/helpers.c b/src/nvim/api/private/helpers.c index 32cdb03130..7df2079d93 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -776,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 5426ccc8aa..56b41f1eea 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -127,11 +127,6 @@ 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) @@ -154,13 +149,6 @@ 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) FUNC_API_NOEVAL diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index aa86e61e29..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); @@ -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); @@ -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); @@ -582,7 +582,7 @@ 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); @@ -596,7 +596,7 @@ 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 ? @@ -608,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; @@ -625,7 +625,7 @@ Dictionary vim_get_color_map(void) } -Array vim_get_api_info(uint64_t channel_id) +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/eval.c b/src/nvim/eval.c index 8313d726e7..ac34ad4923 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7131,7 +7131,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) Object result = fn(INVALID_CHANNEL, NO_RESPONSE, args, &err); if (err.set) { - vim_report_error(cstr_as_string(err.msg)); + nvim_report_error(cstr_as_string(err.msg)); goto end; } @@ -8837,8 +8837,8 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) 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); } } @@ -13751,7 +13751,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (err.set) { - vim_report_error(cstr_as_string(err.msg)); + nvim_report_error(cstr_as_string(err.msg)); goto end; } 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/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/vim_spec.lua b/test/functional/api/vim_spec.lua index 848935fc0f..4195a614c3 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() 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() -- cgit From 98a08c3e5a73dafb2e2f1246f1a2ddd9e071798d Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Fri, 15 Jul 2016 20:35:31 +0200 Subject: api: add tests for calling the api from vimscript --- test/functional/eval/api_functions_spec.lua | 148 ++++++++++++++++++++++++++++ test/functional/viml/function_spec.lua | 9 -- 2 files changed, 148 insertions(+), 9 deletions(-) create mode 100644 test/functional/eval/api_functions_spec.lua 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')") + 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/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) -- cgit From acb7c826b3df50bd9825baf3b2ffaaa79c8b80df Mon Sep 17 00:00:00 2001 From: Björn Linse Date: Sat, 16 Jul 2016 16:51:56 +0200 Subject: api: fix leak when a api function is incorrectly called with a list. This applies both to msgpack-rpc and eval. --- scripts/gendispatch.lua | 6 ------ src/nvim/eval.c | 3 +-- src/nvim/msgpack_rpc/channel.c | 3 +-- test/functional/api/vim_spec.lua | 7 +++++++ 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/scripts/gendispatch.lua b/scripts/gendispatch.lua index 2846aece5d..12d6261b5a 100644 --- a/scripts/gendispatch.lua +++ b/scripts/gendispatch.lua @@ -293,14 +293,8 @@ for i = 1, #functions do 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:'); - for j = 1, #fn.parameters do - local param = fn.parameters[j] - output:write('\n api_free_'..string.lower(real_type(param[1]))..'(arg_'..j..');') - end output:write('\n return ret;\n}\n\n'); end end diff --git a/src/nvim/eval.c b/src/nvim/eval.c index ac34ad4923..bfe4707dab 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -7140,8 +7140,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) } end: - // All arguments were freed already, but we still need to free the array - xfree(args.items); + api_free_array(args); api_free_object(result); } 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/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index 4195a614c3..351094567a 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -303,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) -- cgit