aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval
diff options
context:
space:
mode:
authorJosh Rahm <rahm@google.com>2022-10-11 19:00:34 +0000
committerJosh Rahm <rahm@google.com>2022-10-11 19:00:34 +0000
commitc367400b73d207833d51e09d663f969ffab37531 (patch)
treebc26006d942509a92b514107f9d8dca6d3911128 /src/nvim/eval
parent4066fa85abef16fa23c30e94dc4d2bfb3b9c4545 (diff)
parent760b399f6c0c6470daa0663752bd22886997f9e6 (diff)
downloadrneovim-c367400b73d207833d51e09d663f969ffab37531.tar.gz
rneovim-c367400b73d207833d51e09d663f969ffab37531.tar.bz2
rneovim-c367400b73d207833d51e09d663f969ffab37531.zip
Merge remote-tracking branch 'upstream/master' into colorcolchar
Diffstat (limited to 'src/nvim/eval')
-rw-r--r--src/nvim/eval/decode.c6
-rw-r--r--src/nvim/eval/encode.c6
-rw-r--r--src/nvim/eval/executor.c3
-rw-r--r--src/nvim/eval/funcs.c384
-rw-r--r--src/nvim/eval/typval.c69
-rw-r--r--src/nvim/eval/typval.h409
-rw-r--r--src/nvim/eval/typval_defs.h399
-rw-r--r--src/nvim/eval/typval_encode.c.h2
-rw-r--r--src/nvim/eval/typval_encode.h2
-rw-r--r--src/nvim/eval/userfunc.c582
-rw-r--r--src/nvim/eval/userfunc.h71
-rw-r--r--src/nvim/eval/vars.c30
12 files changed, 967 insertions, 996 deletions
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 7b975ce775..94ef419bed 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -4,6 +4,7 @@
#include <msgpack.h>
#include <stddef.h>
+#include "klib/kvec.h"
#include "nvim/ascii.h"
#include "nvim/charset.h" // vim_str2nr
#include "nvim/eval.h"
@@ -11,7 +12,6 @@
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
#include "nvim/globals.h"
-#include "nvim/lib/kvec.h"
#include "nvim/macros.h"
#include "nvim/message.h"
#include "nvim/vim.h" // OK, FAIL
@@ -430,7 +430,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
const char ubuf[] = { t[1], t[2], t[3], t[4] };
t += 4;
uvarnumber_T ch;
- vim_str2nr((char_u *)ubuf, NULL, NULL,
+ vim_str2nr(ubuf, NULL, NULL,
STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true);
if (ch == 0) {
hasnul = true;
@@ -600,7 +600,7 @@ parse_json_number_check:
// Convert integer
varnumber_T nr;
int num_len;
- vim_str2nr((char_u *)s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true);
+ vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true);
if ((int)exp_num_len != num_len) {
semsg(_("E685: internal error: while converting number \"%.*s\" "
"to integer vim_str2nr consumed %i bytes in place of %zu"),
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index bb514fba47..27d35ea24f 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -13,6 +13,7 @@
#include <msgpack.h>
#include <stddef.h>
+#include "klib/kvec.h"
#include "nvim/ascii.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h" // vim_isprintc()
@@ -21,7 +22,6 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/garray.h"
-#include "nvim/lib/kvec.h"
#include "nvim/macros.h"
#include "nvim/math.h"
#include "nvim/mbyte.h"
@@ -219,7 +219,7 @@ bool encode_vim_list_to_buf(const list_T *const list, size_t *const ret_len, cha
}
len++;
if (TV_LIST_ITEM_TV(li)->vval.v_string != NULL) {
- len += STRLEN(TV_LIST_ITEM_TV(li)->vval.v_string);
+ len += strlen(TV_LIST_ITEM_TV(li)->vval.v_string);
}
});
if (len) {
@@ -281,7 +281,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s
state->offset = 0;
state->li_length = (TV_LIST_ITEM_TV(state->li)->vval.v_string == NULL
? 0
- : STRLEN(TV_LIST_ITEM_TV(state->li)->vval.v_string));
+ : strlen(TV_LIST_ITEM_TV(state->li)->vval.v_string));
}
}
*read_bytes = nbuf;
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index b461456a3a..0e0d0fe696 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -108,8 +108,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons
const char *tvs = tv_get_string(tv1);
char numbuf[NUMBUFLEN];
char *const s =
- (char *)concat_str((const char_u *)tvs, (const char_u *)tv_get_string_buf(tv2,
- numbuf));
+ concat_str(tvs, tv_get_string_buf(tv2, numbuf));
tv_clear(tv1);
tv1->v_type = VAR_STRING;
tv1->vval.v_string = s;
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 581f187140..a326c44371 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -195,15 +195,15 @@ int call_internal_func(const char_u *const fname, const int argcount, typval_T *
{
const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef == NULL) {
- return ERROR_UNKNOWN;
+ return FCERR_UNKNOWN;
} else if (argcount < fdef->min_argc) {
- return ERROR_TOOFEW;
+ return FCERR_TOOFEW;
} else if (argcount > fdef->max_argc) {
- return ERROR_TOOMANY;
+ return FCERR_TOOMANY;
}
argvars[argcount].v_type = VAR_UNKNOWN;
fdef->func(argvars, rettv, fdef->data);
- return ERROR_NONE;
+ return FCERR_NONE;
}
/// Invoke a method for base->method().
@@ -213,13 +213,13 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T
{
const EvalFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef == NULL) {
- return ERROR_UNKNOWN;
+ return FCERR_UNKNOWN;
} else if (fdef->base_arg == BASE_NONE) {
- return ERROR_NOTMETHOD;
+ return FCERR_NOTMETHOD;
} else if (argcount + 1 < fdef->min_argc) {
- return ERROR_TOOFEW;
+ return FCERR_TOOFEW;
} else if (argcount + 1 > fdef->max_argc) {
- return ERROR_TOOMANY;
+ return FCERR_TOOMANY;
}
typval_T argv[MAX_FUNC_ARGS + 1];
@@ -231,7 +231,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T
argv[argcount + 1].v_type = VAR_UNKNOWN;
fdef->func(argv, rettv, fdef->data);
- return ERROR_NONE;
+ return FCERR_NONE;
}
/// @return true for a non-zero Number and a non-empty String.
@@ -423,7 +423,7 @@ static buf_T *find_buffer(typval_T *avar)
FOR_ALL_BUFFERS(bp) {
if (bp->b_fname != NULL
&& (path_with_url(bp->b_fname) || bt_nofilename(bp))
- && STRCMP(bp->b_fname, avar->vval.v_string) == 0) {
+ && strcmp(bp->b_fname, avar->vval.v_string) == 0) {
buf = bp;
break;
}
@@ -840,7 +840,7 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
if (fp->col == MAXCOL) {
// '> can be MAXCOL, get the length of the line then
if (fp->lnum <= curbuf->b_ml.ml_line_count) {
- col = (colnr_T)STRLEN(ml_get(fp->lnum)) + 1;
+ col = (colnr_T)strlen(ml_get(fp->lnum)) + 1;
} else {
col = MAXCOL;
}
@@ -849,11 +849,12 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol)
// col(".") when the cursor is on the NUL at the end of the line
// because of "coladd" can be seen as an extra column.
if (virtual_active() && fp == &curwin->w_cursor) {
- char_u *p = get_cursor_pos_ptr();
+ char *p = get_cursor_pos_ptr();
if (curwin->w_cursor.coladd >=
- (colnr_T)win_chartabsize(curwin, p, curwin->w_virtcol - curwin->w_cursor.coladd)) {
+ (colnr_T)win_chartabsize(curwin, p,
+ curwin->w_virtcol - curwin->w_cursor.coladd)) {
int l;
- if (*p != NUL && p[(l = utfc_ptr2len((char *)p))] == NUL) {
+ if (*p != NUL && p[(l = utfc_ptr2len(p))] == NUL) {
col += l;
}
}
@@ -929,12 +930,12 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
// Return the current directory
- char_u *cwd = xmalloc(MAXPATHL);
- if (os_dirname(cwd, MAXPATHL) != FAIL) {
+ char *cwd = xmalloc(MAXPATHL);
+ if (os_dirname((char_u *)cwd, MAXPATHL) != FAIL) {
#ifdef BACKSLASH_IN_FILENAME
slash_adjust(cwd);
#endif
- rettv->vval.v_string = (char *)vim_strsave(cwd);
+ rettv->vval.v_string = xstrdup(cwd);
}
xfree(cwd);
@@ -1033,7 +1034,7 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (!error) {
- rettv->vval.v_number = do_dialog(type, NULL, (char_u *)message, (char_u *)buttons, def, NULL,
+ rettv->vval.v_number = do_dialog(type, NULL, (char *)message, (char *)buttons, def, NULL,
false);
}
}
@@ -1064,7 +1065,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const size_t len = STRLEN(expr);
while (*p != NUL) {
- if (mb_strnicmp(p, expr, len) == 0) {
+ if (mb_strnicmp((char *)p, (char *)expr, len) == 0) {
n++;
p += len;
} else {
@@ -1269,7 +1270,7 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// Otherwise use the column number as a byte offset.
static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
{
- long line, col;
+ long lnum, col;
long coladd = 0;
bool set_curswant = true;
@@ -1283,7 +1284,7 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
return;
}
- line = pos.lnum;
+ lnum = pos.lnum;
col = pos.col;
coladd = pos.coladd;
if (curswant >= 0) {
@@ -1292,10 +1293,15 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
}
} else if ((argvars[0].v_type == VAR_NUMBER || argvars[0].v_type == VAR_STRING)
&& (argvars[1].v_type == VAR_NUMBER || argvars[1].v_type == VAR_STRING)) {
- line = tv_get_lnum(argvars);
+ lnum = tv_get_lnum(argvars);
+ if (lnum < 0) {
+ semsg(_(e_invarg2), tv_get_string(&argvars[0]));
+ } else if (lnum == 0) {
+ lnum = curwin->w_cursor.lnum;
+ }
col = (long)tv_get_number_chk(&argvars[1], NULL);
if (charcol) {
- col = buf_charidx_to_byteidx(curbuf, (linenr_T)line, (int)col) + 1;
+ col = buf_charidx_to_byteidx(curbuf, (linenr_T)lnum, (int)col) + 1;
}
if (argvars[2].v_type != VAR_UNKNOWN) {
coladd = (long)tv_get_number_chk(&argvars[2], NULL);
@@ -1304,11 +1310,11 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol)
emsg(_(e_invarg));
return;
}
- if (line < 0 || col < 0 || coladd < 0) {
+ if (lnum < 0 || col < 0 || coladd < 0) {
return; // type error; errmsg already given
}
- if (line > 0) {
- curwin->w_cursor.lnum = (linenr_T)line;
+ if (lnum > 0) {
+ curwin->w_cursor.lnum = (linenr_T)lnum;
}
if (col > 0) {
curwin->w_cursor.col = (colnr_T)col - 1;
@@ -1343,7 +1349,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (pid == 0) {
emsg(_(e_invarg));
} else {
-#ifdef WIN32
+#ifdef MSWIN
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
if (hProcess != NULL) {
@@ -1694,7 +1700,7 @@ static void f_environ(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char c = env[i][len];
env[i][len] = NUL;
-#ifdef WIN32
+#ifdef MSWIN
// Upper-case all the keys for Windows so we can detect duplicates
char *const key = strcase_save(str, true);
#else
@@ -1771,7 +1777,7 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
/// "executable()" function
static void f_executable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- if (tv_check_for_string(&argvars[0]) == FAIL) {
+ if (tv_check_for_string_arg(argvars, 0) == FAIL) {
return;
}
@@ -1900,7 +1906,7 @@ static void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "exepath()" function
static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- if (tv_check_for_nonempty_string(&argvars[0]) == FAIL) {
+ if (tv_check_for_nonempty_string_arg(argvars, 0) == FAIL) {
return;
}
@@ -1937,9 +1943,14 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
xfree(exp);
}
} else if (*p == '&' || *p == '+') { // Option.
- n = (get_option_tv(&p, NULL, true) == OK);
- if (*skipwhite(p) != NUL) {
- n = false; // Trailing garbage.
+ bool working = (*p == '+'); // whether option needs to be working
+ int opt_flags;
+
+ if (find_option_end(&p, &opt_flags) != NULL) {
+ int opt_idx = findoption(p);
+ n = (opt_idx >= 0 && (!working || get_varp_scope(get_option(opt_idx), opt_flags) != NULL));
+ } else {
+ n = false;
}
} else if (*p == '*') { // Internal or user defined function.
n = function_exists(p + 1, false);
@@ -2015,10 +2026,9 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
options += WILD_ICASE;
}
if (rettv->v_type == VAR_STRING) {
- rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)s, NULL, options,
- WILD_ALL);
+ rettv->vval.v_string = ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL);
} else {
- ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP);
+ ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
for (int i = 0; i < xpc.xp_numfiles; i++) {
tv_list_append_string(rettv->vval.v_list,
@@ -2209,7 +2219,7 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
{
const char *const p = tv_get_string(&argvars[0]);
rettv->vval.v_number =
- (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p));
+ (*p && !os_isdir(p) && os_file_is_readable(p));
}
/// @return 0 for not writable
@@ -2436,7 +2446,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
pt = argvars[0].vval.v_partial;
} else {
CLEAR_FIELD(fref_pt);
- fref_pt.pt_name = (char_u *)argvars[0].vval.v_string;
+ fref_pt.pt_name = argvars[0].vval.v_string;
pt = &fref_pt;
}
@@ -2578,9 +2588,8 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli
}
} else {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string =
- (char *)((start >= 1 && start <= buf->b_ml.ml_line_count)
- ? vim_strsave(ml_get_buf(buf, start, false)) : NULL);
+ rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count)
+ ? xstrdup(ml_get_buf(buf, start, false)) : NULL);
}
}
@@ -2720,40 +2729,6 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until());
}
-/// "getcmdcompltype()" function
-static void f_getcmdcompltype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)get_cmdline_completion();
-}
-
-/// "getcmdline()" function
-static void f_getcmdline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)get_cmdline_str();
-}
-
-/// "getcmdpos()" function
-static void f_getcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- rettv->vval.v_number = get_cmdline_pos() + 1;
-}
-
-/// "getcmdscreenpos()" function
-static void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- rettv->vval.v_number = get_cmdline_screen_pos() + 1;
-}
-
-/// "getcmdtype()" function
-static void f_getcmdtype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = xmallocz(1);
- rettv->vval.v_string[0] = (char)get_cmdline_type();
-}
-
/// "getcmdwintype()" function
static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -2921,7 +2896,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
FileInfo file_info;
if (os_fileinfo(fname, &file_info)) {
uint64_t filesize = os_fileinfo_size(&file_info);
- if (os_isdir((const char_u *)fname)) {
+ if (os_isdir(fname)) {
rettv->vval.v_number = 0;
} else {
rettv->vval.v_number = (varnumber_T)filesize;
@@ -2952,7 +2927,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "getftype({fname})" function
static void f_getftype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char_u *type = NULL;
+ char *type = NULL;
char *t;
const char *fname = tv_get_string(&argvars[0]);
@@ -2978,9 +2953,9 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
} else {
t = "other";
}
- type = vim_strsave((char_u *)t);
+ type = xstrdup(t);
}
- rettv->vval.v_string = (char *)type;
+ rettv->vval.v_string = type;
}
/// "getjumplist()" function
@@ -3474,11 +3449,11 @@ static void f_glob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
options += WILD_ICASE;
}
if (rettv->v_type == VAR_STRING) {
- rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)
- tv_get_string(&argvars[0]), NULL, options,
- WILD_ALL);
+ rettv->vval.v_string = ExpandOne(&xpc, (char *)
+ tv_get_string(&argvars[0]), NULL, options,
+ WILD_ALL);
} else {
- ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options,
+ ExpandOne(&xpc, (char *)tv_get_string(&argvars[0]), NULL, options,
WILD_ALL_KEEP);
tv_list_alloc_ret(rettv, xpc.xp_numfiles);
for (int i = 0; i < xpc.xp_numfiles; i++) {
@@ -3524,7 +3499,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (file != NULL && !error) {
garray_T ga;
ga_init(&ga, (int)sizeof(char_u *), 10);
- globpath((char *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags);
+ globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags);
if (rettv->v_type == VAR_STRING) {
rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n");
@@ -3567,7 +3542,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
#ifdef UNIX
"unix",
#endif
-#if defined(WIN32)
+#if defined(MSWIN)
"win32",
#endif
#ifdef _WIN64
@@ -3882,7 +3857,7 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
os_get_hostname(hostname, 256);
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)vim_strsave((char_u *)hostname);
+ rettv->vval.v_string = xstrdup(hostname);
}
/// iconv() function
@@ -3895,17 +3870,19 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *const str = tv_get_string(&argvars[0]);
char buf1[NUMBUFLEN];
- char_u *const from = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[1], buf1)));
+ char_u *const from =
+ (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[1], buf1)));
char buf2[NUMBUFLEN];
- char_u *const to = enc_canonize(enc_skip((char_u *)tv_get_string_buf(&argvars[2], buf2)));
+ char_u *const to =
+ (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[2], buf2)));
vimconv.vc_type = CONV_NONE;
- convert_setup(&vimconv, from, to);
+ convert_setup(&vimconv, (char *)from, (char *)to);
// If the encodings are equal, no conversion needed.
if (vimconv.vc_type == CONV_NONE) {
rettv->vval.v_string = xstrdup(str);
} else {
- rettv->vval.v_string = (char *)string_convert(&vimconv, (char_u *)str, NULL);
+ rettv->vval.v_string = string_convert(&vimconv, (char *)str, NULL);
}
convert_setup(&vimconv, NULL, NULL);
@@ -4162,7 +4139,7 @@ static void f_invert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "isdirectory()" function
static void f_isdirectory(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0]));
+ rettv->vval.v_number = os_isdir(tv_get_string(&argvars[0]));
}
/// "islocked()" function
@@ -4290,7 +4267,7 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
static const char *ignored_env_vars[] = {
-#ifndef WIN32
+#ifndef MSWIN
"COLUMNS",
"LINES",
"TERMCAP",
@@ -4302,7 +4279,7 @@ static const char *ignored_env_vars[] = {
/// According to comments in src/win/process.c of libuv, Windows has a few
/// "essential" environment variables.
static const char *required_env_vars[] = {
-#ifdef WIN32
+#ifdef MSWIN
"HOMEDRIVE",
"HOMEPATH",
"LOGONSERVER",
@@ -4341,7 +4318,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
tv_dict_item_remove(env, dv);
}
}
-#ifndef WIN32
+#ifndef MSWIN
// Set COLORTERM to "truecolor" if termguicolors is set and 256
// otherwise, but only if it was set in the parent terminal at all
dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM"));
@@ -4376,7 +4353,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
}
if (job_env) {
-#ifdef WIN32
+#ifdef MSWIN
TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, {
// Always use upper-case keys for Windows so we detect duplicate keys
char *const key = strcase_save((const char *)var->di_key, true);
@@ -4476,7 +4453,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
-#ifdef WIN32
+#ifdef MSWIN
if (pty && overlapped) {
semsg(_(e_invarg2),
"job cannot have both 'pty' and 'overlapped' options set");
@@ -4489,7 +4466,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir((const char_u *)cwd)) {
+ if (!os_isdir(cwd)) {
semsg(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@@ -4706,6 +4683,20 @@ static void f_json_encode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_string = encode_tv2json(&argvars[0], NULL);
}
+/// "keytrans()" function
+static void f_keytrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->v_type = VAR_STRING;
+ if (tv_check_for_string_arg(argvars, 0) == FAIL
+ || argvars[0].vval.v_string == NULL) {
+ return;
+ }
+ // Need to escape K_SPECIAL for mb_unescape().
+ char *escaped = vim_strsave_escape_ks(argvars[0].vval.v_string);
+ rettv->vval.v_string = str2special_save(escaped, true, true);
+ xfree(escaped);
+}
+
/// "last_buffer_nr()" function.
static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -5017,9 +5008,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
li = TV_LIST_ITEM_NEXT(l, li);
idx++;
} else {
- startcol = (colnr_T)(regmatch.startp[0]
- + utfc_ptr2len((char *)regmatch.startp[0]) - str);
- if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) {
+ startcol = (colnr_T)((char_u *)regmatch.startp[0]
+ + utfc_ptr2len(regmatch.startp[0]) - str);
+ if (startcol > (colnr_T)len || str + startcol <= (char_u *)regmatch.startp[0]) {
match = false;
break;
}
@@ -5038,8 +5029,8 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]);
TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz((const char *)regmatch.startp[0], rd);
- TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)(regmatch.startp[0] - expr);
- TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - expr);
+ TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)((char_u *)regmatch.startp[0] - expr);
+ TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - (char *)expr);
if (l != NULL) {
TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx;
}
@@ -5074,10 +5065,10 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv,
} else {
if (type == kSomeMatch) {
rettv->vval.v_number =
- (varnumber_T)(regmatch.startp[0] - str);
+ (varnumber_T)((char_u *)regmatch.startp[0] - str);
} else {
rettv->vval.v_number =
- (varnumber_T)(regmatch.endp[0] - str);
+ (varnumber_T)(regmatch.endp[0] - (char *)str);
}
rettv->vval.v_number += (varnumber_T)(str - expr);
}
@@ -5416,7 +5407,7 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
lnum = 0;
break;
}
- if (*skipwhite((char *)ml_get(lnum)) != NUL) {
+ if (*skipwhite(ml_get(lnum)) != NUL) {
break;
}
}
@@ -5474,11 +5465,11 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
rettv->v_type = VAR_STRING;
- const char_u *p = (char_u *)tv_get_string_chk(&argvars[0]);
+ const char *p = tv_get_string_chk(&argvars[0]);
if (p == NULL) {
rettv->vval.v_string = NULL;
} else {
- rettv->vval.v_string = (char *)vim_strsave(p);
+ rettv->vval.v_string = xstrdup(p);
shorten_dir_len((char_u *)rettv->vval.v_string, trim_len);
}
}
@@ -5504,7 +5495,7 @@ static void f_prevnonblank(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
lnum = 0;
} else {
- while (lnum >= 1 && *skipwhite((char *)ml_get(lnum)) == NUL) {
+ while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) {
lnum--;
}
}
@@ -5596,7 +5587,7 @@ static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, EvalFuncData
return;
}
- rettv->vval.v_string = (char *)vim_strsave(buf_prompt_text(buf));
+ rettv->vval.v_string = xstrdup(buf_prompt_text(buf));
}
/// "prompt_setprompt({buffer}, {text})" function
@@ -5900,9 +5891,9 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool binary = false;
bool blob = false;
FILE *fd;
- char_u buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1
+ char buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1
int io_size = sizeof(buf);
- char_u *prev = NULL; // previously read bytes, if any
+ char *prev = NULL; // previously read bytes, if any
long prevlen = 0; // length of data in prev
long prevsize = 0; // size of prev buffer
long maxline = MAXLNUM;
@@ -5922,7 +5913,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// their own about CR-LF conversion.
const char *const fname = tv_get_string(&argvars[0]);
- if (os_isdir((const char_u *)fname)) {
+ if (os_isdir(fname)) {
semsg(_(e_isadir2), fname);
return;
}
@@ -5953,13 +5944,13 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// - an incomplete line gets written
// - a "binary" file gets an empty line at the end if it ends in a
// newline.
- char_u *p; // Position in buf.
- char_u *start; // Start of current line.
+ char *p; // Position in buf.
+ char *start; // Start of current line.
for (p = buf, start = buf;
p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary));
p++) {
if (*p == '\n' || readlen <= 0) {
- char_u *s = NULL;
+ char *s = NULL;
size_t len = (size_t)(p - start);
// Finished a line. Remove CRs before NL.
@@ -5976,7 +5967,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (prevlen == 0) {
assert(len < INT_MAX);
- s = vim_strnsave(start, len);
+ s = xstrnsave(start, len);
} else {
// Change "prev" buffer to be the right size. This way
// the bytes are only copied once, and very long lines are
@@ -5991,7 +5982,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
tv_list_append_owned_tv(l, (typval_T) {
.v_type = VAR_STRING,
.v_lock = VAR_UNLOCKED,
- .vval.v_string = (char *)s,
+ .vval.v_string = s,
});
start = p + 1; // Step over newline.
@@ -6011,18 +6002,18 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
*p = '\n';
// Check for utf8 "bom"; U+FEFF is encoded as EF BB BF. Do this
// when finding the BF and check the previous two bytes.
- } else if (*p == 0xbf && !binary) {
+ } else if ((uint8_t)(*p) == 0xbf && !binary) {
// Find the two bytes before the 0xbf. If p is at buf, or buf + 1,
// these may be in the "prev" string.
- char_u back1 = p >= buf + 1 ? p[-1]
+ char back1 = p >= buf + 1 ? p[-1]
: prevlen >= 1 ? prev[prevlen - 1] : NUL;
- char_u back2 = p >= buf + 2 ? p[-2]
+ char back2 = p >= buf + 2 ? p[-2]
: p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1]
: prevlen >=
- 2 ? prev[prevlen - 2] : NUL;
+ 2 ? prev[prevlen - 2] : NUL;
- if (back2 == 0xef && back1 == 0xbb) {
- char_u *dest = p - 2;
+ if ((uint8_t)back2 == 0xef && (uint8_t)back1 == 0xbb) {
+ char *dest = p - 2;
// Usually a BOM is at the beginning of a file, and so at
// the beginning of a line; then we can just step over it.
@@ -6258,8 +6249,8 @@ static void f_rename(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = -1;
} else {
char buf[NUMBUFLEN];
- rettv->vval.v_number = vim_rename((const char_u *)tv_get_string(&argvars[0]),
- (const char_u *)tv_get_string_buf(&argvars[1], buf));
+ rettv->vval.v_number = vim_rename(tv_get_string(&argvars[0]),
+ tv_get_string_buf(&argvars[1], buf));
}
}
@@ -6305,7 +6296,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
const char *fname = tv_get_string(&argvars[0]);
-#ifdef WIN32
+#ifdef MSWIN
char *v = os_resolve_shortcut(fname);
if (v == NULL) {
if (os_is_reparse_point_include(fname)) {
@@ -6374,7 +6365,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (*q != NUL) {
cpy = remain;
remain = (remain
- ? (char *)concat_str((char_u *)q - 1, (char_u *)remain)
+ ? concat_str(q - 1, remain)
: xstrdup(q - 1));
xfree(cpy);
q[-1] = NUL;
@@ -6433,7 +6424,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
&& (p[2] == NUL
|| vim_ispathsep(p[2])))))) {
// Prepend "./".
- cpy = (char *)concat_str((const char_u *)"./", (const char_u *)p);
+ cpy = concat_str("./", p);
xfree(p);
p = cpy;
} else if (!is_relative_to_current) {
@@ -6517,8 +6508,8 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
funcexe_T funcexe = FUNCEXE_INIT;
- funcexe.evaluate = true;
- funcexe.partial = partial;
+ funcexe.fe_evaluate = true;
+ funcexe.fe_partial = partial;
typval_T initial;
typval_T argv[3];
@@ -7070,7 +7061,7 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
int pcc[MAX_MCO];
- int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + (size_t)col], pcc);
+ int c = utfc_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col], pcc);
int composing_len = 0;
while (pcc[composing_len] != 0) {
composing_len++;
@@ -7090,32 +7081,6 @@ static void f_screencol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = ui_current_col() + 1;
}
-/// "screenpos({winid}, {lnum}, {col})" function
-static void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- tv_dict_alloc_ret(rettv);
- dict_T *dict = rettv->vval.v_dict;
-
- win_T *wp = find_win_by_nr_or_id(&argvars[0]);
- if (wp == NULL) {
- return;
- }
-
- pos_T pos = {
- .lnum = (linenr_T)tv_get_number(&argvars[1]),
- .col = (colnr_T)tv_get_number(&argvars[2]) - 1,
- .coladd = 0
- };
- int row = 0;
- int scol = 0, ccol = 0, ecol = 0;
- textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
-
- tv_dict_add_nr(dict, S_LEN("row"), row);
- tv_dict_add_nr(dict, S_LEN("col"), scol);
- tv_dict_add_nr(dict, S_LEN("curscol"), ccol);
- tv_dict_add_nr(dict, S_LEN("endcol"), ecol);
-}
-
/// "screenrow()" function
static void f_screenrow(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -7138,7 +7103,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
return;
}
- rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + (size_t)col]);
+ rettv->vval.v_string = xstrdup((char *)grid->chars[grid->line_offset[row] + (size_t)col]);
}
/// "search()" function
@@ -7603,7 +7568,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false);
if (csearch != NULL) {
int pcc[MAX_MCO];
- const int c = utfc_ptr2char(csearch, pcc);
+ const int c = utfc_ptr2char((char *)csearch, pcc);
set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch));
}
@@ -7619,16 +7584,6 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt
}
}
-/// "setcmdpos()" function
-static void f_setcmdpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
-{
- const int pos = (int)tv_get_number(&argvars[0]) - 1;
-
- if (pos >= 0) {
- rettv->vval.v_number = set_cmdline_pos(pos);
- }
-}
-
/// "setcursorcharpos" function
static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -7851,7 +7806,7 @@ free_lstval:
if (strval == NULL) {
return;
}
- write_reg_contents_ex(regname, (const char_u *)strval, (ssize_t)STRLEN(strval),
+ write_reg_contents_ex(regname, strval, (ssize_t)strlen(strval),
append, yank_type, (colnr_T)block_len);
}
if (pointreg != 0) {
@@ -8093,7 +8048,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
// Find the start and length of the badly spelled word.
len = spell_move_to(curwin, FORWARD, true, true, &attr);
if (len != 0) {
- word = (char *)get_cursor_pos_ptr();
+ word = get_cursor_pos_ptr();
curwin->w_set_curswant = true;
}
} else if (*curbuf->b_s.b_p_spl != NUL) {
@@ -8236,11 +8191,11 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
break;
}
// Advance to just after the match.
- if (regmatch.endp[0] > (char_u *)str) {
+ if (regmatch.endp[0] > str) {
col = 0;
} else {
// Don't get stuck at the same match.
- col = utfc_ptr2len((char *)regmatch.endp[0]);
+ col = utfc_ptr2len(regmatch.endp[0]);
}
str = (const char *)regmatch.endp[0];
}
@@ -8345,7 +8300,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
break;
}
varnumber_T n;
- vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false);
+ vim_str2nr((char *)p, NULL, NULL, what, &n, NULL, 0, false);
// Text after the number is silently ignored.
if (isneg) {
rettv->vval.v_number = -n;
@@ -8375,13 +8330,12 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_string = xstrdup(_("(Invalid)"));
} else {
vimconv_T conv;
- char_u *enc;
conv.vc_type = CONV_NONE;
- enc = enc_locale();
- convert_setup(&conv, (char_u *)p_enc, enc);
+ char *enc = (char *)enc_locale();
+ convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
- p = (char *)string_convert(&conv, (char_u *)p, NULL);
+ p = string_convert(&conv, p, NULL);
}
char result_buf[256];
if (p != NULL) {
@@ -8393,9 +8347,9 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (conv.vc_type != CONV_NONE) {
xfree(p);
}
- convert_setup(&conv, enc, (char_u *)p_enc);
+ convert_setup(&conv, enc, p_enc);
if (conv.vc_type != CONV_NONE) {
- rettv->vval.v_string = (char *)string_convert(&conv, (char_u *)result_buf, NULL);
+ rettv->vval.v_string = string_convert(&conv, result_buf, NULL);
} else {
rettv->vval.v_string = xstrdup(result_buf);
}
@@ -8421,7 +8375,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- const size_t len = STRLEN(str);
+ const size_t len = strlen(str);
size_t byteidx = 0;
while (charidx >= 0 && byteidx < len) {
@@ -8512,7 +8466,7 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, EvalFuncData f
col = (int)tv_get_number(&argvars[1]);
}
- rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col);
+ rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char *)s) - col);
}
/// "strwidth()" function
@@ -8527,7 +8481,7 @@ static void f_strwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
const char *const p = tv_get_string(&argvars[0]);
- const size_t slen = STRLEN(p);
+ const size_t slen = strlen(p);
int nbyte = 0;
bool error = false;
@@ -8638,10 +8592,10 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
vimconv_T conv = {
.vc_type = CONV_NONE,
};
- char_u *enc = enc_locale();
- convert_setup(&conv, (char_u *)p_enc, enc);
+ char *enc = (char *)enc_locale();
+ convert_setup(&conv, p_enc, enc);
if (conv.vc_type != CONV_NONE) {
- fmt = (char *)string_convert(&conv, (char_u *)fmt, NULL);
+ fmt = string_convert(&conv, fmt, NULL);
}
if (fmt == NULL
|| os_strptime(str, fmt, &tmval) == NULL
@@ -8667,7 +8621,7 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return; // Type error; errmsg already given.
}
- const size_t haystack_len = STRLEN(haystack);
+ const size_t haystack_len = strlen(haystack);
ptrdiff_t end_idx;
if (argvars[2].v_type != VAR_UNKNOWN) {
// Third argument: upper limit for index.
@@ -8729,7 +8683,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (retList == 0) {
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)reg_submatch(no);
+ rettv->vval.v_string = reg_submatch(no);
} else {
rettv->v_type = VAR_LIST;
rettv->vval.v_list = reg_submatch_list(no);
@@ -8782,7 +8736,7 @@ static void f_swapname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|| buf->b_ml.ml_mfp->mf_fname == NULL) {
rettv->vval.v_string = NULL;
} else {
- rettv->vval.v_string = (char *)vim_strsave(buf->b_ml.ml_mfp->mf_fname);
+ rettv->vval.v_string = xstrdup(buf->b_ml.ml_mfp->mf_fname);
}
}
@@ -8798,7 +8752,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
int id = 0;
if (!transerr && lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count
- && col >= 0 && (size_t)col < STRLEN(ml_get(lnum))) {
+ && col >= 0 && (size_t)col < strlen(ml_get(lnum))) {
id = syn_get_id(curwin, lnum, col, trans, NULL, false);
}
@@ -8864,7 +8818,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
break;
case 'u':
- if (STRLEN(what) >= 9) {
+ if (strlen(what) >= 9) {
if (TOLOWER_ASC(what[5]) == 'l') {
// underline
p = highlight_has_attr(id, HL_UNDERLINE, modec);
@@ -8923,7 +8877,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
CLEAR_FIELD(str);
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0
- && (size_t)col <= STRLEN(ml_get(lnum)) && curwin->w_p_cole > 0) {
+ && (size_t)col <= strlen(ml_get(lnum)) && curwin->w_p_cole > 0) {
(void)syn_get_id(curwin, lnum, col, false, NULL, false);
syntax_flags = get_syntax_info(&matchid);
@@ -8960,7 +8914,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (lnum >= 1
&& lnum <= curbuf->b_ml.ml_line_count
&& col >= 0
- && (size_t)col <= STRLEN(ml_get(lnum))) {
+ && (size_t)col <= strlen(ml_get(lnum))) {
tv_list_alloc_ret(rettv, kListLenMayKnow);
(void)syn_get_id(curwin, lnum, col, false, NULL, true);
@@ -9112,7 +9066,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool first = true;
tagname_T tn;
- while (get_tagfname(&tn, first, (char_u *)fname) == OK) {
+ while (get_tagfname(&tn, first, fname) == OK) {
tv_list_append_string(rettv->vval.v_list, fname, -1);
first = false;
}
@@ -9143,7 +9097,7 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void f_tempname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
rettv->v_type = VAR_STRING;
- rettv->vval.v_string = (char *)vim_tempname();
+ rettv->vval.v_string = vim_tempname();
}
/// "termopen(cmd[, cwd])" function
@@ -9190,7 +9144,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (new_cwd && *new_cwd != NUL) {
cwd = new_cwd;
// The new cwd must be a directory.
- if (!os_isdir((const char_u *)cwd)) {
+ if (!os_isdir(cwd)) {
semsg(_(e_invarg2), "expected valid directory");
shell_free_argv(argv);
return;
@@ -9458,10 +9412,10 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
char buf1[NUMBUFLEN];
char buf2[NUMBUFLEN];
- const char_u *head = (const char_u *)tv_get_string_buf_chk(&argvars[0], buf1);
- const char_u *mask = NULL;
- const char_u *prev;
- const char_u *p;
+ const char *head = tv_get_string_buf_chk(&argvars[0], buf1);
+ const char *mask = NULL;
+ const char *prev;
+ const char *p;
int dir = 0;
rettv->v_type = VAR_STRING;
@@ -9476,7 +9430,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
if (argvars[1].v_type == VAR_STRING) {
- mask = (const char_u *)tv_get_string_buf_chk(&argvars[1], buf2);
+ mask = tv_get_string_buf_chk(&argvars[1], buf2);
if (argvars[2].v_type != VAR_UNKNOWN) {
bool error = false;
// leading or trailing characters to trim
@@ -9514,7 +9468,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
- const char_u *tail = head + STRLEN(head);
+ const char *tail = head + strlen(head);
if (dir == 0 || dir == 2) {
// Trim trailing characters
for (; tail > head; tail = prev) {
@@ -9537,7 +9491,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
}
- rettv->vval.v_string = (char *)vim_strnsave(head, (size_t)(tail - head));
+ rettv->vval.v_string = xstrnsave(head, (size_t)(tail - head));
}
/// "type(expr)" function
@@ -9622,7 +9576,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (fp->col < 0) {
fp->col = 0;
} else {
- const size_t len = STRLEN(ml_get(fp->lnum));
+ const size_t len = strlen(ml_get(fp->lnum));
if (fp->col > (colnr_T)len) {
fp->col = (colnr_T)len;
}
@@ -9637,12 +9591,12 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "visualmode()" function
static void f_visualmode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- char_u str[2];
+ char str[2];
rettv->v_type = VAR_STRING;
- str[0] = (char_u)curbuf->b_visual_mode_eval;
+ str[0] = (char)curbuf->b_visual_mode_eval;
str[1] = NUL;
- rettv->vval.v_string = (char *)vim_strsave(str);
+ rettv->vval.v_string = xstrdup(str);
// A non-zero number or non-empty string argument: reset mode.
if (non_zero_arg(&argvars[0])) {
@@ -9681,7 +9635,7 @@ static void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[0].v_type != VAR_UNKNOWN) {
wp = find_win_by_nr_or_id(&argvars[0]);
if (wp == NULL) {
- rettv->vval.v_string = (char *)vim_strsave((char_u *)"unknown");
+ rettv->vval.v_string = xstrdup("unknown");
return;
}
}
@@ -9701,7 +9655,19 @@ static void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "win_gotoid()" function
static void f_win_gotoid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = win_gotoid(argvars);
+ int id = (int)tv_get_number(&argvars[0]);
+
+ if (cmdwin_type != 0) {
+ emsg(_(e_cmdwin));
+ return;
+ }
+ FOR_ALL_TAB_WINDOWS(tp, wp) {
+ if (wp->handle == id) {
+ goto_tabpage_win(tp, wp);
+ rettv->vval.v_number = 1;
+ return;
+ }
+ }
}
/// "win_id2tabwin()" function
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 152c2eff8f..a0b06aaaf4 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -40,6 +40,13 @@
# include "eval/typval.c.generated.h"
#endif
+static char e_string_required_for_argument_nr[]
+ = N_("E1174: String required for argument %d");
+static char e_non_empty_string_required_for_argument_nr[]
+ = N_("E1142: Non-empty string required for argument %d");
+static char e_number_required_for_argument_nr[]
+ = N_("E1210: Number required for argument %d");
+
bool tv_in_free_unref_items = false;
// TODO(ZyX-I): Remove DICT_MAXNEST, make users be non-recursive instead
@@ -1016,7 +1023,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero)
if (sortinfo->item_compare_lc) {
res = strcoll(p1, p2);
} else {
- res = sortinfo->item_compare_ic ? STRICMP(p1, p2): STRCMP(p1, p2);
+ res = sortinfo->item_compare_ic ? STRICMP(p1, p2): strcmp(p1, p2);
}
} else {
double n1, n2;
@@ -1079,9 +1086,9 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this
funcexe_T funcexe = FUNCEXE_INIT;
- funcexe.evaluate = true;
- funcexe.partial = partial;
- funcexe.selfdict = sortinfo->item_compare_selfdict;
+ funcexe.fe_evaluate = true;
+ funcexe.fe_partial = partial;
+ funcexe.fe_selfdict = sortinfo->item_compare_selfdict;
res = call_func(func_name, -1, &rettv, 2, argv, &funcexe);
tv_clear(&argv[0]);
tv_clear(&argv[1]);
@@ -1242,14 +1249,12 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort)
item_compare_func_ptr = item_compare_keeping_zero;
}
- int idx = 0;
for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l))
; li != NULL;) {
listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li);
if (item_compare_func_ptr(&prev_li, &li) == 0) {
li = tv_list_item_remove(l, li);
} else {
- idx++;
li = TV_LIST_ITEM_NEXT(l, li);
}
if (info.item_compare_func_err) { // -V547
@@ -1568,7 +1573,7 @@ bool tv_callback_equal(const Callback *cb1, const Callback *cb2)
}
switch (cb1->type) {
case kCallbackFuncref:
- return STRCMP(cb1->data.funcref, cb2->data.funcref) == 0;
+ return strcmp(cb1->data.funcref, cb2->data.funcref) == 0;
case kCallbackPartial:
// FIXME: this is inconsistent with tv_equal but is needed for precision
// maybe change dictwatcheradd to return a watcher id instead?
@@ -1774,7 +1779,7 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T
tv_dict_add(argv[2].vval.v_dict, v);
}
- if (oldtv) {
+ if (oldtv && oldtv->v_type != VAR_UNKNOWN) {
dictitem_T *const v = tv_dict_item_alloc_len(S_LEN("old"));
tv_copy(oldtv, &v->di_tv);
tv_dict_add(argv[2].vval.v_dict, v);
@@ -2533,7 +2538,7 @@ dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool
new_di = tv_dict_item_alloc((const char *)di->di_key);
} else {
size_t len = STRLEN(di->di_key);
- char *const key = (char *)string_convert(conv, di->di_key, &len);
+ char *const key = (char *)string_convert(conv, (char *)di->di_key, &len);
if (key == NULL) {
new_di = tv_dict_item_alloc_len((const char *)di->di_key, len);
} else {
@@ -2777,7 +2782,7 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi
switch (what) {
case kDictListKeys:
tv_item.v_type = VAR_STRING;
- tv_item.vval.v_string = (char *)vim_strsave(di->di_key);
+ tv_item.vval.v_string = xstrdup((char *)di->di_key);
break;
case kDictListValues:
tv_copy(&di->di_tv, &tv_item);
@@ -3717,8 +3722,7 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
case VAR_STRING: {
varnumber_T n = 0;
if (tv->vval.v_string != NULL) {
- vim_str2nr((char_u *)tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0,
- false);
+ vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false);
}
return n;
}
@@ -3746,9 +3750,11 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error)
linenr_T tv_get_lnum(const typval_T *const tv)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
+ const int did_emsg_before = did_emsg;
linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL);
- if (lnum == 0) { // No valid number, try using same function as line() does.
+ if (lnum <= 0 && did_emsg_before == did_emsg && tv->v_type != VAR_NUMBER) {
int fnum;
+ // No valid number, try using same function as line() does.
pos_T *const fp = var2fpos(tv, true, &fnum, false);
if (fp != NULL) {
lnum = fp->lnum;
@@ -3801,31 +3807,50 @@ float_T tv_get_float(const typval_T *const tv)
return 0;
}
-// Give an error and return FAIL unless "tv" is a string.
-int tv_check_for_string(const typval_T *const tv)
+/// Give an error and return FAIL unless "args[idx]" is a string.
+int tv_check_for_string_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- if (tv->v_type != VAR_STRING) {
- emsg(_(e_stringreq));
+ if (args[idx].v_type != VAR_STRING) {
+ semsg(_(e_string_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
-// Give an error and return FAIL unless "tv" is a non-empty string.
-int tv_check_for_nonempty_string(const typval_T *const tv)
+/// Give an error and return FAIL unless "args[idx]" is a non-empty string.
+int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
- if (tv_check_for_string(tv) == FAIL) {
+ if (tv_check_for_string_arg(args, idx) == FAIL) {
+ return FAIL;
+ }
+ if (args[idx].vval.v_string == NULL || *args[idx].vval.v_string == NUL) {
+ semsg(_(e_non_empty_string_required_for_argument_nr), idx + 1);
return FAIL;
}
- if (tv->vval.v_string == NULL || *tv->vval.v_string == NUL) {
- emsg(_(e_non_empty_string_required));
+ return OK;
+}
+
+/// Give an error and return FAIL unless "args[idx]" is a number.
+int tv_check_for_number_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ if (args[idx].v_type != VAR_NUMBER) {
+ semsg(_(e_number_required_for_argument_nr), idx + 1);
return FAIL;
}
return OK;
}
+/// Check for an optional number argument at "idx"
+int tv_check_for_opt_number_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ return (args[idx].v_type == VAR_UNKNOWN
+ || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL;
+}
+
/// Get the string value of a "stringish" VimL object.
///
/// @param[in] tv Object to get value of.
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 8177d01f90..0a4adc1f53 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -2,415 +2,19 @@
#define NVIM_EVAL_TYPVAL_H
#include <assert.h>
-#include <inttypes.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
+#include "nvim/eval/typval_defs.h"
#include "nvim/func_attr.h"
-#include "nvim/garray.h"
#include "nvim/gettext.h"
-#include "nvim/hashtab.h"
-#include "nvim/lib/queue.h"
#include "nvim/macros.h"
#include "nvim/mbyte_defs.h"
#include "nvim/message.h"
-#include "nvim/pos.h" // for linenr_T
-#include "nvim/types.h"
-#ifdef LOG_LIST_ACTIONS
-# include "nvim/memory.h"
-#endif
-
-/// Type used for VimL VAR_NUMBER values
-typedef int64_t varnumber_T;
-typedef uint64_t uvarnumber_T;
-
-/// Refcount for dict or list that should not be freed
-enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };
-
-/// Additional values for tv_list_alloc() len argument
-enum ListLenSpecials {
- /// List length is not known in advance
- ///
- /// To be used when there is neither a way to know how many elements will be
- /// needed nor are any educated guesses.
- kListLenUnknown = -1,
- /// List length *should* be known, but is actually not
- ///
- /// All occurrences of this value should be eventually removed. This is for
- /// the case when the only reason why list length is not known is that it
- /// would be hard to code without refactoring, but refactoring is needed.
- kListLenShouldKnow = -2,
- /// List length may be known in advance, but it requires too much effort
- ///
- /// To be used when it looks impractical to determine list length.
- kListLenMayKnow = -3,
-};
-
-/// Maximal possible value of varnumber_T variable
-#define VARNUMBER_MAX INT64_MAX
-#define UVARNUMBER_MAX UINT64_MAX
-
-/// Minimal possible value of varnumber_T variable
-#define VARNUMBER_MIN INT64_MIN
-
-/// %d printf format specifier for varnumber_T
-#define PRIdVARNUMBER PRId64
-
-typedef struct listvar_S list_T;
-typedef struct dictvar_S dict_T;
-typedef struct partial_S partial_T;
-typedef struct blobvar_S blob_T;
-
-typedef struct ufunc ufunc_T;
-
-typedef enum {
- kCallbackNone = 0,
- kCallbackFuncref,
- kCallbackPartial,
- kCallbackLua,
-} CallbackType;
-
-typedef struct {
- union {
- char *funcref;
- partial_T *partial;
- LuaRef luaref;
- } data;
- CallbackType type;
-} Callback;
-
-#define CALLBACK_INIT { .type = kCallbackNone }
-#define CALLBACK_NONE ((Callback)CALLBACK_INIT)
-
-/// Structure holding dictionary watcher
-typedef struct dict_watcher {
- Callback callback;
- char *key_pattern;
- size_t key_pattern_len;
- QUEUE node;
- bool busy; // prevent recursion if the dict is changed in the callback
- bool needs_free;
-} DictWatcher;
-
-/// Bool variable values
-typedef enum {
- kBoolVarFalse, ///< v:false
- kBoolVarTrue, ///< v:true
-} BoolVarValue;
-
-/// Special variable values
-typedef enum {
- kSpecialVarNull, ///< v:null
-} SpecialVarValue;
-
-/// Variable lock status for typval_T.v_lock
-typedef enum {
- VAR_UNLOCKED = 0, ///< Not locked.
- VAR_LOCKED = 1, ///< User lock, can be unlocked.
- VAR_FIXED = 2, ///< Locked forever.
-} VarLockStatus;
-
-/// VimL variable types, for use in typval_T.v_type
-typedef enum {
- VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
- VAR_NUMBER, ///< Number, .v_number is used.
- VAR_STRING, ///< String, .v_string is used.
- VAR_FUNC, ///< Function reference, .v_string is used as function name.
- VAR_LIST, ///< List, .v_list is used.
- VAR_DICT, ///< Dictionary, .v_dict is used.
- VAR_FLOAT, ///< Floating-point value, .v_float is used.
- VAR_BOOL, ///< true, false
- VAR_SPECIAL, ///< Special value (null), .v_special
- ///< is used.
- VAR_PARTIAL, ///< Partial, .v_partial is used.
- VAR_BLOB, ///< Blob, .v_blob is used.
-} VarType;
-
-/// Structure that holds an internal variable value
-typedef struct {
- VarType v_type; ///< Variable type.
- VarLockStatus v_lock; ///< Variable lock status.
- union typval_vval_union {
- varnumber_T v_number; ///< Number, for VAR_NUMBER.
- BoolVarValue v_bool; ///< Bool value, for VAR_BOOL
- SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
- float_T v_float; ///< Floating-point number, for VAR_FLOAT.
- char *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
- list_T *v_list; ///< List for VAR_LIST, can be NULL.
- dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
- partial_T *v_partial; ///< Closure: function with args.
- blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL.
- } vval; ///< Actual value.
-} typval_T;
-
-/// Values for (struct dictvar_S).dv_scope
-typedef enum {
- VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
- VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
- VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
- ///< (l:, g:).
-} ScopeType;
-
-/// Structure to hold an item of a list
-typedef struct listitem_S listitem_T;
-
-struct listitem_S {
- listitem_T *li_next; ///< Next item in list.
- listitem_T *li_prev; ///< Previous item in list.
- typval_T li_tv; ///< Item value.
-};
-
-/// Structure used by those that are using an item in a list
-typedef struct listwatch_S listwatch_T;
-
-struct listwatch_S {
- listitem_T *lw_item; ///< Item being watched.
- listwatch_T *lw_next; ///< Next watcher.
-};
-
-/// Structure to hold info about a list
-/// Order of members is optimized to reduce padding.
-struct listvar_S {
- listitem_T *lv_first; ///< First item, NULL if none.
- listitem_T *lv_last; ///< Last item, NULL if none.
- listwatch_T *lv_watch; ///< First watcher, NULL if none.
- listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
- list_T *lv_copylist; ///< Copied list used by deepcopy().
- list_T *lv_used_next; ///< next list in used lists list.
- list_T *lv_used_prev; ///< Previous list in used lists list.
- int lv_refcount; ///< Reference count.
- int lv_len; ///< Number of items.
- int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
- int lv_copyID; ///< ID used by deepcopy().
- VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
-
- LuaRef lua_table_ref;
-};
-
-// Static list with 10 items. Use tv_list_init_static10() to initialize.
-typedef struct {
- list_T sl_list; // must be first
- listitem_T sl_items[10];
-} staticList10_T;
-
-#define TV_LIST_STATIC10_INIT { \
- .sl_list = { \
- .lv_first = NULL, \
- .lv_last = NULL, \
- .lv_refcount = 0, \
- .lv_len = 0, \
- .lv_watch = NULL, \
- .lv_idx_item = NULL, \
- .lv_lock = VAR_FIXED, \
- .lv_used_next = NULL, \
- .lv_used_prev = NULL, \
- }, \
-}
-
-#define TV_DICTITEM_STRUCT(...) \
- struct { \
- typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
- uint8_t di_flags; /* Flags. */ \
- char_u di_key[__VA_ARGS__]; /* Key value. */ \
- }
-
-/// Structure to hold a scope dictionary
-///
-/// @warning Must be compatible with dictitem_T.
-///
-/// For use in find_var_in_ht to pretend that it found dictionary item when it
-/// finds scope dictionary.
-typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
-
-/// Structure to hold an item of a Dictionary
-///
-/// @warning Must be compatible with ScopeDictDictItem.
-///
-/// Also used for a variable.
-typedef TV_DICTITEM_STRUCT() dictitem_T;
-
-/// Flags for dictitem_T.di_flags
-typedef enum {
- DI_FLAGS_RO = 1, ///< Read-only value
- DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
- DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
- DI_FLAGS_LOCK = 8, ///< Locked value.
- DI_FLAGS_ALLOC = 16, ///< Separately allocated.
-} DictItemFlags;
-
-/// Structure representing a Dictionary
-struct dictvar_S {
- VarLockStatus dv_lock; ///< Whole dictionary lock status.
- ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
- ///< dictionary represents a scope (i.e. g:, l: …).
- int dv_refcount; ///< Reference count.
- int dv_copyID; ///< ID used when recursivery traversing a value.
- hashtab_T dv_hashtab; ///< Hashtab containing all items.
- dict_T *dv_copydict; ///< Copied dict used by deepcopy().
- dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
- dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
- QUEUE watchers; ///< Dictionary key watchers set by user code.
-
- LuaRef lua_table_ref;
-};
-
-/// Structure to hold info about a Blob
-struct blobvar_S {
- garray_T bv_ga; ///< Growarray with the data.
- int bv_refcount; ///< Reference count.
- VarLockStatus bv_lock; ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED.
-};
-
-/// Type used for script ID
-typedef int scid_T;
-/// Format argument for scid_T
-#define PRIdSCID "d"
-
-// SCript ConteXt (SCTX): identifies a script line.
-// When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current
-// line number. When executing a user function "sc_lnum" is the line where the
-// function was defined, "sourcing_lnum" is the line number inside the
-// function. When stored with a function, mapping, option, etc. "sc_lnum" is
-// the line number in the script "sc_sid".
-typedef struct {
- scid_T sc_sid; // script ID
- int sc_seq; // sourcing sequence number
- linenr_T sc_lnum; // line number
-} sctx_T;
-
-/// Maximum number of function arguments
-#define MAX_FUNC_ARGS 20
-/// Short variable name length
-#define VAR_SHORT_LEN 20
-/// Number of fixed variables used for arguments
-#define FIXVAR_CNT 12
-
-/// Callback interface for C function reference>
-/// Used for managing functions that were registered with |register_cfunc|
-typedef int (*cfunc_T)(int argcount, typval_T *argvars, typval_T *rettv, void *state); // NOLINT
-/// Callback to clear cfunc_T and any associated state.
-typedef void (*cfunc_free_T)(void *state);
-
-// Structure to hold info for a function that is currently being executed.
-typedef struct funccall_S funccall_T;
-
-struct funccall_S {
- ufunc_T *func; ///< Function being called.
- int linenr; ///< Next line to be executed.
- int returned; ///< ":return" used.
- /// Fixed variables for arguments.
- TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT];
- dict_T l_vars; ///< l: local function variables.
- ScopeDictDictItem l_vars_var; ///< Variable for l: scope.
- dict_T l_avars; ///< a: argument variables.
- ScopeDictDictItem l_avars_var; ///< Variable for a: scope.
- list_T l_varlist; ///< List for a:000.
- listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000.
- typval_T *rettv; ///< Return value.
- linenr_T breakpoint; ///< Next line with breakpoint or zero.
- int dbg_tick; ///< Debug_tick when breakpoint was set.
- int level; ///< Top nesting level of executed function.
- proftime_T prof_child; ///< Time spent in a child.
- funccall_T *caller; ///< Calling function or NULL; or next funccal in
- ///< list pointed to by previous_funccal.
- int fc_refcount; ///< Number of user functions that reference this funccall.
- int fc_copyID; ///< CopyID used for garbage collection.
- garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func".
-};
-
-/// Structure to hold info for a user function.
-struct ufunc {
- int uf_varargs; ///< variable nr of arguments
- int uf_flags;
- int uf_calls; ///< nr of active calls
- bool uf_cleared; ///< func_clear() was already called
- garray_T uf_args; ///< arguments
- garray_T uf_def_args; ///< default argument expressions
- garray_T uf_lines; ///< function lines
- int uf_profiling; ///< true when func is being profiled
- int uf_prof_initialized;
- // Managing cfuncs
- cfunc_T uf_cb; ///< C function extension callback
- cfunc_free_T uf_cb_free; ///< C function extension free callback
- void *uf_cb_state; ///< State of C function extension.
- // Profiling the function as a whole.
- int uf_tm_count; ///< nr of calls
- proftime_T uf_tm_total; ///< time spent in function + children
- proftime_T uf_tm_self; ///< time spent in function itself
- proftime_T uf_tm_children; ///< time spent in children this call
- // Profiling the function per line.
- int *uf_tml_count; ///< nr of times line was executed
- proftime_T *uf_tml_total; ///< time spent in a line + children
- proftime_T *uf_tml_self; ///< time spent in a line itself
- proftime_T uf_tml_start; ///< start time for current line
- proftime_T uf_tml_children; ///< time spent in children for this line
- proftime_T uf_tml_wait; ///< start wait time for current line
- int uf_tml_idx; ///< index of line being timed; -1 if none
- int uf_tml_execed; ///< line being timed was executed
- sctx_T uf_script_ctx; ///< SCTX where function was defined,
- ///< used for s: variables
- int uf_refcount; ///< reference count, see func_name_refcount()
- funccall_T *uf_scoped; ///< l: local variables for closure
- char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
- ///< "<SNR>" as a string, otherwise NULL
- char_u uf_name[]; ///< Name of function (actual size equals name);
- ///< can start with <SNR>123_
- ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR)
-};
-
-struct partial_S {
- int pt_refcount; ///< Reference count.
- char_u *pt_name; ///< Function name; when NULL use pt_func->name.
- ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with
- ///< pt_name.
- bool pt_auto; ///< When true the partial was created by using dict.member
- ///< in handle_subscript().
- int pt_argc; ///< Number of arguments.
- typval_T *pt_argv; ///< Arguments in allocated array.
- dict_T *pt_dict; ///< Dict for "self".
-};
-
-/// Structure used for explicit stack while garbage collecting hash tables
-typedef struct ht_stack_S {
- hashtab_T *ht;
- struct ht_stack_S *prev;
-} ht_stack_T;
-
-/// Structure used for explicit stack while garbage collecting lists
-typedef struct list_stack_S {
- list_T *list;
- struct list_stack_S *prev;
-} list_stack_T;
-
-/// Structure representing one list item, used for sort array.
-typedef struct {
- listitem_T *item; ///< Sorted list item.
- int idx; ///< Sorted list item index.
-} ListSortItem;
-
-typedef int (*ListSorter)(const void *, const void *);
#ifdef LOG_LIST_ACTIONS
-
-/// List actions log entry
-typedef struct {
- uintptr_t l; ///< List log entry belongs to.
- uintptr_t li1; ///< First list item log entry belongs to, if applicable.
- uintptr_t li2; ///< Second list item log entry belongs to, if applicable.
- int len; ///< List length when log entry was created.
- const char *action; ///< Logged action.
-} ListLogEntry;
-
-typedef struct list_log ListLog;
-
-/// List actions log
-struct list_log {
- ListLog *next; ///< Next chunk or NULL.
- size_t capacity; ///< Number of entries in current chunk.
- size_t size; ///< Current chunk size.
- ListLogEntry entries[]; ///< Actual log entries.
-};
+# include "nvim/memory.h"
extern ListLog *list_log_first; ///< First list log chunk, NULL if missing
extern ListLog *list_log_last; ///< Last list log chunk
@@ -790,12 +394,6 @@ static inline void tv_init(typval_T *const tv)
}
}
-#define TV_INITIAL_VALUE \
- ((typval_T) { \
- .v_type = VAR_UNKNOWN, \
- .v_lock = VAR_UNLOCKED, \
- })
-
/// Empty string
///
/// Needed for hack which allows not allocating empty string and still not
@@ -894,9 +492,6 @@ static inline bool tv_get_float_chk(const typval_T *const tv,
float_T *const ret_f)
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
-// FIXME circular dependency, cannot import message.h.
-bool semsg(const char *const fmt, ...);
-
/// Get the float value
///
/// Raises an error if object is not number or floating-point.
diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h
new file mode 100644
index 0000000000..1c0a438751
--- /dev/null
+++ b/src/nvim/eval/typval_defs.h
@@ -0,0 +1,399 @@
+#ifndef NVIM_EVAL_TYPVAL_DEFS_H
+#define NVIM_EVAL_TYPVAL_DEFS_H
+
+#include <inttypes.h>
+#include <limits.h>
+
+#include "nvim/garray.h"
+#include "nvim/hashtab.h"
+#include "nvim/lib/queue.h"
+#include "nvim/pos.h"
+#include "nvim/types.h"
+
+/// Type used for VimL VAR_NUMBER values
+typedef int64_t varnumber_T;
+typedef uint64_t uvarnumber_T;
+
+/// Refcount for dict or list that should not be freed
+enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };
+
+/// Additional values for tv_list_alloc() len argument
+enum ListLenSpecials {
+ /// List length is not known in advance
+ ///
+ /// To be used when there is neither a way to know how many elements will be
+ /// needed nor are any educated guesses.
+ kListLenUnknown = -1,
+ /// List length *should* be known, but is actually not
+ ///
+ /// All occurrences of this value should be eventually removed. This is for
+ /// the case when the only reason why list length is not known is that it
+ /// would be hard to code without refactoring, but refactoring is needed.
+ kListLenShouldKnow = -2,
+ /// List length may be known in advance, but it requires too much effort
+ ///
+ /// To be used when it looks impractical to determine list length.
+ kListLenMayKnow = -3,
+};
+
+/// Maximal possible value of varnumber_T variable
+#define VARNUMBER_MAX INT64_MAX
+#define UVARNUMBER_MAX UINT64_MAX
+
+/// Minimal possible value of varnumber_T variable
+#define VARNUMBER_MIN INT64_MIN
+
+/// %d printf format specifier for varnumber_T
+#define PRIdVARNUMBER PRId64
+
+typedef struct listvar_S list_T;
+typedef struct dictvar_S dict_T;
+typedef struct partial_S partial_T;
+typedef struct blobvar_S blob_T;
+
+typedef struct ufunc ufunc_T;
+
+typedef enum {
+ kCallbackNone = 0,
+ kCallbackFuncref,
+ kCallbackPartial,
+ kCallbackLua,
+} CallbackType;
+
+typedef struct {
+ union {
+ char *funcref;
+ partial_T *partial;
+ LuaRef luaref;
+ } data;
+ CallbackType type;
+} Callback;
+
+#define CALLBACK_INIT { .type = kCallbackNone }
+#define CALLBACK_NONE ((Callback)CALLBACK_INIT)
+
+/// Structure holding dictionary watcher
+typedef struct dict_watcher {
+ Callback callback;
+ char *key_pattern;
+ size_t key_pattern_len;
+ QUEUE node;
+ bool busy; // prevent recursion if the dict is changed in the callback
+ bool needs_free;
+} DictWatcher;
+
+/// Bool variable values
+typedef enum {
+ kBoolVarFalse, ///< v:false
+ kBoolVarTrue, ///< v:true
+} BoolVarValue;
+
+/// Special variable values
+typedef enum {
+ kSpecialVarNull, ///< v:null
+} SpecialVarValue;
+
+/// Variable lock status for typval_T.v_lock
+typedef enum {
+ VAR_UNLOCKED = 0, ///< Not locked.
+ VAR_LOCKED = 1, ///< User lock, can be unlocked.
+ VAR_FIXED = 2, ///< Locked forever.
+} VarLockStatus;
+
+/// VimL variable types, for use in typval_T.v_type
+typedef enum {
+ VAR_UNKNOWN = 0, ///< Unknown (unspecified) value.
+ VAR_NUMBER, ///< Number, .v_number is used.
+ VAR_STRING, ///< String, .v_string is used.
+ VAR_FUNC, ///< Function reference, .v_string is used as function name.
+ VAR_LIST, ///< List, .v_list is used.
+ VAR_DICT, ///< Dictionary, .v_dict is used.
+ VAR_FLOAT, ///< Floating-point value, .v_float is used.
+ VAR_BOOL, ///< true, false
+ VAR_SPECIAL, ///< Special value (null), .v_special is used.
+ VAR_PARTIAL, ///< Partial, .v_partial is used.
+ VAR_BLOB, ///< Blob, .v_blob is used.
+} VarType;
+
+/// Structure that holds an internal variable value
+typedef struct {
+ VarType v_type; ///< Variable type.
+ VarLockStatus v_lock; ///< Variable lock status.
+ union typval_vval_union {
+ varnumber_T v_number; ///< Number, for VAR_NUMBER.
+ BoolVarValue v_bool; ///< Bool value, for VAR_BOOL
+ SpecialVarValue v_special; ///< Special value, for VAR_SPECIAL.
+ float_T v_float; ///< Floating-point number, for VAR_FLOAT.
+ char *v_string; ///< String, for VAR_STRING and VAR_FUNC, can be NULL.
+ list_T *v_list; ///< List for VAR_LIST, can be NULL.
+ dict_T *v_dict; ///< Dictionary for VAR_DICT, can be NULL.
+ partial_T *v_partial; ///< Closure: function with args.
+ blob_T *v_blob; ///< Blob for VAR_BLOB, can be NULL.
+ } vval; ///< Actual value.
+} typval_T;
+
+#define TV_INITIAL_VALUE \
+ ((typval_T) { \
+ .v_type = VAR_UNKNOWN, \
+ .v_lock = VAR_UNLOCKED, \
+ })
+
+/// Values for (struct dictvar_S).dv_scope
+typedef enum {
+ VAR_NO_SCOPE = 0, ///< Not a scope dictionary.
+ VAR_SCOPE = 1, ///< Scope dictionary which requires prefix (a:, v:, …).
+ VAR_DEF_SCOPE = 2, ///< Scope dictionary which may be accessed without prefix
+ ///< (l:, g:).
+} ScopeType;
+
+/// Structure to hold an item of a list
+typedef struct listitem_S listitem_T;
+
+struct listitem_S {
+ listitem_T *li_next; ///< Next item in list.
+ listitem_T *li_prev; ///< Previous item in list.
+ typval_T li_tv; ///< Item value.
+};
+
+/// Structure used by those that are using an item in a list
+typedef struct listwatch_S listwatch_T;
+
+struct listwatch_S {
+ listitem_T *lw_item; ///< Item being watched.
+ listwatch_T *lw_next; ///< Next watcher.
+};
+
+/// Structure to hold info about a list
+/// Order of members is optimized to reduce padding.
+struct listvar_S {
+ listitem_T *lv_first; ///< First item, NULL if none.
+ listitem_T *lv_last; ///< Last item, NULL if none.
+ listwatch_T *lv_watch; ///< First watcher, NULL if none.
+ listitem_T *lv_idx_item; ///< When not NULL item at index "lv_idx".
+ list_T *lv_copylist; ///< Copied list used by deepcopy().
+ list_T *lv_used_next; ///< next list in used lists list.
+ list_T *lv_used_prev; ///< Previous list in used lists list.
+ int lv_refcount; ///< Reference count.
+ int lv_len; ///< Number of items.
+ int lv_idx; ///< Index of a cached item, used for optimising repeated l[idx].
+ int lv_copyID; ///< ID used by deepcopy().
+ VarLockStatus lv_lock; ///< Zero, VAR_LOCKED, VAR_FIXED.
+
+ LuaRef lua_table_ref;
+};
+
+/// Static list with 10 items. Use tv_list_init_static10() to initialize.
+typedef struct {
+ list_T sl_list; // must be first
+ listitem_T sl_items[10];
+} staticList10_T;
+
+#define TV_LIST_STATIC10_INIT { \
+ .sl_list = { \
+ .lv_first = NULL, \
+ .lv_last = NULL, \
+ .lv_refcount = 0, \
+ .lv_len = 0, \
+ .lv_watch = NULL, \
+ .lv_idx_item = NULL, \
+ .lv_lock = VAR_FIXED, \
+ .lv_used_next = NULL, \
+ .lv_used_prev = NULL, \
+ }, \
+}
+
+#define TV_DICTITEM_STRUCT(...) \
+ struct { \
+ typval_T di_tv; /* Structure that holds scope dictionary itself. */ \
+ uint8_t di_flags; /* Flags. */ \
+ char_u di_key[__VA_ARGS__]; /* Key value. */ \
+ }
+
+/// Structure to hold a scope dictionary
+///
+/// @warning Must be compatible with dictitem_T.
+///
+/// For use in find_var_in_ht to pretend that it found dictionary item when it
+/// finds scope dictionary.
+typedef TV_DICTITEM_STRUCT(1) ScopeDictDictItem;
+
+/// Structure to hold an item of a Dictionary
+///
+/// @warning Must be compatible with ScopeDictDictItem.
+///
+/// Also used for a variable.
+typedef TV_DICTITEM_STRUCT() dictitem_T;
+
+/// Flags for dictitem_T.di_flags
+typedef enum {
+ DI_FLAGS_RO = 1, ///< Read-only value
+ DI_FLAGS_RO_SBX = 2, ///< Value, read-only in the sandbox
+ DI_FLAGS_FIX = 4, ///< Fixed value: cannot be :unlet or remove()d.
+ DI_FLAGS_LOCK = 8, ///< Locked value.
+ DI_FLAGS_ALLOC = 16, ///< Separately allocated.
+} DictItemFlags;
+
+/// Structure representing a Dictionary
+struct dictvar_S {
+ VarLockStatus dv_lock; ///< Whole dictionary lock status.
+ ScopeType dv_scope; ///< Non-zero (#VAR_SCOPE, #VAR_DEF_SCOPE) if
+ ///< dictionary represents a scope (i.e. g:, l: …).
+ int dv_refcount; ///< Reference count.
+ int dv_copyID; ///< ID used when recursivery traversing a value.
+ hashtab_T dv_hashtab; ///< Hashtab containing all items.
+ dict_T *dv_copydict; ///< Copied dict used by deepcopy().
+ dict_T *dv_used_next; ///< Next dictionary in used dictionaries list.
+ dict_T *dv_used_prev; ///< Previous dictionary in used dictionaries list.
+ QUEUE watchers; ///< Dictionary key watchers set by user code.
+
+ LuaRef lua_table_ref;
+};
+
+/// Structure to hold info about a Blob
+struct blobvar_S {
+ garray_T bv_ga; ///< Growarray with the data.
+ int bv_refcount; ///< Reference count.
+ VarLockStatus bv_lock; ///< VAR_UNLOCKED, VAR_LOCKED, VAR_FIXED.
+};
+
+/// Type used for script ID
+typedef int scid_T;
+/// Format argument for scid_T
+#define PRIdSCID "d"
+
+/// SCript ConteXt (SCTX): identifies a script line.
+/// When sourcing a script "sc_lnum" is zero, "sourcing_lnum" is the current
+/// line number. When executing a user function "sc_lnum" is the line where the
+/// function was defined, "sourcing_lnum" is the line number inside the
+/// function. When stored with a function, mapping, option, etc. "sc_lnum" is
+/// the line number in the script "sc_sid".
+typedef struct {
+ scid_T sc_sid; ///< script ID
+ int sc_seq; ///< sourcing sequence number
+ linenr_T sc_lnum; ///< line number
+} sctx_T;
+
+/// Maximum number of function arguments
+enum { MAX_FUNC_ARGS = 20, };
+/// Short variable name length
+enum { VAR_SHORT_LEN = 20, };
+/// Number of fixed variables used for arguments
+enum { FIXVAR_CNT = 12, };
+
+/// Structure to hold info for a function that is currently being executed.
+typedef struct funccall_S funccall_T;
+
+struct funccall_S {
+ ufunc_T *func; ///< Function being called.
+ int linenr; ///< Next line to be executed.
+ int returned; ///< ":return" used.
+ /// Fixed variables for arguments.
+ TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT];
+ dict_T l_vars; ///< l: local function variables.
+ ScopeDictDictItem l_vars_var; ///< Variable for l: scope.
+ dict_T l_avars; ///< a: argument variables.
+ ScopeDictDictItem l_avars_var; ///< Variable for a: scope.
+ list_T l_varlist; ///< List for a:000.
+ listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000.
+ typval_T *rettv; ///< Return value.
+ linenr_T breakpoint; ///< Next line with breakpoint or zero.
+ int dbg_tick; ///< debug_tick when breakpoint was set.
+ int level; ///< Top nesting level of executed function.
+ proftime_T prof_child; ///< Time spent in a child.
+ funccall_T *caller; ///< Calling function or NULL; or next funccal in
+ ///< list pointed to by previous_funccal.
+ int fc_refcount; ///< Number of user functions that reference this funccall.
+ int fc_copyID; ///< CopyID used for garbage collection.
+ garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func".
+};
+
+/// Structure to hold info for a user function.
+struct ufunc {
+ int uf_varargs; ///< variable nr of arguments
+ int uf_flags;
+ int uf_calls; ///< nr of active calls
+ bool uf_cleared; ///< func_clear() was already called
+ garray_T uf_args; ///< arguments
+ garray_T uf_def_args; ///< default argument expressions
+ garray_T uf_lines; ///< function lines
+ int uf_profiling; ///< true when func is being profiled
+ int uf_prof_initialized;
+ LuaRef uf_luaref; ///< lua callback, used if (uf_flags & FC_LUAREF)
+ // Profiling the function as a whole.
+ int uf_tm_count; ///< nr of calls
+ proftime_T uf_tm_total; ///< time spent in function + children
+ proftime_T uf_tm_self; ///< time spent in function itself
+ proftime_T uf_tm_children; ///< time spent in children this call
+ // Profiling the function per line.
+ int *uf_tml_count; ///< nr of times line was executed
+ proftime_T *uf_tml_total; ///< time spent in a line + children
+ proftime_T *uf_tml_self; ///< time spent in a line itself
+ proftime_T uf_tml_start; ///< start time for current line
+ proftime_T uf_tml_children; ///< time spent in children for this line
+ proftime_T uf_tml_wait; ///< start wait time for current line
+ int uf_tml_idx; ///< index of line being timed; -1 if none
+ int uf_tml_execed; ///< line being timed was executed
+ sctx_T uf_script_ctx; ///< SCTX where function was defined,
+ ///< used for s: variables
+ int uf_refcount; ///< reference count, see func_name_refcount()
+ funccall_T *uf_scoped; ///< l: local variables for closure
+ char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with
+ ///< "<SNR>" as a string, otherwise NULL
+ char_u uf_name[]; ///< Name of function (actual size equals name);
+ ///< can start with <SNR>123_
+ ///< (<SNR> is K_SPECIAL KS_EXTRA KE_SNR)
+};
+
+struct partial_S {
+ int pt_refcount; ///< Reference count.
+ char *pt_name; ///< Function name; when NULL use pt_func->name.
+ ufunc_T *pt_func; ///< Function pointer; when NULL lookup function with pt_name.
+ bool pt_auto; ///< When true the partial was created by using dict.member
+ ///< in handle_subscript().
+ int pt_argc; ///< Number of arguments.
+ typval_T *pt_argv; ///< Arguments in allocated array.
+ dict_T *pt_dict; ///< Dict for "self".
+};
+
+/// Structure used for explicit stack while garbage collecting hash tables
+typedef struct ht_stack_S {
+ hashtab_T *ht;
+ struct ht_stack_S *prev;
+} ht_stack_T;
+
+/// Structure used for explicit stack while garbage collecting lists
+typedef struct list_stack_S {
+ list_T *list;
+ struct list_stack_S *prev;
+} list_stack_T;
+
+/// Structure representing one list item, used for sort array.
+typedef struct {
+ listitem_T *item; ///< Sorted list item.
+ int idx; ///< Sorted list item index.
+} ListSortItem;
+
+typedef int (*ListSorter)(const void *, const void *);
+
+#ifdef LOG_LIST_ACTIONS
+/// List actions log entry
+typedef struct {
+ uintptr_t l; ///< List log entry belongs to.
+ uintptr_t li1; ///< First list item log entry belongs to, if applicable.
+ uintptr_t li2; ///< Second list item log entry belongs to, if applicable.
+ int len; ///< List length when log entry was created.
+ const char *action; ///< Logged action.
+} ListLogEntry;
+
+typedef struct list_log ListLog;
+
+/// List actions log
+struct list_log {
+ ListLog *next; ///< Next chunk or NULL.
+ size_t capacity; ///< Number of entries in current chunk.
+ size_t size; ///< Current chunk size.
+ ListLogEntry entries[]; ///< Actual log entries.
+};
+#endif
+
+#endif // NVIM_EVAL_TYPVAL_DEFS_H
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 73b36b8611..ff4f92e40b 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -250,7 +250,7 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/func_attr.h"
-#include "nvim/lib/kvec.h"
+#include "klib/kvec.h"
// -V::1063
diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h
index ed70ba87ec..33e19c531c 100644
--- a/src/nvim/eval/typval_encode.h
+++ b/src/nvim/eval/typval_encode.h
@@ -10,9 +10,9 @@
#include <stddef.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/eval/typval.h"
#include "nvim/func_attr.h"
-#include "nvim/lib/kvec.h"
/// Type of the stack entry
typedef enum {
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 8cb7a075cb..b0a56c4440 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -28,20 +28,6 @@
#include "nvim/ui.h"
#include "nvim/vim.h"
-// flags used in uf_flags
-#define FC_ABORT 0x01 // abort function on error
-#define FC_RANGE 0x02 // function accepts range
-#define FC_DICT 0x04 // Dict function, uses "self"
-#define FC_CLOSURE 0x08 // closure, uses outer scope variables
-#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
-#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
-#define FC_SANDBOX 0x40 // function defined in the sandbox
-#define FC_DEAD 0x80 // function kept only for reference to dfunc
-#define FC_EXPORT 0x100 // "export def Func()"
-#define FC_NOARGS 0x200 // no a: variables in lambda
-#define FC_VIM9 0x400 // defined in vim9 script file
-#define FC_CFUNC 0x800 // C function extension
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/userfunc.c.generated.h"
#endif
@@ -125,7 +111,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
// Check for duplicate argument name.
for (i = 0; i < newargs->ga_len; i++) {
- if (STRCMP(((char **)(newargs->ga_data))[i], arg) == 0) {
+ if (strcmp(((char **)(newargs->ga_data))[i], arg) == 0) {
semsg(_("E853: Duplicate argument name: %s"), arg);
xfree(arg);
goto err_ret;
@@ -142,18 +128,18 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int
any_default = true;
p = skipwhite(p) + 1;
p = skipwhite(p);
- char_u *expr = (char_u *)p;
+ char *expr = p;
if (eval1(&p, &rettv, false) != FAIL) {
ga_grow(default_args, 1);
// trim trailing whitespace
- while (p > (char *)expr && ascii_iswhite(p[-1])) {
+ while (p > expr && ascii_iswhite(p[-1])) {
p--;
}
c = (char_u)(*p);
*p = NUL;
- expr = vim_strsave(expr);
- ((char **)(default_args->ga_data))[default_args->ga_len] = (char *)expr;
+ expr = xstrdup(expr);
+ ((char **)(default_args->ga_data))[default_args->ga_len] = expr;
default_args->ga_len++;
*p = (char)c;
} else {
@@ -378,7 +364,7 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp,
*lenp = 0;
return (char_u *)"";
}
- *lenp = (int)STRLEN(v->di_tv.vval.v_string);
+ *lenp = (int)strlen(v->di_tv.vval.v_string);
return (char_u *)v->di_tv.vval.v_string;
}
@@ -409,7 +395,7 @@ void emsg_funcname(char *ermsg, const char_u *name)
char_u *p;
if (*name == K_SPECIAL) {
- p = concat_str((char_u *)"<SNR>", name + 3);
+ p = (char_u *)concat_str("<SNR>", (char *)name + 3);
} else {
p = (char_u *)name;
}
@@ -439,12 +425,12 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char **arg, funcex
// Get the arguments.
argp = *arg;
while (argcount < MAX_FUNC_ARGS
- - (funcexe->partial == NULL ? 0 : funcexe->partial->pt_argc)) {
+ - (funcexe->fe_partial == NULL ? 0 : funcexe->fe_partial->pt_argc)) {
argp = skipwhite(argp + 1); // skip the '(' or ','
if (*argp == ')' || *argp == ',' || *argp == NUL) {
break;
}
- if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) {
+ if (eval1(&argp, &argvars[argcount], funcexe->fe_evaluate) == FAIL) {
ret = FAIL;
break;
}
@@ -525,39 +511,38 @@ static inline bool eval_fname_sid(const char *const name)
///
/// @return transformed name: either `fname_buf` or a pointer to an allocated
/// memory.
-static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf,
- char_u **const tofree, int *const error)
+static char *fname_trans_sid(const char *const name, char *const fname_buf, char **const tofree,
+ int *const error)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- char_u *fname;
- const int llen = eval_fname_script((const char *)name);
- if (llen > 0) {
- fname_buf[0] = K_SPECIAL;
- fname_buf[1] = KS_EXTRA;
- fname_buf[2] = KE_SNR;
- int i = 3;
- if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:"
- if (current_sctx.sc_sid <= 0) {
- *error = ERROR_SCRIPT;
- } else {
- snprintf((char *)fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_",
- (int64_t)current_sctx.sc_sid);
- i = (int)STRLEN(fname_buf);
- }
- }
- if ((size_t)i + STRLEN(name + llen) < FLEN_FIXED) {
- STRCPY(fname_buf + i, name + llen);
- fname = fname_buf;
+ const int llen = eval_fname_script(name);
+ if (llen == 0) {
+ return (char *)name; // no prefix
+ }
+
+ fname_buf[0] = (char)K_SPECIAL;
+ fname_buf[1] = (char)KS_EXTRA;
+ fname_buf[2] = KE_SNR;
+ int i = 3;
+ if (eval_fname_sid(name)) { // "<SID>" or "s:"
+ if (current_sctx.sc_sid <= 0) {
+ *error = FCERR_SCRIPT;
} else {
- fname = xmalloc((size_t)i + STRLEN(name + llen) + 1);
- *tofree = fname;
- memmove(fname, fname_buf, (size_t)i);
- STRCPY(fname + i, name + llen);
+ snprintf(fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_",
+ (int64_t)current_sctx.sc_sid);
+ i = (int)strlen(fname_buf);
}
+ }
+ char *fname;
+ if ((size_t)i + strlen(name + llen) < FLEN_FIXED) {
+ STRCPY(fname_buf + i, name + llen);
+ fname = fname_buf;
} else {
- fname = (char_u *)name;
+ fname = xmalloc((size_t)i + strlen(name + llen) + 1);
+ *tofree = fname;
+ memmove(fname, fname_buf, (size_t)i);
+ STRCPY(fname + i, name + llen);
}
-
return fname;
}
@@ -758,9 +743,9 @@ static void func_clear_items(ufunc_T *fp)
ga_clear_strings(&(fp->uf_lines));
XFREE_CLEAR(fp->uf_name_exp);
- if (fp->uf_cb_free != NULL) {
- fp->uf_cb_free(fp->uf_cb_state);
- fp->uf_cb_free = NULL;
+ if (fp->uf_flags & FC_LUAREF) {
+ api_free_luaref(fp->uf_luaref);
+ fp->uf_luaref = LUA_NOREF;
}
XFREE_CLEAR(fp->uf_tml_count);
@@ -863,7 +848,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
fc->rettv = rettv;
fc->level = ex_nesting_level;
// Check if this function has a breakpoint.
- fc->breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0);
+ fc->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, (linenr_T)0);
fc->dbg_tick = debug_tick;
// Set up fields for closure.
@@ -970,11 +955,11 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1);
name = (char *)numbuf;
}
- if (fixvar_idx < FIXVAR_CNT && STRLEN(name) <= VAR_SHORT_LEN) {
+ if (fixvar_idx < FIXVAR_CNT && strlen(name) <= VAR_SHORT_LEN) {
v = (dictitem_T *)&fc->fixvar[fixvar_idx++];
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
} else {
- v = xmalloc(sizeof(dictitem_T) + STRLEN(name));
+ v = xmalloc(sizeof(dictitem_T) + strlen(name));
v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX | DI_FLAGS_ALLOC;
}
STRCPY(v->di_key, name);
@@ -1058,7 +1043,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
bool func_not_yet_profiling_but_should =
do_profiling_yes
- && !fp->uf_profiling && has_profiling(false, fp->uf_name, NULL);
+ && !fp->uf_profiling && has_profiling(false, (char *)fp->uf_name, NULL);
if (func_not_yet_profiling_but_should) {
started_profiling = true;
@@ -1213,6 +1198,34 @@ static bool func_name_refcount(char_u *name)
return isdigit(*name) || *name == '<';
}
+/// Call a user function after checking the arguments.
+static int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv,
+ funcexe_T *funcexe, dict_T *selfdict)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 4, 5)
+{
+ if (fp->uf_flags & FC_LUAREF) {
+ return typval_exec_lua_callable(fp->uf_luaref, argcount, argvars, rettv);
+ }
+
+ if ((fp->uf_flags & FC_RANGE) && funcexe->fe_doesrange != NULL) {
+ *funcexe->fe_doesrange = true;
+ }
+ int error;
+ if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
+ error = FCERR_TOOFEW;
+ } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) {
+ error = FCERR_TOOMANY;
+ } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) {
+ error = FCERR_DICT;
+ } else {
+ // Call the user function.
+ call_user_func(fp, argcount, argvars, rettv, funcexe->fe_firstline, funcexe->fe_lastline,
+ (fp->uf_flags & FC_DICT) ? selfdict : NULL);
+ error = FCERR_NONE;
+ }
+ return error;
+}
+
static funccal_entry_T *funccal_stack = NULL;
/// Save the current function call pointer, and set it to NULL.
@@ -1353,11 +1366,11 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict
});
funcexe_T funcexe = FUNCEXE_INIT;
- funcexe.firstline = curwin->w_cursor.lnum;
- funcexe.lastline = curwin->w_cursor.lnum;
- funcexe.evaluate = true;
- funcexe.partial = partial;
- funcexe.selfdict = selfdict;
+ funcexe.fe_firstline = curwin->w_cursor.lnum;
+ funcexe.fe_lastline = curwin->w_cursor.lnum;
+ funcexe.fe_evaluate = true;
+ funcexe.fe_partial = partial;
+ funcexe.fe_selfdict = selfdict;
r = call_func((char *)name, -1, rettv, argc, argv, &funcexe);
func_call_skip_call:
@@ -1375,27 +1388,27 @@ static void user_func_error(int error, const char_u *name)
FUNC_ATTR_NONNULL_ALL
{
switch (error) {
- case ERROR_UNKNOWN:
+ case FCERR_UNKNOWN:
emsg_funcname(N_("E117: Unknown function: %s"), name);
break;
- case ERROR_NOTMETHOD:
+ case FCERR_NOTMETHOD:
emsg_funcname(N_("E276: Cannot use function as a method: %s"), name);
break;
- case ERROR_DELETED:
+ case FCERR_DELETED:
emsg_funcname(N_("E933: Function was deleted: %s"), name);
break;
- case ERROR_TOOMANY:
+ case FCERR_TOOMANY:
emsg_funcname(_(e_toomanyarg), name);
break;
- case ERROR_TOOFEW:
+ case FCERR_TOOFEW:
emsg_funcname(N_("E119: Not enough arguments for function: %s"),
name);
break;
- case ERROR_SCRIPT:
+ case FCERR_SCRIPT:
emsg_funcname(N_("E120: Using <SID> not in a script context: %s"),
name);
break;
- case ERROR_DICT:
+ case FCERR_DICT:
emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"),
name);
break;
@@ -1435,27 +1448,27 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6)
{
int ret = FAIL;
- int error = ERROR_NONE;
+ int error = FCERR_NONE;
ufunc_T *fp = NULL;
- char_u fname_buf[FLEN_FIXED + 1];
- char_u *tofree = NULL;
- char_u *fname = NULL;
- char_u *name = NULL;
+ char fname_buf[FLEN_FIXED + 1];
+ char *tofree = NULL;
+ char *fname = NULL;
+ char *name = NULL;
int argcount = argcount_in;
typval_T *argvars = argvars_in;
- dict_T *selfdict = funcexe->selfdict;
+ dict_T *selfdict = funcexe->fe_selfdict;
typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" or
- // "funcexe->basetv" is not NULL
+ // "funcexe->fe_basetv" is not NULL
int argv_clear = 0;
int argv_base = 0;
- partial_T *partial = funcexe->partial;
+ partial_T *partial = funcexe->fe_partial;
// Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
// even when call_func() returns FAIL.
rettv->v_type = VAR_UNKNOWN;
if (len <= 0) {
- len = (int)STRLEN(funcname);
+ len = (int)strlen(funcname);
}
if (partial != NULL) {
fp = partial->pt_func;
@@ -1463,12 +1476,12 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
if (fp == NULL) {
// Make a copy of the name, if it comes from a funcref variable it could
// be changed or deleted in the called function.
- name = vim_strnsave((char_u *)funcname, (size_t)len);
- fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ name = xstrnsave(funcname, (size_t)len);
+ fname = fname_trans_sid(name, (char *)fname_buf, &tofree, &error);
}
- if (funcexe->doesrange != NULL) {
- *funcexe->doesrange = false;
+ if (funcexe->fe_doesrange != NULL) {
+ *funcexe->fe_doesrange = false;
}
if (partial != NULL) {
@@ -1478,10 +1491,10 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto)) {
selfdict = partial->pt_dict;
}
- if (error == ERROR_NONE && partial->pt_argc > 0) {
+ if (error == FCERR_NONE && partial->pt_argc > 0) {
for (argv_clear = 0; argv_clear < partial->pt_argc; argv_clear++) {
if (argv_clear + argcount_in >= MAX_FUNC_ARGS) {
- error = ERROR_TOOMANY;
+ error = FCERR_TOOMANY;
goto theend;
}
tv_copy(&partial->pt_argv[argv_clear], &argv[argv_clear]);
@@ -1494,8 +1507,8 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
}
}
- if (error == ERROR_NONE && funcexe->evaluate) {
- char_u *rfname = fname;
+ if (error == FCERR_NONE && funcexe->fe_evaluate) {
+ char *rfname = fname;
// Ignore "g:" before a function name.
if (fp == NULL && fname[0] == 'g' && fname[1] == ':') {
@@ -1504,12 +1517,12 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
rettv->v_type = VAR_NUMBER; // default rettv is number zero
rettv->vval.v_number = 0;
- error = ERROR_UNKNOWN;
+ error = FCERR_UNKNOWN;
if (is_luafunc(partial)) {
if (len > 0) {
- error = ERROR_NONE;
- argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base);
+ error = FCERR_NONE;
+ argv_add_base(funcexe->fe_basetv, &argvars, &argcount, argv, &argv_base);
nlua_typval_call(funcname, (size_t)len, argvars, argcount, rettv);
} else {
// v:lua was called directly; show its name in the emsg
@@ -1519,76 +1532,55 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t
} else if (fp != NULL || !builtin_function((const char *)rfname, -1)) {
// User defined function.
if (fp == NULL) {
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
// Trigger FuncUndefined event, may load the function.
if (fp == NULL
- && apply_autocmds(EVENT_FUNCUNDEFINED, (char *)rfname, (char *)rfname, true, NULL)
+ && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL)
&& !aborting()) {
// executed an autocommand, search for the function again
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
// Try loading a package.
- if (fp == NULL && script_autoload((const char *)rfname, STRLEN(rfname),
+ if (fp == NULL && script_autoload((const char *)rfname, strlen(rfname),
true) && !aborting()) {
// Loaded a package, search for the function again.
- fp = find_func(rfname);
+ fp = find_func((char_u *)rfname);
}
if (fp != NULL && (fp->uf_flags & FC_DELETED)) {
- error = ERROR_DELETED;
- } else if (fp != NULL && (fp->uf_flags & FC_CFUNC)) {
- cfunc_T cb = fp->uf_cb;
- error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
+ error = FCERR_DELETED;
} else if (fp != NULL) {
- if (funcexe->argv_func != NULL) {
+ if (funcexe->fe_argv_func != NULL) {
// postponed filling in the arguments, do it now
- argcount = funcexe->argv_func(argcount, argvars, argv_clear,
- fp->uf_args.ga_len);
+ argcount = funcexe->fe_argv_func(argcount, argvars, argv_clear, fp);
}
- argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base);
+ argv_add_base(funcexe->fe_basetv, &argvars, &argcount, argv, &argv_base);
- if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL) {
- *funcexe->doesrange = true;
- }
- if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
- error = ERROR_TOOFEW;
- } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) {
- error = ERROR_TOOMANY;
- } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) {
- error = ERROR_DICT;
- } else {
- // Call the user function.
- call_user_func(fp, argcount, argvars, rettv, funcexe->firstline,
- funcexe->lastline,
- (fp->uf_flags & FC_DICT) ? selfdict : NULL);
- error = ERROR_NONE;
- }
+ error = call_user_func_check(fp, argcount, argvars, rettv, funcexe, selfdict);
}
- } else if (funcexe->basetv != NULL) {
+ } else if (funcexe->fe_basetv != NULL) {
// expr->method(): Find the method name in the table, call its
// implementation with the base as one of the arguments.
- error = call_internal_method(fname, argcount, argvars, rettv,
- funcexe->basetv);
+ error = call_internal_method((char_u *)fname, argcount, argvars, rettv,
+ funcexe->fe_basetv);
} else {
// Find the function name in the table, call its implementation.
- error = call_internal_func(fname, argcount, argvars, rettv);
- }
- /*
- * The function call (or "FuncUndefined" autocommand sequence) might
- * have been aborted by an error, an interrupt, or an explicitly thrown
- * exception that has not been caught so far. This situation can be
- * tested for by calling aborting(). For an error in an internal
- * function or for the "E132" error in call_user_func(), however, the
- * throw point at which the "force_abort" flag (temporarily reset by
- * emsg()) is normally updated has not been reached yet. We need to
- * update that flag first to make aborting() reliable.
- */
+ error = call_internal_func((char_u *)fname, argcount, argvars, rettv);
+ }
+ // The function call (or "FuncUndefined" autocommand sequence) might
+ // have been aborted by an error, an interrupt, or an explicitly thrown
+ // exception that has not been caught so far. This situation can be
+ // tested for by calling aborting(). For an error in an internal
+ // function or for the "E132" error in call_user_func(), however, the
+ // throw point at which the "force_abort" flag (temporarily reset by
+ // emsg()) is normally updated has not been reached yet. We need to
+ // update that flag first to make aborting() reliable.
update_force_abort();
}
- if (error == ERROR_NONE) {
+ if (error == FCERR_NONE) {
ret = OK;
}
@@ -1596,7 +1588,7 @@ theend:
// Report an error unless the argument evaluation or function call has been
// cancelled due to an aborting error, an interrupt, or an exception.
if (!aborting()) {
- user_func_error(error, (name != NULL) ? name : (char_u *)funcname);
+ user_func_error(error, (name != NULL) ? (char_u *)name : (char_u *)funcname);
}
// clear the copies made from the partial
@@ -1682,7 +1674,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force)
char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial)
FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *name = NULL;
+ char *name = NULL;
const char_u *start;
const char_u *end;
int lead;
@@ -1720,11 +1712,9 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
goto theend;
}
if (end == NULL || (lv.ll_tv != NULL && (lead > 2 || lv.ll_range))) {
- /*
- * Report an invalid expression in braces, unless the expression
- * evaluation has been cancelled due to an aborting error, an
- * interrupt, or an exception.
- */
+ // Report an invalid expression in braces, unless the expression
+ // evaluation has been cancelled due to an aborting error, an
+ // interrupt, or an exception.
if (!aborting()) {
if (end != NULL) {
semsg(_(e_invarg2), start);
@@ -1743,7 +1733,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
fdp->fd_di = lv.ll_di;
}
if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) {
- name = vim_strsave((char_u *)lv.ll_tv->vval.v_string);
+ name = xstrdup(lv.ll_tv->vval.v_string);
*pp = (char *)end;
} else if (lv.ll_tv->v_type == VAR_PARTIAL
&& lv.ll_tv->vval.v_partial != NULL) {
@@ -1757,7 +1747,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
memcpy(name, end + 1, (size_t)len);
*pp = (char *)end + 1 + len;
} else {
- name = vim_strsave((char_u *)partial_name(lv.ll_tv->vval.v_partial));
+ name = xstrdup(partial_name(lv.ll_tv->vval.v_partial));
*pp = (char *)end;
}
if (partial != NULL) {
@@ -1785,28 +1775,28 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
// Check if the name is a Funcref. If so, use the value.
if (lv.ll_exp_name != NULL) {
len = (int)strlen(lv.ll_exp_name);
- name = deref_func_name(lv.ll_exp_name, &len, partial,
- flags & TFN_NO_AUTOLOAD);
+ name = (char *)deref_func_name(lv.ll_exp_name, &len, partial,
+ flags & TFN_NO_AUTOLOAD);
if ((const char *)name == lv.ll_exp_name) {
name = NULL;
}
} else if (!(flags & TFN_NO_DEREF)) {
len = (int)(end - (char_u *)(*pp));
- name = deref_func_name((const char *)(*pp), &len, partial,
- flags & TFN_NO_AUTOLOAD);
- if (name == (char_u *)(*pp)) {
+ name = (char *)deref_func_name((const char *)(*pp), &len, partial,
+ flags & TFN_NO_AUTOLOAD);
+ if (name == *pp) {
name = NULL;
}
}
if (name != NULL) {
- name = vim_strsave(name);
+ name = xstrdup(name);
*pp = (char *)end;
if (STRNCMP(name, "<SNR>", 5) == 0) {
// Change "<SNR>" to the byte sequence.
- name[0] = K_SPECIAL;
- name[1] = KS_EXTRA;
+ name[0] = (char)K_SPECIAL;
+ name[1] = (char)KS_EXTRA;
name[2] = KE_SNR;
- memmove(name + 3, name + 5, strlen((char *)name + 5) + 1);
+ memmove(name + 3, name + 5, strlen(name + 5) + 1);
}
goto theend;
}
@@ -1869,8 +1859,8 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
name = xmalloc((size_t)len + (size_t)lead + 1);
if (!skip && lead > 0) {
- name[0] = K_SPECIAL;
- name[1] = KS_EXTRA;
+ name[0] = (char)K_SPECIAL;
+ name[1] = (char)KS_EXTRA;
name[2] = KE_SNR;
if (sid_buf_len > 0) { // If it's "<SID>"
memcpy(name + 3, sid_buf, sid_buf_len);
@@ -1882,7 +1872,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa
theend:
clear_lval(&lv);
- return name;
+ return (char_u *)name;
}
#define MAX_FUNC_NESTING 50
@@ -1890,15 +1880,15 @@ theend:
/// ":function"
void ex_function(exarg_T *eap)
{
- char_u *theline;
- char_u *line_to_free = NULL;
- char_u c;
+ char *theline;
+ char *line_to_free = NULL;
+ char c;
int saved_did_emsg;
bool saved_wait_return = need_wait_return;
- char_u *name = NULL;
- char_u *p;
- char_u *arg;
- char_u *line_arg = NULL;
+ char *name = NULL;
+ char *p;
+ char *arg;
+ char *line_arg = NULL;
garray_T newargs;
garray_T default_args;
garray_T newlines;
@@ -1918,14 +1908,12 @@ void ex_function(exarg_T *eap)
linenr_T sourcing_lnum_off;
linenr_T sourcing_lnum_top;
bool is_heredoc = false;
- char_u *skip_until = NULL;
- char_u *heredoc_trimmed = NULL;
+ char *skip_until = NULL;
+ char *heredoc_trimmed = NULL;
bool show_block = false;
bool do_concat = true;
- /*
- * ":function" without argument: list functions.
- */
+ // ":function" without argument: list functions.
if (ends_excmd(*eap->arg)) {
if (!eap->skip) {
todo = (int)func_hashtab.ht_used;
@@ -1933,7 +1921,7 @@ void ex_function(exarg_T *eap)
if (!HASHITEM_EMPTY(hi)) {
todo--;
fp = HI2UF(hi);
- if (message_filtered(fp->uf_name)) {
+ if (message_filtered((char *)fp->uf_name)) {
continue;
}
if (!func_name_refcount(fp->uf_name)) {
@@ -1942,15 +1930,13 @@ void ex_function(exarg_T *eap)
}
}
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)eap->arg);
+ eap->nextcmd = check_nextcmd(eap->arg);
return;
}
- /*
- * ":function /pat": list functions matching pattern.
- */
+ // ":function /pat": list functions matching pattern.
if (*eap->arg == '/') {
- p = skip_regexp((char_u *)eap->arg + 1, '/', true, NULL);
+ p = skip_regexp(eap->arg + 1, '/', true, NULL);
if (!eap->skip) {
regmatch_T regmatch;
@@ -1978,7 +1964,7 @@ void ex_function(exarg_T *eap)
if (*p == '/') {
p++;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd(p);
return;
}
@@ -1996,15 +1982,20 @@ void ex_function(exarg_T *eap)
// "fudi.fd_di" set, "fudi.fd_newkey" == NULL
// s:func script-local function name
// g:func global function name, same as "func"
- p = (char_u *)eap->arg;
- name = trans_function_name((char **)&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
- paren = (vim_strchr((char *)p, '(') != NULL);
+ p = eap->arg;
+ if (strncmp(p, "<lambda>", 8) == 0) {
+ p += 8;
+ (void)getdigits(&p, false, 0);
+ name = xstrndup(eap->arg, (size_t)(p - eap->arg));
+ CLEAR_FIELD(fudi);
+ } else {
+ name = (char *)trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
+ }
+ paren = (vim_strchr(p, '(') != NULL);
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) {
- /*
- * Return on an invalid expression in braces, unless the expression
- * evaluation has been cancelled due to an aborting error, an
- * interrupt, or an exception.
- */
+ // Return on an invalid expression in braces, unless the expression
+ // evaluation has been cancelled due to an aborting error, an
+ // interrupt, or an exception.
if (!aborting()) {
if (fudi.fd_newkey != NULL) {
semsg(_(e_dictkey), fudi.fd_newkey);
@@ -2028,16 +2019,16 @@ void ex_function(exarg_T *eap)
// - exclude line numbers from function body
//
if (!paren) {
- if (!ends_excmd(*skipwhite((char *)p))) {
+ if (!ends_excmd(*skipwhite(p))) {
semsg(_(e_trailing_arg), p);
goto ret_free;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd(p);
if (eap->nextcmd != NULL) {
*p = NUL;
}
if (!eap->skip && !got_int) {
- fp = find_func(name);
+ fp = find_func((char_u *)name);
if (fp != NULL) {
list_func_head(fp, !eap->forceit, eap->forceit);
for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) {
@@ -2054,7 +2045,7 @@ void ex_function(exarg_T *eap)
msg_putchar(' ');
}
}
- msg_prt_line((char_u *)FUNCLINE(fp, j), false);
+ msg_prt_line(FUNCLINE(fp, j), false);
ui_flush(); // show a line at a time
os_breakcheck();
}
@@ -2063,27 +2054,25 @@ void ex_function(exarg_T *eap)
msg_puts(eap->forceit ? "endfunction" : " endfunction");
}
} else {
- emsg_funcname(N_("E123: Undefined function: %s"), name);
+ emsg_funcname(N_("E123: Undefined function: %s"), (char_u *)name);
}
}
goto ret_free;
}
- /*
- * ":function name(arg1, arg2)" Define function.
- */
- p = (char_u *)skipwhite((char *)p);
+ // ":function name(arg1, arg2)" Define function.
+ p = skipwhite(p);
if (*p != '(') {
if (!eap->skip) {
semsg(_("E124: Missing '(': %s"), eap->arg);
goto ret_free;
}
// attempt to continue by skipping some text
- if (vim_strchr((char *)p, '(') != NULL) {
- p = (char_u *)vim_strchr((char *)p, '(');
+ if (vim_strchr(p, '(') != NULL) {
+ p = vim_strchr(p, '(');
}
}
- p = (char_u *)skipwhite((char *)p + 1);
+ p = skipwhite(p + 1);
ga_init(&newargs, (int)sizeof(char_u *), 3);
ga_init(&newlines, (int)sizeof(char_u *), 3);
@@ -2094,15 +2083,15 @@ void ex_function(exarg_T *eap)
if (name != NULL) {
arg = name;
} else {
- arg = fudi.fd_newkey;
+ arg = (char *)fudi.fd_newkey;
}
if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) {
- int j = (*arg == K_SPECIAL) ? 3 : 0;
+ int j = ((uint8_t)(*arg) == K_SPECIAL) ? 3 : 0;
while (arg[j] != NUL && (j == 0 ? eval_isnamec1(arg[j]) : eval_isnamec(arg[j]))) {
j++;
}
if (arg[j] != NUL) {
- emsg_funcname((char *)e_invarg2, arg);
+ emsg_funcname((char *)e_invarg2, (char_u *)arg);
}
}
// Disallow using the g: dict.
@@ -2111,7 +2100,7 @@ void ex_function(exarg_T *eap)
}
}
- if (get_function_args((char **)&p, ')', &newargs, &varargs,
+ if (get_function_args(&p, ')', &newargs, &varargs,
&default_args, eap->skip) == FAIL) {
goto errret_2;
}
@@ -2123,7 +2112,7 @@ void ex_function(exarg_T *eap)
// find extra arguments "range", "dict", "abort" and "closure"
for (;;) {
- p = (char_u *)skipwhite((char *)p);
+ p = skipwhite(p);
if (STRNCMP(p, "range", 5) == 0) {
flags |= FC_RANGE;
p += 5;
@@ -2137,9 +2126,8 @@ void ex_function(exarg_T *eap)
flags |= FC_CLOSURE;
p += 7;
if (current_funccal == NULL) {
- emsg_funcname(N_
- ("E932: Closure function should not be at top level: %s"),
- name == NULL ? (char_u *)"" : name);
+ emsg_funcname(N_("E932: Closure function should not be at top level: %s"),
+ name == NULL ? (char_u *)"" : (char_u *)name);
goto erret;
}
} else {
@@ -2155,9 +2143,7 @@ void ex_function(exarg_T *eap)
semsg(_(e_trailing_arg), p);
}
- /*
- * Read the body of the function, until ":endfunction" is found.
- */
+ // Read the body of the function, until ":endfunction" is found.
if (KeyTyped) {
// Check if the function already exists, don't let the user type the
// whole function before telling him it doesn't work! For a script we
@@ -2165,8 +2151,8 @@ void ex_function(exarg_T *eap)
if (!eap->skip && !eap->forceit) {
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) {
emsg(_(e_funcdict));
- } else if (name != NULL && find_func(name) != NULL) {
- emsg_funcname(e_funcexts, name);
+ } else if (name != NULL && find_func((char_u *)name) != NULL) {
+ emsg_funcname(e_funcexts, (char_u *)name);
}
}
@@ -2195,9 +2181,9 @@ void ex_function(exarg_T *eap)
if (line_arg != NULL) {
// Use eap->arg, split up in parts by line breaks.
theline = line_arg;
- p = (char_u *)vim_strchr((char *)theline, '\n');
+ p = vim_strchr(theline, '\n');
if (p == NULL) {
- line_arg += STRLEN(line_arg);
+ line_arg += strlen(line_arg);
} else {
*p = NUL;
line_arg = p + 1;
@@ -2205,9 +2191,9 @@ void ex_function(exarg_T *eap)
} else {
xfree(line_to_free);
if (eap->getline == NULL) {
- theline = getcmdline(':', 0L, indent, do_concat);
+ theline = (char *)getcmdline(':', 0L, indent, do_concat);
} else {
- theline = (char_u *)eap->getline(':', eap->cookie, indent, do_concat);
+ theline = eap->getline(':', eap->cookie, indent, do_concat);
}
line_to_free = theline;
}
@@ -2237,18 +2223,18 @@ void ex_function(exarg_T *eap)
// * ":python <<EOF" and "EOF"
// * ":let {var-name} =<< [trim] {marker}" and "{marker}"
if (heredoc_trimmed == NULL
- || (is_heredoc && (char_u *)skipwhite((char *)theline) == theline)
+ || (is_heredoc && skipwhite(theline) == theline)
|| STRNCMP(theline, heredoc_trimmed,
- STRLEN(heredoc_trimmed)) == 0) {
+ strlen(heredoc_trimmed)) == 0) {
if (heredoc_trimmed == NULL) {
p = theline;
} else if (is_heredoc) {
- p = (char_u *)skipwhite((char *)theline) == theline
- ? theline : theline + STRLEN(heredoc_trimmed);
+ p = skipwhite(theline) == theline
+ ? theline : theline + strlen(heredoc_trimmed);
} else {
- p = theline + STRLEN(heredoc_trimmed);
+ p = theline + strlen(heredoc_trimmed);
}
- if (STRCMP(p, skip_until) == 0) {
+ if (strcmp(p, skip_until) == 0) {
XFREE_CLEAR(skip_until);
XFREE_CLEAR(heredoc_trimmed);
do_concat = true;
@@ -2260,27 +2246,26 @@ void ex_function(exarg_T *eap)
for (p = theline; ascii_iswhite(*p) || *p == ':'; p++) {}
// Check for "endfunction".
- if (checkforcmd((char **)&p, "endfunction", 4) && nesting-- == 0) {
+ if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) {
if (*p == '!') {
p++;
}
- char_u *nextcmd = NULL;
+ char *nextcmd = NULL;
if (*p == '|') {
nextcmd = p + 1;
- } else if (line_arg != NULL && *skipwhite((char *)line_arg) != NUL) {
+ } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) {
nextcmd = line_arg;
} else if (*p != NUL && *p != '"' && p_verbose > 0) {
- give_warning2((char_u *)_("W22: Text found after :endfunction: %s"),
- p, true);
+ give_warning2(_("W22: Text found after :endfunction: %s"), p, true);
}
if (nextcmd != NULL) {
// Another command follows. If the line came from "eap" we
// can simply point into it, otherwise we need to change
// "eap->cmdlinep".
- eap->nextcmd = (char *)nextcmd;
+ eap->nextcmd = nextcmd;
if (line_to_free != NULL) {
xfree(*eap->cmdlinep);
- *eap->cmdlinep = (char *)line_to_free;
+ *eap->cmdlinep = line_to_free;
line_to_free = NULL;
}
}
@@ -2299,13 +2284,13 @@ void ex_function(exarg_T *eap)
}
// Check for defining a function inside this function.
- if (checkforcmd((char **)&p, "function", 2)) {
+ if (checkforcmd(&p, "function", 2)) {
if (*p == '!') {
- p = (char_u *)skipwhite((char *)p + 1);
+ p = skipwhite(p + 1);
}
p += eval_fname_script((const char *)p);
- xfree(trans_function_name((char **)&p, true, 0, NULL, NULL));
- if (*skipwhite((char *)p) == '(') {
+ xfree(trans_function_name(&p, true, 0, NULL, NULL));
+ if (*skipwhite(p) == '(') {
if (nesting == MAX_FUNC_NESTING - 1) {
emsg(_("E1058: function nesting too deep"));
} else {
@@ -2316,7 +2301,7 @@ void ex_function(exarg_T *eap)
}
// Check for ":append", ":change", ":insert".
- p = (char_u *)skip_range((char *)p, NULL);
+ p = skip_range(p, NULL);
if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p'))
|| (p[0] == 'c'
&& (!ASCII_ISALPHA(p[1])
@@ -2328,11 +2313,11 @@ void ex_function(exarg_T *eap)
&& (!ASCII_ISALPHA(p[1]) || (p[1] == 'n'
&& (!ASCII_ISALPHA(p[2])
|| (p[2] == 's')))))) {
- skip_until = vim_strsave((char_u *)".");
+ skip_until = xstrdup(".");
}
// heredoc: Check for ":python <<EOF", ":lua <<EOF", etc.
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = skipwhite(skiptowhite(p));
if (arg[0] == '<' && arg[1] == '<'
&& ((p[0] == 'p' && p[1] == 'y'
&& (!ASCII_ISALNUM(p[2]) || p[2] == 't'
@@ -2349,22 +2334,22 @@ void ex_function(exarg_T *eap)
|| (p[0] == 'm' && p[1] == 'z'
&& (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) {
// ":python <<" continues until a dot, like ":append"
- p = (char_u *)skipwhite((char *)arg + 2);
+ p = skipwhite(arg + 2);
if (*p == NUL) {
- skip_until = vim_strsave((char_u *)".");
+ skip_until = xstrdup(".");
} else {
- skip_until = vim_strsave(p);
+ skip_until = xstrdup(p);
}
}
// Check for ":let v =<< [trim] EOF"
// and ":let [a, b] =<< [trim] EOF"
- arg = (char_u *)skipwhite((char *)skiptowhite(p));
+ arg = skipwhite(skiptowhite(p));
if (*arg == '[') {
- arg = (char_u *)vim_strchr((char *)arg, ']');
+ arg = vim_strchr(arg, ']');
}
if (arg != NULL) {
- arg = (char_u *)skipwhite((char *)skiptowhite(arg));
+ arg = skipwhite(skiptowhite(arg));
if (arg[0] == '='
&& arg[1] == '<'
&& arg[2] == '<'
@@ -2372,14 +2357,13 @@ void ex_function(exarg_T *eap)
&& p[1] == 'e'
&& (!ASCII_ISALNUM(p[2])
|| (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) {
- p = (char_u *)skipwhite((char *)arg + 3);
+ p = skipwhite(arg + 3);
if (STRNCMP(p, "trim", 4) == 0) {
// Ignore leading white space.
- p = (char_u *)skipwhite((char *)p + 4);
- heredoc_trimmed =
- vim_strnsave(theline, (size_t)((char_u *)skipwhite((char *)theline) - theline));
+ p = skipwhite(p + 4);
+ heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline));
}
- skip_until = vim_strnsave(p, (size_t)(skiptowhite(p) - p));
+ skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p));
do_concat = false;
is_heredoc = true;
}
@@ -2392,8 +2376,8 @@ void ex_function(exarg_T *eap)
// Copy the line to newly allocated memory. get_one_sourceline()
// allocates 250 bytes per line, this saves 80% on average. The cost
// is an extra alloc/free.
- p = vim_strsave(theline);
- ((char **)(newlines.ga_data))[newlines.ga_len++] = (char *)p;
+ p = xstrdup(theline);
+ ((char **)(newlines.ga_data))[newlines.ga_len++] = p;
// Add NULL lines for continuation lines, so that the line count is
// equal to the index in the growarray.
@@ -2413,30 +2397,28 @@ void ex_function(exarg_T *eap)
goto erret;
}
- /*
- * If there are no errors, add the function
- */
+ // If there are no errors, add the function
if (fudi.fd_dict == NULL) {
- v = find_var((const char *)name, STRLEN(name), &ht, false);
+ v = find_var((const char *)name, strlen(name), &ht, false);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
emsg_funcname(N_("E707: Function name conflicts with variable: %s"),
- name);
+ (char_u *)name);
goto erret;
}
- fp = find_func(name);
+ fp = find_func((char_u *)name);
if (fp != NULL) {
// Function can be replaced with "function!" and when sourcing the
// same script again, but only once.
if (!eap->forceit
&& (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid
|| fp->uf_script_ctx.sc_seq == current_sctx.sc_seq)) {
- emsg_funcname(e_funcexts, name);
+ emsg_funcname(e_funcexts, (char_u *)name);
goto erret;
}
if (fp->uf_calls > 0) {
emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"),
- name);
+ (char_u *)name);
goto erret;
}
if (fp->uf_refcount > 1) {
@@ -2480,23 +2462,23 @@ void ex_function(exarg_T *eap)
// Give the function a sequential number. Can only be used with a
// Funcref!
xfree(name);
- sprintf(numbuf, "%d", ++func_nr);
- name = vim_strsave((char_u *)numbuf);
+ sprintf(numbuf, "%d", ++func_nr); // NOLINT(runtime/printf)
+ name = xstrdup(numbuf);
}
if (fp == NULL) {
- if (fudi.fd_dict == NULL && vim_strchr((char *)name, AUTOLOAD_CHAR) != NULL) {
+ if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) {
int slen, plen;
char_u *scriptname;
// Check that the autoload name matches the script name.
int j = FAIL;
if (SOURCING_NAME != NULL) {
- scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name));
- p = (char_u *)vim_strchr((char *)scriptname, '/');
+ scriptname = (char_u *)autoload_name((const char *)name, strlen(name));
+ p = vim_strchr((char *)scriptname, '/');
plen = (int)STRLEN(p);
slen = (int)STRLEN(SOURCING_NAME);
- if (slen > plen && FNAMECMP(p, SOURCING_NAME + slen - plen) == 0) {
+ if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) {
j = OK;
}
xfree(scriptname);
@@ -2508,7 +2490,7 @@ void ex_function(exarg_T *eap)
}
}
- fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
+ fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1);
if (fudi.fd_dict != NULL) {
if (fudi.fd_di == NULL) {
@@ -2524,16 +2506,16 @@ void ex_function(exarg_T *eap)
tv_clear(&fudi.fd_di->di_tv);
}
fudi.fd_di->di_tv.v_type = VAR_FUNC;
- fudi.fd_di->di_tv.vval.v_string = (char *)vim_strsave(name);
+ fudi.fd_di->di_tv.vval.v_string = xstrdup(name);
// behave like "dict" was used
flags |= FC_DICT;
}
// insert the new function in the function list
- set_ufunc_name(fp, name);
+ set_ufunc_name(fp, (char_u *)name);
if (overwrite) {
- hi = hash_find(&func_hashtab, (char *)name);
+ hi = hash_find(&func_hashtab, name);
hi->hi_key = UF2HIKEY(fp);
} else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) {
xfree(fp);
@@ -2590,8 +2572,8 @@ int eval_fname_script(const char *const p)
// Use mb_strnicmp() because in Turkish comparing the "I" may not work with
// the standard library function.
if (p[0] == '<'
- && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0
- || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) {
+ && (mb_strnicmp(p + 1, "SID>", 4) == 0
+ || mb_strnicmp(p + 1, "SNR>", 4) == 0)) {
return 5;
}
if (p[0] == 's' && p[1] == ':') {
@@ -2666,7 +2648,7 @@ char *get_user_func_name(expand_T *xp, int idx)
return (char *)fp->uf_name; // Prevent overflow.
}
- cat_func_name(IObuff, fp);
+ cat_func_name((char_u *)IObuff, fp);
if (xp->xp_context != EXPAND_USER_FUNC) {
STRCAT(IObuff, "(");
if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) {
@@ -2700,7 +2682,7 @@ void ex_delfunction(exarg_T *eap)
semsg(_(e_trailing_arg), p);
return;
}
- eap->nextcmd = (char *)check_nextcmd(p);
+ eap->nextcmd = check_nextcmd((char *)p);
if (eap->nextcmd != NULL) {
*p = NUL;
}
@@ -2889,7 +2871,7 @@ void ex_return(exarg_T *eap)
if (returning) {
eap->nextcmd = NULL;
} else if (eap->nextcmd == NULL) { // no argument
- eap->nextcmd = (char *)check_nextcmd(arg);
+ eap->nextcmd = check_nextcmd((char *)arg);
}
if (eap->skip) {
@@ -2975,12 +2957,12 @@ void ex_call(exarg_T *eap)
arg = startarg;
funcexe_T funcexe = FUNCEXE_INIT;
- funcexe.firstline = eap->line1;
- funcexe.lastline = eap->line2;
- funcexe.doesrange = &doesrange;
- funcexe.evaluate = true;
- funcexe.partial = partial;
- funcexe.selfdict = fudi.fd_dict;
+ funcexe.fe_firstline = eap->line1;
+ funcexe.fe_lastline = eap->line2;
+ funcexe.fe_doesrange = &doesrange;
+ funcexe.fe_evaluate = true;
+ funcexe.fe_partial = partial;
+ funcexe.fe_selfdict = fudi.fd_dict;
if (get_func_tv(name, -1, &rettv, (char **)&arg, &funcexe) == FAIL) {
failed = true;
break;
@@ -3010,7 +2992,7 @@ void ex_call(exarg_T *eap)
// When inside :try we need to check for following "| catch" or "| endtry".
// Not when there was an error, but do check if an exception was thrown.
- if ((!aborting() || current_exception != NULL) && (!failed || eap->cstack->cs_trylevel > 0)) {
+ if ((!aborting() || did_throw) && (!failed || eap->cstack->cs_trylevel > 0)) {
// Check for trailing illegal characters and a following command.
if (!ends_excmd(*arg)) {
if (!failed && !aborting()) {
@@ -3018,7 +3000,7 @@ void ex_call(exarg_T *eap)
semsg(_(e_trailing_arg), arg);
}
} else {
- eap->nextcmd = (char *)check_nextcmd(arg);
+ eap->nextcmd = check_nextcmd((char *)arg);
}
}
@@ -3105,25 +3087,25 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
/// Generate a return command for producing the value of "rettv". The result
/// is an allocated string. Used by report_pending() for verbose messages.
-char_u *get_return_cmd(void *rettv)
+char *get_return_cmd(void *rettv)
{
- char_u *s = NULL;
- char_u *tofree = NULL;
+ char *s = NULL;
+ char *tofree = NULL;
if (rettv != NULL) {
- tofree = s = (char_u *)encode_tv2echo((typval_T *)rettv, NULL);
+ tofree = s = encode_tv2echo((typval_T *)rettv, NULL);
}
if (s == NULL) {
- s = (char_u *)"";
+ s = "";
}
STRCPY(IObuff, ":return ");
STRLCPY(IObuff + 8, s, IOSIZE - 8);
- if (STRLEN(s) + 8 >= IOSIZE) {
+ if (strlen(s) + 8 >= IOSIZE) {
STRCPY(IObuff + IOSIZE - 4, "...");
}
xfree(tofree);
- return vim_strsave(IObuff);
+ return xstrdup((char *)IObuff);
}
/// Get next function line.
@@ -3134,12 +3116,12 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
{
funccall_T *fcp = (funccall_T *)cookie;
ufunc_T *fp = fcp->func;
- char_u *retval;
+ char *retval;
garray_T *gap; // growarray with function lines
// If breakpoints have been added/deleted need to check for it.
if (fcp->dbg_tick != debug_tick) {
- fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM);
+ fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM);
fcp->dbg_tick = debug_tick;
}
if (do_profiling == PROF_YES) {
@@ -3159,7 +3141,7 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
if (fcp->linenr >= gap->ga_len) {
retval = NULL;
} else {
- retval = (char_u *)xstrdup(((char **)(gap->ga_data))[fcp->linenr++]);
+ retval = xstrdup(((char **)(gap->ga_data))[fcp->linenr++]);
SOURCING_LNUM = fcp->linenr;
if (do_profiling == PROF_YES) {
func_line_start(cookie);
@@ -3169,13 +3151,13 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat)
// Did we encounter a breakpoint?
if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) {
- dbg_breakpoint(fp->uf_name, SOURCING_LNUM);
+ dbg_breakpoint((char *)fp->uf_name, SOURCING_LNUM);
// Find next breakpoint.
- fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM);
+ fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM);
fcp->dbg_tick = debug_tick;
}
- return (char *)retval;
+ return retval;
}
/// @return true if the currently active function should be ended, because a
@@ -3211,9 +3193,9 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
} else {
fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING
? (char_u *)rettv->vval.v_string
- : rettv->vval.v_partial->pt_name;
+ : (char_u *)rettv->vval.v_partial->pt_name;
// Translate "s:func" to the stored function name.
- fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
+ fname = (char_u *)fname_trans_sid((char *)fname, (char *)fname_buf, (char **)&tofree, &error);
fp = find_func(fname);
xfree(tofree);
}
@@ -3227,7 +3209,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
pt->pt_auto = true;
if (rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING) {
// Just a function: Take over the function name and use selfdict.
- pt->pt_name = (char_u *)rettv->vval.v_string;
+ pt->pt_name = rettv->vval.v_string;
} else {
partial_T *ret_pt = rettv->vval.v_partial;
int i;
@@ -3236,8 +3218,8 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv)
// args. Can't take over name or args, the partial might
// be referenced elsewhere.
if (ret_pt->pt_name != NULL) {
- pt->pt_name = vim_strsave(ret_pt->pt_name);
- func_ref(pt->pt_name);
+ pt->pt_name = xstrdup(ret_pt->pt_name);
+ func_ref((char_u *)pt->pt_name);
} else {
pt->pt_func = ret_pt->pt_func;
func_ptr_ref(pt->pt_func);
@@ -3549,7 +3531,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
{
ufunc_T *fp = fp_in;
funccall_T *fc;
- int error = ERROR_NONE;
+ int error = FCERR_NONE;
char_u fname_buf[FLEN_FIXED + 1];
char_u *tofree = NULL;
char_u *fname;
@@ -3559,7 +3541,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
}
if (fp_in == NULL) {
- fname = fname_trans_sid(name, fname_buf, &tofree, &error);
+ fname = (char_u *)fname_trans_sid((char *)name, (char *)fname_buf, (char **)&tofree, &error);
fp = find_func(fname);
}
if (fp != NULL) {
@@ -3571,20 +3553,18 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
return abort;
}
-/// Registers a C extension user function.
-char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state)
+/// Registers a luaref as a lambda.
+char_u *register_luafunc(LuaRef ref)
{
char_u *name = get_lambda_name();
ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
fp->uf_refcount = 1;
fp->uf_varargs = true;
- fp->uf_flags = FC_CFUNC;
+ fp->uf_flags = FC_LUAREF;
fp->uf_calls = 0;
fp->uf_script_ctx = current_sctx;
- fp->uf_cb = cb;
- fp->uf_cb_free = cb_free;
- fp->uf_cb_state = state;
+ fp->uf_luaref = ref;
STRCPY(fp->uf_name, name);
hash_add(&func_hashtab, UF2HIKEY(fp));
diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h
index 4b7007aae9..4098622a14 100644
--- a/src/nvim/eval/userfunc.h
+++ b/src/nvim/eval/userfunc.h
@@ -9,6 +9,20 @@
#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name)))
#define HI2UF(hi) HIKEY2UF((hi)->hi_key)
+// flags used in uf_flags
+#define FC_ABORT 0x01 // abort function on error
+#define FC_RANGE 0x02 // function accepts range
+#define FC_DICT 0x04 // Dict function, uses "self"
+#define FC_CLOSURE 0x08 // closure, uses outer scope variables
+#define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0
+#define FC_REMOVED 0x20 // function redefined while uf_refcount > 0
+#define FC_SANDBOX 0x40 // function defined in the sandbox
+#define FC_DEAD 0x80 // function kept only for reference to dfunc
+#define FC_EXPORT 0x100 // "export def Func()"
+#define FC_NOARGS 0x200 // no a: variables in lambda
+#define FC_VIM9 0x400 // defined in vim9 script file
+#define FC_LUAREF 0x800 // luaref callback
+
///< Structure used by trans_function_name()
typedef struct {
dict_T *fd_dict; ///< Dictionary used.
@@ -24,44 +38,43 @@ struct funccal_entry {
/// errors for when calling a function
typedef enum {
- ERROR_UNKNOWN = 0,
- ERROR_TOOMANY,
- ERROR_TOOFEW,
- ERROR_SCRIPT,
- ERROR_DICT,
- ERROR_NONE,
- ERROR_OTHER,
- ERROR_BOTH,
- ERROR_DELETED,
- ERROR_NOTMETHOD,
+ FCERR_UNKNOWN = 0,
+ FCERR_TOOMANY = 1,
+ FCERR_TOOFEW = 2,
+ FCERR_SCRIPT = 3,
+ FCERR_DICT = 4,
+ FCERR_NONE = 5,
+ FCERR_OTHER = 6,
+ FCERR_DELETED = 7,
+ FCERR_NOTMETHOD = 8, ///< function cannot be used as a method
} FnameTransError;
/// Used in funcexe_T. Returns the new argcount.
-typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip,
- int called_func_argcount);
+typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int partial_argcount,
+ ufunc_T *called_func);
/// Structure passed between functions dealing with function call execution.
typedef struct {
- ArgvFunc argv_func; ///< when not NULL, can be used to fill in arguments only
- ///< when the invoked function uses them
- linenr_T firstline; ///< first line of range
- linenr_T lastline; ///< last line of range
- bool *doesrange; ///< [out] if not NULL: function handled range
- bool evaluate; ///< actually evaluate expressions
- partial_T *partial; ///< for extra arguments
- dict_T *selfdict; ///< Dictionary for "self"
- typval_T *basetv; ///< base for base->method()
+ ArgvFunc fe_argv_func; ///< when not NULL, can be used to fill in arguments only
+ ///< when the invoked function uses them
+ linenr_T fe_firstline; ///< first line of range
+ linenr_T fe_lastline; ///< last line of range
+ bool *fe_doesrange; ///< [out] if not NULL: function handled range
+ bool fe_evaluate; ///< actually evaluate expressions
+ partial_T *fe_partial; ///< for extra arguments
+ dict_T *fe_selfdict; ///< Dictionary for "self"
+ typval_T *fe_basetv; ///< base for base->method()
} funcexe_T;
#define FUNCEXE_INIT (funcexe_T) { \
- .argv_func = NULL, \
- .firstline = 0, \
- .lastline = 0, \
- .doesrange = NULL, \
- .evaluate = false, \
- .partial = NULL, \
- .selfdict = NULL, \
- .basetv = NULL, \
+ .fe_argv_func = NULL, \
+ .fe_firstline = 0, \
+ .fe_lastline = 0, \
+ .fe_doesrange = NULL, \
+ .fe_evaluate = false, \
+ .fe_partial = NULL, \
+ .fe_selfdict = NULL, \
+ .fe_basetv = NULL, \
}
#define FUNCARG(fp, j) ((char **)(fp->uf_args.ga_data))[j]
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 0086cc41ca..4d7214205d 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -81,7 +81,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
// The marker is the next word.
if (*cmd != NUL && *cmd != '"') {
marker = skipwhite(cmd);
- p = (char *)skiptowhite((char_u *)marker);
+ p = skiptowhite(marker);
if (*skipwhite(p) != NUL && *skipwhite(p) != '"') {
semsg(_(e_trailing_arg), p);
return NULL;
@@ -113,7 +113,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd)
&& STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0) {
mi = marker_indent_len;
}
- if (STRCMP(marker, theline + mi) == 0) {
+ if (strcmp(marker, theline + mi) == 0) {
xfree(theline);
break;
}
@@ -207,7 +207,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const)
list_func_vars(&first);
list_vim_vars(&first);
}
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
} else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') {
// HERE document
list_T *l = heredoc_get(eap, expr + 3);
@@ -413,7 +413,7 @@ void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, int *firs
// apply :filter /pat/ to variable name
xstrlcpy(buf, prefix, IOSIZE);
xstrlcat(buf, (char *)di->di_key, IOSIZE);
- if (message_filtered((char_u *)buf)) {
+ if (message_filtered(buf)) {
continue;
}
@@ -587,7 +587,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
char *s = vim_getenv(name);
if (s != NULL) {
- tofree = (char *)concat_str((const char_u *)s, (const char_u *)p);
+ tofree = concat_str(s, p);
p = (const char *)tofree;
xfree(s);
}
@@ -663,8 +663,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
} else if (opt_type == gov_string && stringval != NULL && s != NULL) {
// string
char *const oldstringval = stringval;
- stringval = (char *)concat_str((const char_u *)stringval,
- (const char_u *)s);
+ stringval = concat_str(stringval, s);
xfree(oldstringval);
s = stringval;
}
@@ -705,14 +704,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo
if (p != NULL && op != NULL && *op == '.') {
s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
if (s != NULL) {
- ptofree = (char *)concat_str((char_u *)s, (const char_u *)p);
+ ptofree = concat_str(s, p);
p = (const char *)ptofree;
xfree(s);
}
}
if (p != NULL) {
- write_reg_contents(*arg == '@' ? '"' : *arg,
- (const char_u *)p, (ssize_t)STRLEN(p), false);
+ write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)strlen(p), false);
arg_end = arg + 1;
}
xfree(ptofree);
@@ -826,7 +824,7 @@ static void ex_unletlock(exarg_T *eap, char *argstart, int deep, ex_unletlock_ca
arg = skipwhite(name_end);
} while (!ends_excmd(*arg));
- eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
+ eap->nextcmd = check_nextcmd(arg);
}
// TODO(ZyX-I): move to eval/ex_cmds
@@ -1350,12 +1348,8 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv,
}
if (watched) {
- if (oldtv.v_type == VAR_UNKNOWN) {
- tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, NULL);
- } else {
- tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv);
- tv_clear(&oldtv);
- }
+ tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv);
+ tv_clear(&oldtv);
}
if (is_const) {
@@ -1803,7 +1797,7 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
// reset notion of buffer
aucmd_restbuf(&aco);
} else {
- const size_t varname_len = STRLEN(varname);
+ const size_t varname_len = strlen(varname);
char *const bufvarname = xmalloc(varname_len + 3);
buf_T *const save_curbuf = curbuf;
curbuf = buf;