diff options
Diffstat (limited to 'src/nvim/eval')
| -rw-r--r-- | src/nvim/eval/decode.c | 20 | ||||
| -rw-r--r-- | src/nvim/eval/encode.c | 67 | ||||
| -rw-r--r-- | src/nvim/eval/executor.c | 4 | ||||
| -rw-r--r-- | src/nvim/eval/funcs.c | 3312 | ||||
| -rw-r--r-- | src/nvim/eval/funcs.h | 7 | ||||
| -rw-r--r-- | src/nvim/eval/typval.c | 135 | ||||
| -rw-r--r-- | src/nvim/eval/typval.h | 28 | ||||
| -rw-r--r-- | src/nvim/eval/typval_encode.c.h | 9 | ||||
| -rw-r--r-- | src/nvim/eval/typval_encode.h | 4 | ||||
| -rw-r--r-- | src/nvim/eval/userfunc.c | 456 |
10 files changed, 1620 insertions, 2422 deletions
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 797420c150..7b975ce775 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -290,8 +290,7 @@ typval_T decode_string(const char *const s, const size_t len, const TriState has return (typval_T) { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval = { .v_string = (char_u *)( - (s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, + .vval = { .v_string = ((s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, }; } } @@ -376,7 +375,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, "inside string: %.*s"), LENP(p, e)); goto parse_json_string_fail; } - const int ch = utf_ptr2char((char_u *)p); + const int ch = utf_ptr2char(p); // All characters above U+007F are encoded using two or more bytes // and thus cannot possibly be equal to *p. But utf_ptr2char({0xFF, // 0}) will return 0xFF, even though 0xFF cannot start any UTF-8 @@ -393,7 +392,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, goto parse_json_string_fail; } const size_t ch_len = (size_t)utf_char2len(ch); - assert(ch_len == (size_t)(ch ? utf_ptr2len((char_u *)p) : 1)); + assert(ch_len == (size_t)(ch ? utf_ptr2len(p) : 1)); len += ch_len; p += ch_len; } @@ -415,9 +414,9 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, bool hasnul = false; #define PUT_FST_IN_PAIR(fst_in_pair, str_end) \ do { \ - if (fst_in_pair != 0) { \ - str_end += utf_char2bytes(fst_in_pair, (char_u *)str_end); \ - fst_in_pair = 0; \ + if ((fst_in_pair) != 0) { \ + (str_end) += utf_char2bytes(fst_in_pair, (str_end)); \ + (fst_in_pair) = 0; \ } \ } while (0) for (const char *t = s; t < p; t++) { @@ -441,15 +440,14 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, fst_in_pair = (int)ch; } else if (SURROGATE_LO_START <= ch && ch <= SURROGATE_LO_END && fst_in_pair != 0) { - const int full_char = ( - (int)(ch - SURROGATE_LO_START) + const int full_char = ((int)(ch - SURROGATE_LO_START) + ((fst_in_pair - SURROGATE_HI_START) << 10) + SURROGATE_FIRST_CHAR); - str_end += utf_char2bytes(full_char, (char_u *)str_end); + str_end += utf_char2bytes(full_char, str_end); fst_in_pair = 0; } else { PUT_FST_IN_PAIR(fst_in_pair, str_end); - str_end += utf_char2bytes((int)ch, (char_u *)str_end); + str_end += utf_char2bytes((int)ch, str_end); } break; } diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 6f4357421b..090939666d 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -29,8 +29,6 @@ #include "nvim/message.h" #include "nvim/vim.h" // For _() -#define utf_char2len(b) ((size_t)utf_char2len(b)) - const char *const encode_bool_var_names[] = { [kBoolVarTrue] = "true", [kBoolVarFalse] = "false", @@ -69,10 +67,10 @@ int encode_list_write(void *const data, const char *const buf, const size_t len) line_end = xmemscan(buf, NL, len); if (line_end != buf) { const size_t line_length = (size_t)(line_end - buf); - char *str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string; + char *str = TV_LIST_ITEM_TV(li)->vval.v_string; const size_t li_len = (str == NULL ? 0 : strlen(str)); TV_LIST_ITEM_TV(li)->vval.v_string = xrealloc(str, li_len + line_length + 1); - str = (char *)TV_LIST_ITEM_TV(li)->vval.v_string + li_len; + str = TV_LIST_ITEM_TV(li)->vval.v_string + li_len; memcpy(str, buf, line_length); str[line_length] = 0; memchrsub(str, NUL, NL, line_length); @@ -132,9 +130,10 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, case kMPConvDict: { typval_T key_tv = { .v_type = VAR_STRING, - .vval = { .v_string = (v.data.d.hi == NULL - ? v.data.d.dict->dv_hashtab.ht_array - : (v.data.d.hi - 1))->hi_key }, + .vval = { .v_string = + (char *)(v.data.d.hi == + NULL ? v.data.d.dict->dv_hashtab.ht_array : (v.data.d.hi - + 1))->hi_key }, }; char *const key = encode_tv2string(&key_tv, NULL); vim_snprintf((char *)IObuff, IOSIZE, key_msg, key); @@ -265,7 +264,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s || TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL); for (size_t i = state->offset; i < state->li_length && p < buf_end; i++) { assert(TV_LIST_ITEM_TV(state->li)->vval.v_string != NULL); - const char ch = (char)(TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]); + const char ch = TV_LIST_ITEM_TV(state->li)->vval.v_string[state->offset++]; *p++ = (char)(ch == (char)NL ? (char)NUL : ch); } if (p < buf_end) { @@ -294,8 +293,8 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ - const char *const buf_ = (const char *)buf; \ - if (buf == NULL) { \ + const char *const buf_ = (const char *)(buf); \ + if ((buf) == NULL) { \ ga_concat(gap, "''"); \ } else { \ const size_t len_ = (len); \ @@ -384,14 +383,14 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, len) \ do { \ - if (len != 0) { \ + if ((len) != 0) { \ ga_concat(gap, ", "); \ } \ } while (0) #define TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, len) \ do { \ - if ((ptrdiff_t)len != -1) { \ + if ((ptrdiff_t)(len) != -1) { \ ga_concat(gap, ", "); \ } \ } while (0) @@ -453,12 +452,12 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s size_t backref = 0; \ for (; backref < kv_size(*mpstack); backref++) { \ const MPConvStackVal mpval = kv_A(*mpstack, backref); \ - if (mpval.type == conv_type) { \ - if (conv_type == kMPConvDict) { \ + if (mpval.type == (conv_type)) { \ + if ((conv_type) == kMPConvDict) { \ if ((void *)mpval.data.d.dict == (void *)(val)) { \ break; \ } \ - } else if (conv_type == kMPConvList) { \ + } else if ((conv_type) == kMPConvList) { \ if ((void *)mpval.data.l.list == (void *)(val)) { \ break; \ } \ @@ -488,19 +487,19 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s size_t backref = 0; \ for (; backref < kv_size(*mpstack); backref++) { \ const MPConvStackVal mpval = kv_A(*mpstack, backref); \ - if (mpval.type == conv_type) { \ - if (conv_type == kMPConvDict) { \ - if ((void *)mpval.data.d.dict == (void *)val) { \ + if (mpval.type == (conv_type)) { \ + if ((conv_type) == kMPConvDict) { \ + if ((void *)mpval.data.d.dict == (void *)(val)) { \ break; \ } \ - } else if (conv_type == kMPConvList) { \ - if ((void *)mpval.data.l.list == (void *)val) { \ + } else if ((conv_type) == kMPConvList) { \ + if ((void *)mpval.data.l.list == (void *)(val)) { \ break; \ } \ } \ } \ } \ - if (conv_type == kMPConvDict) { \ + if ((conv_type) == kMPConvDict) { \ vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "{...@%zu}", backref); \ } else { \ vim_snprintf(ebuf, ARRAY_SIZE(ebuf), "[...@%zu]", backref); \ @@ -610,10 +609,10 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const // This is done to make resulting values displayable on screen also not from // Neovim. #define ENCODE_RAW(ch) \ - (ch >= 0x20 && utf_printable(ch)) + ((ch) >= 0x20 && utf_printable(ch)) for (size_t i = 0; i < utf_len;) { - const int ch = utf_ptr2char((char_u *)utf_buf + i); - const size_t shift = (ch == 0 ? 1 : ((size_t)utf_ptr2len((char_u *)utf_buf + i))); + const int ch = utf_ptr2char(utf_buf + i); + const size_t shift = (ch == 0 ? 1 : ((size_t)utf_ptr2len(utf_buf + i))); assert(shift > 0); i += shift; switch (ch) { @@ -652,11 +651,11 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const ga_append(gap, '"'); ga_grow(gap, (int)str_len); for (size_t i = 0; i < utf_len;) { - const int ch = utf_ptr2char((char_u *)utf_buf + i); - const size_t shift = (ch == 0? 1: utf_char2len(ch)); + const int ch = utf_ptr2char(utf_buf + i); + const size_t shift = (ch == 0 ? 1 : ((size_t)utf_char2len(ch))); assert(shift > 0); // Is false on invalid unicode, but this should already be handled. - assert(ch == 0 || shift == ((size_t)utf_ptr2len((char_u *)utf_buf + i))); + assert(ch == 0 || shift == ((size_t)utf_ptr2len(utf_buf + i))); switch (ch) { case BS: case TAB: @@ -789,7 +788,7 @@ bool encode_check_json_key(const typval_T *const tv) #undef TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK #define TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(label, key) \ do { \ - if (!encode_check_json_key(&key)) { \ + if (!encode_check_json_key(&(key))) { \ emsg(_("E474: Invalid key in special dictionary")); \ goto label; \ } \ @@ -871,7 +870,7 @@ char *encode_tv2echo(typval_T *tv, size_t *len) ga_init(&ga, (int)sizeof(char), 80); if (tv->v_type == VAR_STRING || tv->v_type == VAR_FUNC) { if (tv->vval.v_string != NULL) { - ga_concat(&ga, (char *)tv->vval.v_string); + ga_concat(&ga, tv->vval.v_string); } } else { const int eve_ret = encode_vim_to_echo(&ga, tv, N_(":echo argument")); @@ -912,7 +911,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ - if (buf == NULL) { \ + if ((buf) == NULL) { \ msgpack_pack_bin(packer, 0); \ } else { \ const size_t len_ = (len); \ @@ -923,7 +922,7 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) \ do { \ - if (buf == NULL) { \ + if ((buf) == NULL) { \ msgpack_pack_str(packer, 0); \ } else { \ const size_t len_ = (len); \ @@ -934,11 +933,11 @@ char *encode_tv2json(typval_T *tv, size_t *len) #define TYPVAL_ENCODE_CONV_EXT_STRING(tv, buf, len, type) \ do { \ - if (buf == NULL) { \ - msgpack_pack_ext(packer, 0, (int8_t)type); \ + if ((buf) == NULL) { \ + msgpack_pack_ext(packer, 0, (int8_t)(type)); \ } else { \ const size_t len_ = (len); \ - msgpack_pack_ext(packer, len_, (int8_t)type); \ + msgpack_pack_ext(packer, len_, (int8_t)(type)); \ msgpack_pack_ext_body(packer, buf, len_); \ } \ } while (0) diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index ed4f36f4c7..3e66150180 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -63,7 +63,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons if (tv2->v_type == VAR_LIST) { break; } - if (vim_strchr((char_u *)"+-*/%", *op) != NULL) { + if (vim_strchr("+-*/%", *op) != NULL) { // nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr varnumber_T n = tv_get_number(tv1); if (tv2->v_type == VAR_FLOAT) { @@ -114,7 +114,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons numbuf)); tv_clear(tv1); tv1->v_type = VAR_STRING; - tv1->vval.v_string = (char_u *)s; + tv1->vval.v_string = s; } return OK; case VAR_FLOAT: { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 875655d0b3..7bed21e99b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -16,27 +16,31 @@ #include "nvim/context.h" #include "nvim/cursor.h" #include "nvim/diff.h" +#include "nvim/digraph.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" #include "nvim/eval/executor.h" #include "nvim/eval/funcs.h" +#include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" -#include "nvim/ex_cmds2.h" #include "nvim/ex_docmd.h" #include "nvim/ex_getln.h" #include "nvim/file_search.h" #include "nvim/fileio.h" #include "nvim/fold.h" #include "nvim/globals.h" +#include "nvim/highlight_group.h" #include "nvim/if_cscope.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/input.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" +#include "nvim/mapping.h" #include "nvim/mark.h" +#include "nvim/match.h" #include "nvim/math.h" #include "nvim/memline.h" #include "nvim/mouse.h" @@ -61,11 +65,12 @@ #include "nvim/state.h" #include "nvim/syntax.h" #include "nvim/tag.h" +#include "nvim/testing.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/vim.h" - +#include "nvim/window.h" /// Describe data to return from find_some_match() typedef enum { @@ -76,9 +81,6 @@ typedef enum { kSomeMatchStrPos, ///< Data for matchstrpos(). } SomeMatchType; -KHASH_MAP_INIT_STR(functions, VimLFuncDef) - - #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/funcs.c.generated.h" @@ -96,10 +98,9 @@ PRAGMA_DIAG_POP PRAGMA_DIAG_POP #endif - -static char *e_listarg = N_("E686: Argument of %s must be a List"); static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static char *e_invalwindow = N_("E957: Invalid window number"); +static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); /// Dummy va_list for passing to vim_snprintf /// @@ -109,10 +110,9 @@ static char *e_invalwindow = N_("E957: Invalid window number"); /// - using va_start() to initialize it gives "function with fixed args" error static va_list dummy_ap; - /// Function given to ExpandGeneric() to obtain the list of internal /// or user defined function names. -char_u *get_function_name(expand_T *xp, int idx) +char *get_function_name(expand_T *xp, int idx) { static int intidx = -1; char_u *name; @@ -121,24 +121,20 @@ char_u *get_function_name(expand_T *xp, int idx) intidx = -1; } if (intidx < 0) { - name = get_user_func_name(xp, idx); + name = (char_u *)get_user_func_name(xp, idx); if (name != NULL) { if (*name != NUL && *name != '<' && STRNCMP("g:", xp->xp_pattern, 2) == 0) { - return cat_prefix_varname('g', name); + return cat_prefix_varname('g', (char *)name); } - return name; + return (char *)name; } } - while ((size_t)++intidx < ARRAY_SIZE(functions) - && functions[intidx].name[0] == '\0') { - } - if ((size_t)intidx >= ARRAY_SIZE(functions)) { + const char *const key = functions[++intidx].name; + if (!key) { return NULL; } - - const char *const key = functions[intidx].name; const size_t key_len = strlen(key); memcpy(IObuff, key, key_len); IObuff[key_len] = '('; @@ -148,12 +144,12 @@ char_u *get_function_name(expand_T *xp, int idx) } else { IObuff[key_len + 1] = NUL; } - return IObuff; + return (char *)IObuff; } /// Function given to ExpandGeneric() to obtain the list of internal or /// user defined variable or function names. -char_u *get_expr_name(expand_T *xp, int idx) +char *get_expr_name(expand_T *xp, int idx) { static int intidx = -1; char_u *name; @@ -162,9 +158,9 @@ char_u *get_expr_name(expand_T *xp, int idx) intidx = -1; } if (intidx < 0) { - name = get_function_name(xp, idx); + name = (char_u *)get_function_name(xp, idx); if (name != NULL) { - return name; + return (char *)name; } } return get_user_var_name(xp, ++intidx); @@ -174,19 +170,20 @@ char_u *get_expr_name(expand_T *xp, int idx) /// /// @param[in] name Name of the function. /// -/// Returns pointer to the function definition or NULL if not found. -const VimLFuncDef *find_internal_func(const char *const name) +/// @return pointer to the function definition or NULL if not found. +const EvalFuncDef *find_internal_func(const char *const name) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL { size_t len = strlen(name); - return find_internal_func_gperf(name, len); + int index = find_internal_func_hash(name, len); + return index >= 0 ? &functions[index] : NULL; } int call_internal_func(const char_u *const fname, const int argcount, typval_T *const argvars, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL { - const VimLFuncDef *const fdef = find_internal_func((const char *)fname); + const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { return ERROR_UNKNOWN; } else if (argcount < fdef->min_argc) { @@ -204,7 +201,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T typval_T *const rettv, typval_T *const basetv) FUNC_ATTR_NONNULL_ALL { - const VimLFuncDef *const fdef = find_internal_func((const char *)fname); + const EvalFuncDef *const fdef = find_internal_func((const char *)fname); if (fdef == NULL) { return ERROR_UNKNOWN; } else if (fdef->base_arg == BASE_NONE) { @@ -228,9 +225,7 @@ int call_internal_method(const char_u *const fname, const int argcount, typval_T return ERROR_NONE; } -/* - * Return TRUE for a non-zero Number and a non-empty String. - */ +/// @return TRUE for a non-zero Number and a non-empty String. static int non_zero_arg(typval_T *argvars) { return ((argvars[0].v_type == VAR_NUMBER @@ -242,11 +237,11 @@ static int non_zero_arg(typval_T *argvars) && *argvars[0].vval.v_string != NUL)); } -// Apply a floating point C function on a typval with one float_T. -// -// Some versions of glibc on i386 have an optimization that makes it harder to -// call math functions indirectly from inside an inlined function, causing -// compile-time errors. Avoid `inline` in that case. #3072 +/// Apply a floating point C function on a typval with one float_T. +/// +/// Some versions of glibc on i386 have an optimization that makes it harder to +/// call math functions indirectly from inside an inlined function, causing +/// compile-time errors. Avoid `inline` in that case. #3072 static void float_op_wrapper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; @@ -292,9 +287,7 @@ end: api_clear_error(&err); } -/* - * "abs(expr)" function - */ +/// "abs(expr)" function static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type == VAR_FLOAT) { @@ -314,9 +307,7 @@ static void f_abs(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "add(list, item)" function - */ +/// "add(list, item)" function static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 1; // Default: failed. @@ -344,16 +335,13 @@ static void f_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "and(expr, expr)" function - */ +/// "and(expr, expr)" function static void f_and(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) & tv_get_number_chk(&argvars[1], NULL); } - /// "api_info()" function static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -362,7 +350,7 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) api_free_dictionary(metadata); } -// "append(lnum, string/list)" function +/// "append(lnum, string/list)" function static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const linenr_T lnum = tv_get_lnum(&argvars[0]); @@ -370,7 +358,7 @@ static void f_append(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); } -// "appendbufline(buf, lnum, string/list)" function +/// "appendbufline(buf, lnum, string/list)" function static void f_appendbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *const buf = tv_get_buf(&argvars[0], false); @@ -402,9 +390,7 @@ static void f_argc(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "argidx()" function - */ +/// "argidx()" function static void f_argidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = curwin->w_arg_idx; @@ -420,9 +406,7 @@ static void f_arglistid(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "argv(nr)" function - */ +/// "argv(nr)" function static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { aentry_T *arglist = NULL; @@ -448,7 +432,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = NULL; int idx = tv_get_number_chk(&argvars[0], NULL); if (arglist != NULL && idx >= 0 && idx < argcount) { - rettv->vval.v_string = (char_u *)xstrdup((const char *)alist_name(&arglist[idx])); + rettv->vval.v_string = xstrdup((const char *)alist_name(&arglist[idx])); } else if (idx == -1) { get_arglist_as_rettv(arglist, argcount, rettv); } @@ -457,93 +441,7 @@ static void f_argv(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "assert_beeps(cmd [, error])" function -static void f_assert_beeps(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_beeps(argvars, false); -} - -// "assert_nobeep(cmd [, error])" function -static void f_assert_nobeep(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_beeps(argvars, true); -} - -// "assert_equal(expected, actual[, msg])" function -static void f_assert_equal(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_equal_common(argvars, ASSERT_EQUAL); -} - -// "assert_equalfile(fname-one, fname-two[, msg])" function -static void f_assert_equalfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_equalfile(argvars); -} - -// "assert_notequal(expected, actual[, msg])" function -static void f_assert_notequal(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_equal_common(argvars, ASSERT_NOTEQUAL); -} - -/// "assert_report(msg) -static void f_assert_report(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - garray_T ga; - - prepare_assert_error(&ga); - ga_concat(&ga, tv_get_string(&argvars[0])); - assert_error(&ga); - ga_clear(&ga); - rettv->vval.v_number = 1; -} - -/// "assert_exception(string[, msg])" function -static void f_assert_exception(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_exception(argvars); -} - -/// "assert_fails(cmd [, error [, msg]])" function -static void f_assert_fails(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_fails(argvars); -} - -// "assert_false(actual[, msg])" function -static void f_assert_false(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_bool(argvars, false); -} - -/// "assert_inrange(lower, upper[, msg])" function -static void f_assert_inrange(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_inrange(argvars); -} - -/// "assert_match(pattern, actual[, msg])" function -static void f_assert_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_match_common(argvars, ASSERT_MATCH); -} - -/// "assert_notmatch(pattern, actual[, msg])" function -static void f_assert_notmatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_match_common(argvars, ASSERT_NOTMATCH); -} - -// "assert_true(actual[, msg])" function -static void f_assert_true(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = assert_bool(argvars, true); -} - -/* - * "atan2()" function - */ +/// "atan2()" function static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx; @@ -557,27 +455,20 @@ static void f_atan2(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "browse(save, title, initdir, default)" function - */ +/// "browse(save, title, initdir, default)" function static void f_browse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; } -/* - * "browsedir(title, initdir)" function - */ +/// "browsedir(title, initdir)" function static void f_browsedir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { f_browse(argvars, rettv, NULL); } - -/* - * Find a buffer by number or exact name. - */ +/// Find a buffer by number or exact name. static buf_T *find_buffer(typval_T *avar) { buf_T *buf = NULL; @@ -591,9 +482,7 @@ static buf_T *find_buffer(typval_T *avar) * buffer, these don't use the full path. */ FOR_ALL_BUFFERS(bp) { if (bp->b_fname != NULL - && (path_with_url((char *)bp->b_fname) - || bt_nofile(bp) - ) + && (path_with_url(bp->b_fname) || bt_nofilename(bp)) && STRCMP(bp->b_fname, avar->vval.v_string) == 0) { buf = bp; break; @@ -604,25 +493,21 @@ static buf_T *find_buffer(typval_T *avar) return buf; } -// "bufadd(expr)" function +/// "bufadd(expr)" function static void f_bufadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *name = (char_u *)tv_get_string(&argvars[0]); - rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0); + rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0); } -/* - * "bufexists(expr)" function - */ +/// "bufexists(expr)" function static void f_bufexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); } -/* - * "buflisted(expr)" function - */ +/// "buflisted(expr)" function static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -631,7 +516,7 @@ static void f_buflisted(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (buf != NULL && buf->b_p_bl); } -// "bufload(expr)" function +/// "bufload(expr)" function static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr) { buf_T *buf = get_buf_arg(&argvars[0]); @@ -646,9 +531,7 @@ static void f_bufload(typval_T *argvars, typval_T *unused, FunPtr fptr) } } -/* - * "bufloaded(expr)" function - */ +/// "bufloaded(expr)" function static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -657,9 +540,7 @@ static void f_bufloaded(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); } -/* - * "bufname(expr)" function - */ +/// "bufname(expr)" function static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const buf_T *buf; @@ -671,13 +552,11 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr) buf = tv_get_buf_from_arg(&argvars[0]); } if (buf != NULL && buf->b_fname != NULL) { - rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname); + rettv->vval.v_string = xstrdup(buf->b_fname); } } -/* - * "bufnr(expr)" function - */ +/// "bufnr(expr)" function static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const buf_T *buf; @@ -707,7 +586,7 @@ static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) && tv_get_number_chk(&argvars[1], &error) != 0 && !error && (name = tv_get_string_chk(&argvars[0])) != NULL) { - buf = buflist_new((char_u *)name, NULL, 1, 0); + buf = buflist_new((char *)name, NULL, 1, 0); } if (buf != NULL) { @@ -749,14 +628,12 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) buf_win_common(argvars, rettv, true); } -/* - * Get buffer by number or pattern. - */ +/// Get buffer by number or pattern. buf_T *tv_get_buf(typval_T *tv, int curtab_only) { - char_u *name = tv->vval.v_string; + char_u *name = (char_u *)tv->vval.v_string; int save_magic; - char_u *save_cpo; + char *save_cpo; buf_T *buf; if (tv->v_type == VAR_NUMBER) { @@ -776,9 +653,9 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) save_magic = p_magic; p_magic = TRUE; save_cpo = p_cpo; - p_cpo = (char_u *)""; + p_cpo = ""; - buf = buflist_findnr(buflist_findpat(name, name + STRLEN(name), + buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name), true, false, curtab_only)); p_magic = save_magic; @@ -819,9 +696,7 @@ buf_T *get_buf_arg(typval_T *arg) return buf; } -/* - * "byte2line(byte)" function - */ +/// "byte2line(byte)" function static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long boff = tv_get_number(&argvars[0]) - 1; @@ -848,25 +723,21 @@ static void byteidx(typval_T *argvars, typval_T *rettv, int comp) return; } if (comp) { - t += utf_ptr2len((const char_u *)t); + t += utf_ptr2len(t); } else { - t += utfc_ptr2len((const char_u *)t); + t += utfc_ptr2len(t); } } rettv->vval.v_number = (varnumber_T)(t - str); } -/* - * "byteidx()" function - */ +/// "byteidx()" function static void f_byteidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { byteidx(argvars, rettv, FALSE); } -/* - * "byteidxcomp()" function - */ +/// "byteidxcomp()" function static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, FunPtr fptr) { byteidx(argvars, rettv, TRUE); @@ -888,11 +759,12 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) partial_T *partial = NULL; dict_T *selfdict = NULL; if (argvars[0].v_type == VAR_FUNC) { - func = argvars[0].vval.v_string; + func = (char_u *)argvars[0].vval.v_string; } else if (argvars[0].v_type == VAR_PARTIAL) { partial = argvars[0].vval.v_partial; - func = partial_name(partial); + func = (char_u *)partial_name(partial); } else if (nlua_is_table_from_lua(&argvars[0])) { + // TODO(tjdevries): UnifiedCallback func = nlua_register_table_as_callable(&argvars[0]); owned = true; } else { @@ -906,6 +778,9 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_DICT) { emsg(_(e_dictreq)); + if (owned) { + func_unref(func); + } return; } selfdict = argvars[2].vval.v_dict; @@ -917,15 +792,13 @@ static void f_call(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "changenr()" function - */ +/// "changenr()" function static void f_changenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = curbuf->b_u_seq_cur; } -// "chanclose(id[, stream])" function +/// "chanclose(id[, stream])" function static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -943,7 +816,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) ChannelPart part = kChannelPartAll; if (argvars[1].v_type == VAR_STRING) { - char *stream = (char *)argvars[1].vval.v_string; + char *stream = argvars[1].vval.v_string; if (!strcmp(stream, "stdin")) { part = kChannelPartStdin; } else if (!strcmp(stream, "stdout")) { @@ -964,7 +837,7 @@ static void f_chanclose(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "chansend(id, data)" function +/// "chansend(id, data)" function static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -1005,9 +878,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "char2nr(string)" function - */ +/// "char2nr(string)" function static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[1].v_type != VAR_UNKNOWN) { @@ -1016,10 +887,54 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - rettv->vval.v_number = utf_ptr2char((const char_u *)tv_get_string(&argvars[0])); + rettv->vval.v_number = utf_ptr2char(tv_get_string(&argvars[0])); } -// "charidx()" function +/// Get the current cursor column and store it in 'rettv'. +/// +/// @return the character index of the column if 'charcol' is true, +/// otherwise the byte index of the column. +static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) +{ + colnr_T col = 0; + pos_T *fp; + int fnum = curbuf->b_fnum; + + fp = var2fpos(&argvars[0], false, &fnum, charcol); + if (fp != NULL && fnum == curbuf->b_fnum) { + 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; + } else { + col = MAXCOL; + } + } else { + col = fp->col + 1; + // 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(); + if (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) { + col += l; + } + } + } + } + } + rettv->vval.v_number = col; +} + +/// "charcol()" function +static void f_charcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + get_col(argvars, rettv, true); +} + +/// "charidx()" function static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -1046,7 +961,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - int (*ptr2len)(const char_u *); + int (*ptr2len)(const char *); if (countcc) { ptr2len = utf_ptr2len; } else { @@ -1059,13 +974,13 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (*p == NUL) { return; } - p += ptr2len((const char_u *)p); + p += ptr2len(p); } rettv->vval.v_number = len > 0 ? len - 1 : 0; } -// "chdir(dir)" function +/// "chdir(dir)" function static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *cwd; @@ -1086,7 +1001,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) #ifdef BACKSLASH_IN_FILENAME slash_adjust(cwd); #endif - rettv->vval.v_string = vim_strsave(cwd); + rettv->vval.v_string = (char *)vim_strsave(cwd); } xfree(cwd); @@ -1102,9 +1017,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "cindent(lnum)" function - */ +/// "cindent(lnum)" function static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T pos; @@ -1121,7 +1034,7 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -static win_T *get_optional_window(typval_T *argvars, int idx) +win_T *get_optional_window(typval_T *argvars, int idx) { win_T *win = curwin; @@ -1135,65 +1048,16 @@ static win_T *get_optional_window(typval_T *argvars, int idx) return win; } -/* - * "clearmatches()" function - */ -static void f_clearmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - win_T *win = get_optional_window(argvars, 0); - - if (win != NULL) { - clear_matches(win); - } -} - -/* - * "col(string)" function - */ +/// "col(string)" function static void f_col(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - colnr_T col = 0; - pos_T *fp; - int fnum = curbuf->b_fnum; - - fp = var2fpos(&argvars[0], FALSE, &fnum); - if (fp != NULL && fnum == curbuf->b_fnum) { - 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; - } else { - col = MAXCOL; - } - } else { - col = fp->col + 1; - // 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(); - - if (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(p))] == NUL) { - col += l; - } - } - } - } - } - rettv->vval.v_number = col; + get_col(argvars, rettv, false); } -/* - * "complete()" function - */ +/// "complete()" function static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if ((State & INSERT) == 0) { + if ((State & MODE_INSERT) == 0) { emsg(_("E785: complete() can only be used in Insert mode")); return; } @@ -1206,28 +1070,21 @@ static void f_complete(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[1].v_type != VAR_LIST) { emsg(_(e_invarg)); - return; - } - - const colnr_T startcol = tv_get_number_chk(&argvars[0], NULL); - if (startcol <= 0) { - return; + } else { + const colnr_T startcol = tv_get_number_chk(&argvars[0], NULL); + if (startcol > 0) { + set_completion(startcol - 1, argvars[1].vval.v_list); + } } - - set_completion(startcol - 1, argvars[1].vval.v_list); } -/* - * "complete_add()" function - */ +/// "complete_add()" function static void f_complete_add(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ins_compl_add_tv(&argvars[0], 0, false); } -/* - * "complete_check()" function - */ +/// "complete_check()" function static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int saved = RedrawingDisabled; @@ -1238,7 +1095,7 @@ static void f_complete_check(typval_T *argvars, typval_T *rettv, FunPtr fptr) RedrawingDisabled = saved; } -// "complete_info()" function +/// "complete_info()" function static void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_dict_alloc_ret(rettv); @@ -1255,9 +1112,7 @@ static void f_complete_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_complete_info(what_list, rettv->vval.v_dict); } -/* - * "confirm(message, buttons[, default [, type]])" function - */ +/// "confirm(message, buttons[, default [, type]])" function static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf[NUMBUFLEN]; @@ -1312,17 +1167,13 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "copy()" function - */ +/// "copy()" function static void f_copy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { var_item_copy(NULL, &argvars[0], rettv, false, 0); } -/* - * "count()" function - */ +/// "count()" function static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long n = 0; @@ -1335,7 +1186,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type == VAR_STRING) { const char_u *expr = (char_u *)tv_get_string_chk(&argvars[1]); - const char_u *p = argvars[0].vval.v_string; + const char_u *p = (char_u *)argvars[0].vval.v_string; if (!error && expr != NULL && *expr != NUL && p != NULL) { if (ic) { @@ -1413,11 +1264,9 @@ static void f_count(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "cscope_connection([{num} , {dbpath} [, {prepend}]])" function - * - * Checks the existence of a cscope connection. - */ +/// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function +/// +/// Checks the existence of a cscope connection. static void f_cscope_connection(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int num = 0; @@ -1548,24 +1397,21 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = ctx_size(); } -/// "cursor(lnum, col)" function, or -/// "cursor(list)" -/// -/// Moves the cursor to the specified line and column. -/// -/// @returns 0 when the position could be set, -1 otherwise. -static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) +/// Set the cursor position. +/// If 'charcol' is true, then use the column number as a character offset. +/// 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 coladd = 0; bool set_curswant = true; rettv->vval.v_number = -1; - if (argvars[1].v_type == VAR_UNKNOWN) { + if (argvars[0].v_type == VAR_LIST) { pos_T pos; colnr_T curswant = -1; - if (list2fpos(argvars, &pos, NULL, &curswant) == FAIL) { + if (list2fpos(argvars, &pos, NULL, &curswant, charcol) == FAIL) { emsg(_(e_invarg)); return; } @@ -1577,16 +1423,22 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) curwin->w_curswant = curswant - 1; set_curswant = false; } - } else { + } 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); col = (long)tv_get_number_chk(&argvars[1], NULL); + if (charcol) { + col = buf_charidx_to_byteidx(curbuf, line, col) + 1; + } if (argvars[2].v_type != VAR_UNKNOWN) { coladd = (long)tv_get_number_chk(&argvars[2], NULL); } + } else { + emsg(_(e_invarg)); + return; } - if (line < 0 || col < 0 - || coladd < 0) { - return; // type error; errmsg already given + if (line < 0 || col < 0 || coladd < 0) { + return; // type error; errmsg already given } if (line > 0) { curwin->w_cursor.lnum = line; @@ -1605,7 +1457,18 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; } -// "debugbreak()" function +/// "cursor(lnum, col)" function, or +/// "cursor(list)" +/// +/// Moves the cursor to the specified line and column. +/// +/// @return 0 when the position could be set, -1 otherwise. +static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + set_cursorpos(argvars, rettv, false); +} + +/// "debugbreak()" function static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int pid; @@ -1629,7 +1492,7 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "deepcopy()" function +/// "deepcopy()" function static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int noref = 0; @@ -1646,7 +1509,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "delete()" function +/// "delete()" function static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -1682,7 +1545,7 @@ static void f_delete(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// dictwatcheradd(dict, key, funcref) function +/// dictwatcheradd(dict, key, funcref) function static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_secure()) { @@ -1720,7 +1583,7 @@ static void f_dictwatcheradd(typval_T *argvars, typval_T *rettv, FunPtr fptr) callback); } -// dictwatcherdel(dict, key, funcref) function +/// dictwatcherdel(dict, key, funcref) function static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_secure()) { @@ -1768,6 +1631,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } const bool is_curbuf = buf == curbuf; + const bool save_VIsual_active = VIsual_active; const linenr_T first = tv_get_lnum_buf(&argvars[1], buf); if (argvars[2].v_type != VAR_UNKNOWN) { @@ -1783,6 +1647,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (!is_curbuf) { + VIsual_active = false; curbuf_save = curbuf; curwin_save = curwin; curbuf = buf; @@ -1826,28 +1691,23 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!is_curbuf) { curbuf = curbuf_save; curwin = curwin_save; + VIsual_active = save_VIsual_active; } } -/* - * "did_filetype()" function - */ +/// "did_filetype()" function static void f_did_filetype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = did_filetype; } -/* - * "diff_filler()" function - */ +/// "diff_filler()" function static void f_diff_filler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = MAX(0, diff_check(curwin, tv_get_lnum(argvars))); } -/* - * "diff_hlID()" function - */ +/// "diff_hlID()" function static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = tv_get_lnum(argvars); @@ -1899,9 +1759,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)(hlID + 1); } -/* - * "empty({expr})" function - */ +/// "empty({expr})" function static void f_empty(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool n = true; @@ -1998,15 +1856,14 @@ static void f_environ(typval_T *argvars, typval_T *rettv, FunPtr fptr) os_free_fullenv(env); } -/* - * "escape({string}, {chars})" function - */ +/// "escape({string}, {chars})" function static void f_escape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf[NUMBUFLEN]; - rettv->vval.v_string = vim_strsave_escaped((const char_u *)tv_get_string(&argvars[0]), - (const char_u *)tv_get_string_buf(&argvars[1], buf)); + rettv->vval.v_string = (char *)vim_strsave_escaped((const char_u *)tv_get_string(&argvars[0]), + (const char_u *)tv_get_string_buf(&argvars[1], + buf)); rettv->v_type = VAR_STRING; } @@ -2020,22 +1877,20 @@ static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_special = kSpecialVarNull; return; } - rettv->vval.v_string = p; + rettv->vval.v_string = (char *)p; rettv->v_type = VAR_STRING; } -/* - * "eval()" function - */ +/// "eval()" function static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *s = tv_get_string_chk(&argvars[0]); if (s != NULL) { - s = (const char *)skipwhite((const char_u *)s); + s = (const char *)skipwhite(s); } const char *const expr_start = s; - if (s == NULL || eval1((char_u **)&s, rettv, true) == FAIL) { + if (s == NULL || eval1((char **)&s, rettv, true) == FAIL) { if (expr_start != NULL && !aborting()) { semsg(_(e_invexpr2), expr_start); } @@ -2047,17 +1902,13 @@ static void f_eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "eventhandler()" function - */ +/// "eventhandler()" function static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = vgetc_busy; } -/* - * "executable()" function - */ +/// "executable()" function static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (tv_check_for_string(&argvars[0]) == FAIL) { @@ -2073,7 +1924,7 @@ typedef struct { const listitem_T *li; } GetListLineCookie; -static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat) +static char *get_list_line(int c, void *cookie, int indent, bool do_concat) { GetListLineCookie *const p = (GetListLineCookie *)cookie; @@ -2084,7 +1935,7 @@ static char_u *get_list_line(int c, void *cookie, int indent, bool do_concat) char buf[NUMBUFLEN]; const char *const s = tv_get_string_buf_chk(TV_LIST_ITEM_TV(item), buf); p->li = TV_LIST_ITEM_NEXT(p->l, item); - return (char_u *)(s == NULL ? NULL : xstrdup(s)); + return s == NULL ? NULL : xstrdup(s); } static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int arg_off) @@ -2165,36 +2016,24 @@ static void execute_common(typval_T *argvars, typval_T *rettv, FunPtr fptr, int capture_ga = save_capture_ga; } -// "execute(command)" function +/// "execute(command)" function static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { execute_common(argvars, rettv, fptr, 0); } -// "win_execute(win_id, command)" function +/// "win_execute(win_id, command)" function static void f_win_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - tabpage_T *tp; - win_T *wp = win_id2wp_tp(argvars, &tp); - win_T *save_curwin; - tabpage_T *save_curtab; // Return an empty string if something fails. rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; + int id = tv_get_number(argvars); + tabpage_T *tp; + win_T *wp = win_id2wp_tp(id, &tp); if (wp != NULL && tp != NULL) { - pos_T curpos = wp->w_cursor; - if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) == - OK) { - check_cursor(); - execute_common(argvars, rettv, fptr, 1); - } - restore_win_noblock(save_curwin, save_curtab, true); - - // Update the status line if the cursor moved. - if (win_valid(wp) && !equalpos(curpos, wp->w_cursor)) { - wp->w_redr_status = true; - } + WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, fptr, 1)); } } @@ -2209,13 +2048,17 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr) (void)os_can_exe(tv_get_string(&argvars[0]), &path, true); +#ifdef BACKSLASH_IN_FILENAME + if (path != NULL) { + slash_adjust((char_u *)path); + } +#endif + rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)path; + rettv->vval.v_string = path; } -/* - * "exists()" function - */ +/// "exists()" function static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n = false; @@ -2227,7 +2070,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = true; } else { // Try expanding things like $VIM and ${HOME}. - char_u *const exp = expand_env_save((char_u *)p); + char *const exp = expand_env_save((char *)p); if (exp != NULL && *exp != '$') { n = true; } @@ -2235,7 +2078,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } else if (*p == '&' || *p == '+') { // Option. n = (get_option_tv(&p, NULL, true) == OK); - if (*skipwhite((const char_u *)p) != NUL) { + if (*skipwhite(p) != NUL) { n = false; // Trailing garbage. } } else if (*p == '*') { // Internal or user defined function. @@ -2255,9 +2098,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "expand()" function - */ +/// "expand()" function static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) { size_t len; @@ -2293,7 +2134,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) } XFREE_CLEAR(result); } else { - rettv->vval.v_string = result; + rettv->vval.v_string = (char *)result; } } else { // When the optional second argument is non-zero, don't remove matches @@ -2309,8 +2150,8 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) options += WILD_ICASE; } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = ExpandOne(&xpc, (char_u *)s, NULL, options, - WILD_ALL); + rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *)s, NULL, options, + WILD_ALL); } else { ExpandOne(&xpc, (char_u *)s, NULL, options, WILD_ALL_KEEP); tv_list_alloc_ret(rettv, xpc.xp_numfiles); @@ -2329,7 +2170,6 @@ static void f_expand(typval_T *argvars, typval_T *rettv, FunPtr fptr) #endif } - /// "menu_get(path [, modes])" function static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -2339,11 +2179,11 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *const strmodes = tv_get_string(&argvars[1]); modes = get_menu_cmd_modes(strmodes, false, NULL, NULL); } - menu_get((char_u *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list); + menu_get((char *)tv_get_string(&argvars[0]), modes, rettv->vval.v_list); } -// "expandcmd()" function -// Expand all the special characters in a command string. +/// "expandcmd()" function +/// Expand all the special characters in a command string. static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *errormsg = NULL; @@ -2352,8 +2192,8 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) char_u *cmdstr = (char_u *)xstrdup(tv_get_string(&argvars[0])); exarg_T eap = { - .cmd = cmdstr, - .arg = cmdstr, + .cmd = (char *)cmdstr, + .arg = (char *)cmdstr, .usefilter = false, .nextcmd = NULL, .cmdidx = CMD_USER, @@ -2364,10 +2204,9 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (errormsg != NULL && *errormsg != NUL) { emsg(errormsg); } - rettv->vval.v_string = cmdstr; + rettv->vval.v_string = (char *)cmdstr; } - /// "flatten(list[, {maxdepth}])" function static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -2403,10 +2242,8 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "extend(list, list [, idx])" function - * "extend(dict, dict [, action])" function - */ +/// "extend(list, list [, idx])" function +/// "extend(dict, dict [, action])" function static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const arg_errmsg = N_("extend() argument"); @@ -2483,9 +2320,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "feedkeys()" function - */ +/// "feedkeys()" function static void f_feedkeys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { // This is not allowed in the sandbox. If the commands would still be @@ -2514,17 +2349,15 @@ static void f_filereadable(typval_T *argvars, typval_T *rettv, FunPtr fptr) (*p && !os_isdir((const char_u *)p) && os_file_is_readable(p)); } -/* - * Return 0 for not writable, 1 for writable file, 2 for a dir which we have - * rights to write into. - */ +/// @return 0 for not writable +/// 1 for writable file +/// 2 for a dir which we have rights to write into. static void f_filewritable(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *filename = tv_get_string(&argvars[0]); rettv->vval.v_number = os_file_is_writable(filename); } - static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { char_u *fresult = NULL; @@ -2566,7 +2399,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) fresult = find_file_in_path_option(first ? (char_u *)fname : NULL, first ? strlen(fname) : 0, 0, first, path, - find_what, curbuf->b_ffname, + find_what, (char_u *)curbuf->b_ffname, (find_what == FINDFILE_DIR ? (char_u *)"" : curbuf->b_p_sua)); @@ -2579,44 +2412,35 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = fresult; + rettv->vval.v_string = (char *)fresult; } } - -/* - * "filter()" function - */ +/// "filter()" function static void f_filter(typval_T *argvars, typval_T *rettv, FunPtr fptr) { filter_map(argvars, rettv, FALSE); } -/* - * "finddir({fname}[, {path}[, {count}]])" function - */ +/// "finddir({fname}[, {path}[, {count}]])" function static void f_finddir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { findfilendir(argvars, rettv, FINDFILE_DIR); } -/* - * "findfile({fname}[, {path}[, {count}]])" function - */ +/// "findfile({fname}[, {path}[, {count}]])" function static void f_findfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { findfilendir(argvars, rettv, FINDFILE_FILE); } -/* - * "float2nr({float})" function - */ +/// "float2nr({float})" function static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T f; if (tv_get_float_chk(argvars, &f)) { - if (f <= (float_T)-VARNUMBER_MAX + DBL_EPSILON) { + if (f <= (float_T) - VARNUMBER_MAX + DBL_EPSILON) { rettv->vval.v_number = -VARNUMBER_MAX; } else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) { rettv->vval.v_number = VARNUMBER_MAX; @@ -2626,9 +2450,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "fmod()" function - */ +/// "fmod()" function static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx; @@ -2642,18 +2464,14 @@ static void f_fmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "fnameescape({string})" function - */ +/// "fnameescape({string})" function static void f_fnameescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - rettv->vval.v_string = (char_u *)vim_strsave_fnameescape(tv_get_string(&argvars[0]), false); + rettv->vval.v_string = vim_strsave_fnameescape(tv_get_string(&argvars[0]), VSE_NONE); rettv->v_type = VAR_STRING; } -/* - * "fnamemodify({fname}, {mods})" function - */ +/// "fnamemodify({fname}, {mods})" function static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *fbuf = NULL; @@ -2667,8 +2485,8 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) len = strlen(fname); if (*mods != NUL) { size_t usedlen = 0; - (void)modify_fname((char_u *)mods, false, &usedlen, - (char_u **)&fname, &fbuf, &len); + (void)modify_fname((char *)mods, false, &usedlen, + (char **)&fname, (char **)&fbuf, &len); } } @@ -2676,15 +2494,12 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (fname == NULL) { rettv->vval.v_string = NULL; } else { - rettv->vval.v_string = (char_u *)xmemdupz(fname, len); + rettv->vval.v_string = xmemdupz(fname, len); } xfree(fbuf); } - -/* - * "foldclosed()" function - */ +/// "foldclosed()" function static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end) { const linenr_T lnum = tv_get_lnum(argvars); @@ -2703,25 +2518,19 @@ static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end) rettv->vval.v_number = -1; } -/* - * "foldclosed()" function - */ +/// "foldclosed()" function static void f_foldclosed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { foldclosed_both(argvars, rettv, FALSE); } -/* - * "foldclosedend()" function - */ +/// "foldclosedend()" function static void f_foldclosedend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { foldclosed_both(argvars, rettv, TRUE); } -/* - * "foldlevel()" function - */ +/// "foldlevel()" function static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const linenr_T lnum = tv_get_lnum(argvars); @@ -2730,9 +2539,7 @@ static void f_foldlevel(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "foldtext()" function - */ +/// "foldtext()" function static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T foldstart; @@ -2749,7 +2556,7 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) foldstart = (linenr_T)get_vim_var_nr(VV_FOLDSTART); foldend = (linenr_T)get_vim_var_nr(VV_FOLDEND); - dashes = get_vim_var_str(VV_FOLDDASHES); + dashes = (char_u *)get_vim_var_str(VV_FOLDDASHES); if (foldstart > 0 && foldend <= curbuf->b_ml.ml_line_count) { // Find first non-empty line in the fold. for (lnum = foldstart; lnum < foldend; lnum++) { @@ -2759,18 +2566,18 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // Find interesting text in this line. - s = skipwhite(ml_get(lnum)); + s = (char_u *)skipwhite((char *)ml_get(lnum)); // skip C comment-start if (s[0] == '/' && (s[1] == '*' || s[1] == '/')) { - s = skipwhite(s + 2); - if (*skipwhite(s) == NUL && lnum + 1 < foldend) { - s = skipwhite(ml_get(lnum + 1)); + s = (char_u *)skipwhite((char *)s + 2); + if (*skipwhite((char *)s) == NUL && lnum + 1 < foldend) { + s = (char_u *)skipwhite((char *)ml_get(lnum + 1)); if (*s == '*') { - s = skipwhite(s + 1); + s = (char_u *)skipwhite((char *)s + 1); } } } - unsigned long count = (unsigned long)(foldend - foldstart + 1); + unsigned long count = (unsigned long)foldend - foldstart + 1; txt = NGETTEXT("+-%s%3ld line: ", "+-%s%3ld lines: ", count); r = xmalloc(STRLEN(txt) + STRLEN(dashes) // for %s @@ -2781,13 +2588,11 @@ static void f_foldtext(typval_T *argvars, typval_T *rettv, FunPtr fptr) STRCAT(r, s); // remove 'foldmarker' and 'commentstring' foldtext_cleanup(r + len); - rettv->vval.v_string = r; + rettv->vval.v_string = (char *)r; } } -/* - * "foldtextresult(lnum)" function - */ +/// "foldtextresult(lnum)" function static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *text; @@ -2812,18 +2617,15 @@ static void f_foldtextresult(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (text == buf) { text = vim_strsave(text); } - rettv->vval.v_string = text; + rettv->vval.v_string = (char *)text; } entered = false; } -/* - * "foreground()" function - */ +/// "foreground()" function static void f_foreground(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ -} +{} static void f_funcref(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -2847,9 +2649,7 @@ static void f_garbagecollect(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "get()" function - */ +/// "get()" function static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) { listitem_T *li; @@ -2899,7 +2699,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) pt = argvars[0].vval.v_partial; } else { memset(&fref_pt, 0, sizeof(fref_pt)); - fref_pt.pt_name = argvars[0].vval.v_string; + fref_pt.pt_name = (char_u *)argvars[0].vval.v_string; pt = &fref_pt; } @@ -2910,9 +2710,9 @@ static void f_get(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); const char *const n = (const char *)partial_name(pt); assert(n != NULL); - rettv->vval.v_string = (char_u *)xstrdup(n); + rettv->vval.v_string = xstrdup(n); if (rettv->v_type == VAR_FUNC) { - func_ref(rettv->vval.v_string); + func_ref((char_u *)rettv->vval.v_string); } } else if (strcmp(what, "dict") == 0) { what_is_dict = true; @@ -3009,12 +2809,12 @@ static void f_getbufinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * Get line or list of lines from buffer "buf" into "rettv". - * Return a range (from start to end) of lines in rettv from the specified - * buffer. - * If 'retlist' is TRUE, then the lines are returned as a Vim List. - */ +/// Get line or list of lines from buffer "buf" into "rettv". +/// +/// @param retlist if TRUE, then the lines are returned as a Vim List. +/// +/// @return range (from start to end) of lines in rettv from the specified +/// buffer. static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv) { rettv->v_type = (retlist ? VAR_LIST : VAR_STRING); @@ -3041,15 +2841,13 @@ 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 = ((start >= 1 && start <= buf->b_ml.ml_line_count) - ? vim_strsave(ml_get_buf(buf, start, false)) - : NULL); + rettv->vval.v_string = + (char *)((start >= 1 && start <= buf->b_ml.ml_line_count) + ? vim_strsave(ml_get_buf(buf, start, false)) : NULL); } } -/* - * "getbufline()" function - */ +/// "getbufline()" function static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); @@ -3062,9 +2860,7 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_buffer_lines(buf, lnum, end, true, rettv); } -/* - * "getbufvar()" function - */ +/// "getbufvar()" function static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool done = false; @@ -3124,7 +2920,7 @@ f_getbufvar_end: } } -// "getchangelist()" function +/// "getchangelist()" function static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_alloc_ret(rettv, 2); @@ -3164,7 +2960,7 @@ static void f_getchangelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "getchar()" and "getcharstr()" functions +/// "getchar()" and "getcharstr()" functions static void getchar_common(typval_T *argvars, typval_T *rettv) FUNC_ATTR_NONNULL_ALL { @@ -3172,6 +2968,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) bool error = false; no_mapping++; + allow_keys++; for (;;) { // Position the cursor. Needed after a message that ends in a space, // or if event processing caused a redraw. @@ -3180,7 +2977,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) if (argvars[0].v_type == VAR_UNKNOWN) { // getchar(): blocking wait. // TODO(bfredl): deduplicate shared logic with state_enter ? - if (!(char_avail() || using_script() || input_available())) { + if (!char_avail()) { (void)os_inchar(NULL, 0, -1, 0, main_loop.events); if (!multiqueue_empty(main_loop.events)) { state_handle_k_event(); @@ -3209,6 +3006,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) break; } no_mapping--; + allow_keys--; set_vim_var_nr(VV_MOUSE_WIN, 0); set_vim_var_nr(VV_MOUSE_WINID, 0); @@ -3216,7 +3014,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) set_vim_var_nr(VV_MOUSE_COL, 0); rettv->vval.v_number = n; - if (IS_SPECIAL(n) || mod_mask != 0) { + if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) { char_u temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1 int i = 0; @@ -3231,12 +3029,12 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) temp[i++] = K_SECOND(n); temp[i++] = K_THIRD(n); } else { - i += utf_char2bytes(n, temp + i); + i += utf_char2bytes(n, (char *)temp + i); } assert(i < 10); temp[i++] = NUL; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(temp); + rettv->vval.v_string = (char *)vim_strsave(temp); if (is_mouse_key(n)) { int row = mouse_row; @@ -3266,43 +3064,100 @@ static void getchar_common(typval_T *argvars, typval_T *rettv) } } -// "getchar()" function +/// "getchar()" function static void f_getchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getchar_common(argvars, rettv); } -// "getcharstr()" function +/// "getcharstr()" function static void f_getcharstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getchar_common(argvars, rettv); if (rettv->v_type == VAR_NUMBER) { - char_u temp[7]; // mbyte-char: 6, NUL: 1 + char temp[7]; // mbyte-char: 6, NUL: 1 const varnumber_T n = rettv->vval.v_number; int i = 0; if (n != 0) { - i += utf_char2bytes(n, temp); + i += utf_char2bytes(n, (char *)temp); } assert(i < 7); temp[i++] = NUL; rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave(temp); + rettv->vval.v_string = xstrdup(temp); } } -/* - * "getcharmod()" function - */ +/// "getcharmod()" function static void f_getcharmod(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = mod_mask; } -/* - * "getcharsearch()" function - */ +static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos, bool charcol) +{ + pos_T *fp = NULL; + pos_T pos; + win_T *wp = curwin; + int fnum = -1; + + if (getcurpos) { + if (argvars[0].v_type != VAR_UNKNOWN) { + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp != NULL) { + fp = &wp->w_cursor; + } + } else { + fp = &curwin->w_cursor; + } + if (fp != NULL && charcol) { + pos = *fp; + pos.col = buf_byteidx_to_charidx(wp->w_buffer, pos.lnum, pos.col); + fp = &pos; + } + } else { + fp = var2fpos(&argvars[0], true, &fnum, charcol); + } + + list_T *const l = tv_list_alloc_ret(rettv, 4 + getcurpos); + tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); + tv_list_append_number(l, ((fp != NULL) ? (varnumber_T)fp->lnum : (varnumber_T)0)); + tv_list_append_number(l, ((fp != NULL) + ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) + : (varnumber_T)0)); + tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); + if (getcurpos) { + const int save_set_curswant = curwin->w_set_curswant; + const colnr_T save_curswant = curwin->w_curswant; + const colnr_T save_virtcol = curwin->w_virtcol; + + if (wp == curwin) { + update_curswant(); + } + tv_list_append_number(l, (wp == NULL) ? 0 : ((wp->w_curswant == MAXCOL) + ? (varnumber_T)MAXCOL + : (varnumber_T)wp->w_curswant + 1)); + + // Do not change "curswant", as it is unexpected that a get + // function has a side effect. + if (wp == curwin && save_set_curswant) { + curwin->w_set_curswant = save_set_curswant; + curwin->w_curswant = save_curswant; + curwin->w_virtcol = save_virtcol; + curwin->w_valid &= ~VALID_VIRTCOL; + } + } +} + +/// "getcharpos()" function +static void f_getcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + getpos_both(argvars, rettv, false, true); +} + +/// "getcharsearch()" function static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_dict_alloc_ret(rettv); @@ -3314,26 +3169,33 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until()); } -/* - * "getcmdline()" function - */ +/// "getcmdcompltype()" function +static void f_getcmdcompltype(typval_T *argvars, typval_T *rettv, FunPtr 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, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = get_cmdline_str(); + rettv->vval.v_string = (char *)get_cmdline_str(); } -/* - * "getcmdpos()" function - */ +/// "getcmdpos()" function static void f_getcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = get_cmdline_pos() + 1; } -/* - * "getcmdtype()" function - */ +/// "getcmdscreenpos()" function +static void f_getcmdscreenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + rettv->vval.v_number = get_cmdline_screen_pos() + 1; +} + +/// "getcmdtype()" function static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; @@ -3341,9 +3203,7 @@ static void f_getcmdtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string[0] = get_cmdline_type(); } -/* - * "getcmdwintype()" function - */ +/// "getcmdwintype()" function static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; @@ -3352,7 +3212,7 @@ static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string[0] = cmdwin_type; } -// "getcompletion()" function +/// "getcompletion()" function static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *pat; @@ -3394,7 +3254,7 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) } ExpandInit(&xpc); - xpc.xp_pattern = (char_u *)pattern; + xpc.xp_pattern = (char *)pattern; xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); xpc.xp_context = cmdcomplete_str_to_type(type); if (xpc.xp_context == EXPAND_NOTHING) { @@ -3413,12 +3273,12 @@ static void f_getcompletion(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (xpc.xp_context == EXPAND_SIGN) { - set_context_in_sign_cmd(&xpc, xpc.xp_pattern); + set_context_in_sign_cmd(&xpc, (char_u *)xpc.xp_pattern); xpc.xp_pattern_len = STRLEN(xpc.xp_pattern); } theend: - pat = addstar(xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); + pat = addstar((char_u *)xpc.xp_pattern, xpc.xp_pattern_len, xpc.xp_context); ExpandOne(&xpc, pat, NULL, options, WILD_ALL_KEEP); tv_list_alloc_ret(rettv, xpc.xp_numfiles); @@ -3451,8 +3311,8 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) [kCdScopeTabpage] = 0, // Number of tab to look at. }; - char_u *cwd = NULL; // Current working directory to print - char_u *from = NULL; // The original string to copy + char *cwd = NULL; // Current working directory to print + char *from = NULL; // The original string to copy tabpage_T *tp = curtab; // The tabpage to look at. win_T *win = curwin; // The window to look at. @@ -3534,8 +3394,8 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } FALLTHROUGH; // In global directory, just need to get OS CWD. case kCdScopeInvalid: // If called without any arguments, get OS CWD. - if (os_dirname(cwd, MAXPATHL) == FAIL) { - from = (char_u *)""; // Return empty string on failure. + if (os_dirname((char_u *)cwd, MAXPATHL) == FAIL) { + from = ""; // Return empty string on failure. } } @@ -3543,7 +3403,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) STRLCPY(cwd, from, MAXPATHL); } - rettv->vval.v_string = vim_strsave(cwd); + rettv->vval.v_string = xstrdup(cwd); #ifdef BACKSLASH_IN_FILENAME slash_adjust(rettv->vval.v_string); #endif @@ -3551,18 +3411,14 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(cwd); } -/* - * "getfontname()" function - */ +/// "getfontname()" function static void f_getfontname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; } -/* - * "getfperm({fname})" function - */ +/// "getfperm({fname})" function static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *perm = NULL; @@ -3579,12 +3435,10 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)perm; + rettv->vval.v_string = perm; } -/* - * "getfsize({fname})" function - */ +/// "getfsize({fname})" function static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *fname = tv_get_string(&argvars[0]); @@ -3609,9 +3463,7 @@ static void f_getfsize(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "getftime({fname})" function - */ +/// "getftime({fname})" function static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *fname = tv_get_string(&argvars[0]); @@ -3624,9 +3476,7 @@ static void f_getftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "getftype({fname})" function - */ +/// "getftype({fname})" function static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u *type = NULL; @@ -3657,10 +3507,10 @@ static void f_getftype(typval_T *argvars, typval_T *rettv, FunPtr fptr) } type = vim_strsave((char_u *)t); } - rettv->vval.v_string = type; + rettv->vval.v_string = (char *)type; } -// "getjumplist()" function +/// "getjumplist()" function static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_alloc_ret(rettv, kListLenMayKnow); @@ -3686,14 +3536,12 @@ static void f_getjumplist(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_nr(d, S_LEN("coladd"), wp->w_jumplist[i].fmark.mark.coladd); tv_dict_add_nr(d, S_LEN("bufnr"), wp->w_jumplist[i].fmark.fnum); if (wp->w_jumplist[i].fname != NULL) { - tv_dict_add_str(d, S_LEN("filename"), (char *)wp->w_jumplist[i].fname); + tv_dict_add_str(d, S_LEN("filename"), wp->w_jumplist[i].fname); } } } -/* - * "getline(lnum, [end])" function - */ +/// "getline(lnum, [end])" function static void f_getline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T end; @@ -3718,7 +3566,6 @@ static void f_getloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_qf_loc_list(false, wp, &argvars[1], rettv); } - /// "getmarklist()" function static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -3737,65 +3584,8 @@ static void f_getmarklist(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_buf_local_marks(buf, rettv->vval.v_list); } -/* - * "getmatches()" function - */ -static void f_getmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - matchitem_T *cur; - int i; - win_T *win = get_optional_window(argvars, 0); - - if (win == NULL) { - return; - } - - tv_list_alloc_ret(rettv, kListLenMayKnow); - cur = win->w_match_head; - while (cur != NULL) { - dict_T *dict = tv_dict_alloc(); - if (cur->match.regprog == NULL) { - // match added with matchaddpos() - for (i = 0; i < MAXPOSMATCH; i++) { - llpos_T *llpos; - char buf[30]; // use 30 to avoid compiler warning - - llpos = &cur->pos.pos[i]; - if (llpos->lnum == 0) { - break; - } - list_T *const l = tv_list_alloc(1 + (llpos->col > 0 ? 2 : 0)); - tv_list_append_number(l, (varnumber_T)llpos->lnum); - if (llpos->col > 0) { - tv_list_append_number(l, (varnumber_T)llpos->col); - tv_list_append_number(l, (varnumber_T)llpos->len); - } - int len = snprintf(buf, sizeof(buf), "pos%d", i + 1); - assert((size_t)len < sizeof(buf)); - tv_dict_add_list(dict, buf, (size_t)len, l); - } - } else { - tv_dict_add_str(dict, S_LEN("pattern"), (const char *)cur->pattern); - } - tv_dict_add_str(dict, S_LEN("group"), - (const char *)syn_id2name(cur->hlg_id)); - tv_dict_add_nr(dict, S_LEN("priority"), (varnumber_T)cur->priority); - tv_dict_add_nr(dict, S_LEN("id"), (varnumber_T)cur->id); - - if (cur->conceal_char) { - char buf[MB_MAXBYTES + 1]; - - buf[utf_char2bytes(cur->conceal_char, (char_u *)buf)] = NUL; - tv_dict_add_str(dict, S_LEN("conceal"), buf); - } - - tv_list_append_dict(rettv->vval.v_list, dict); - cur = cur->next; - } -} - -// "getmousepos()" function -void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +/// "getmousepos()" function +static void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *d; win_T *wp; @@ -3805,7 +3595,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr) varnumber_T winid = 0; varnumber_T winrow = 0; varnumber_T wincol = 0; - linenr_T line = 0; + linenr_T lnum = 0; varnumber_T column = 0; tv_dict_alloc_ret(rettv); @@ -3816,26 +3606,16 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr) wp = mouse_find_win(&grid, &row, &col); if (wp != NULL) { - int height = wp->w_height + wp->w_status_height; + int height = wp->w_height + wp->w_hsep_height + wp->w_status_height; // The height is adjusted by 1 when there is a bottom border. This is not // necessary for a top border since `row` starts at -1 in that case. if (row < height + wp->w_border_adj[2]) { winid = wp->handle; - winrow = row + 1 + wp->w_border_adj[0]; // Adjust by 1 for top border - wincol = col + 1 + wp->w_border_adj[3]; // Adjust by 1 for left border + winrow = row + 1 + wp->w_winrow_off; // Adjust by 1 for top border + wincol = col + 1 + wp->w_wincol_off; // Adjust by 1 for left border if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) { - char_u *p; - int count; - - mouse_comp_pos(wp, &row, &col, &line); - - // limit to text length plus one - p = ml_get_buf(wp->w_buffer, line, false); - count = (int)STRLEN(p); - if (col > count) { - col = count; - } - + (void)mouse_comp_pos(wp, &row, &col, &lnum); + col = vcol2col(wp, lnum, col); column = col + 1; } } @@ -3843,73 +3623,31 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_nr(d, S_LEN("winid"), winid); tv_dict_add_nr(d, S_LEN("winrow"), winrow); tv_dict_add_nr(d, S_LEN("wincol"), wincol); - tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)line); + tv_dict_add_nr(d, S_LEN("line"), (varnumber_T)lnum); tv_dict_add_nr(d, S_LEN("column"), column); } -/* - * "getpid()" function - */ +/// "getpid()" function static void f_getpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = os_get_pid(); } -static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos) +/// "getcurpos(string)" function +static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - pos_T *fp; - int fnum = -1; - - if (getcurpos) { - fp = &curwin->w_cursor; - } else { - fp = var2fpos(&argvars[0], true, &fnum); - } - - list_T *const l = tv_list_alloc_ret(rettv, 4 + (!!getcurpos)); - tv_list_append_number(l, (fnum != -1) ? (varnumber_T)fnum : (varnumber_T)0); - tv_list_append_number(l, ((fp != NULL) - ? (varnumber_T)fp->lnum - : (varnumber_T)0)); - tv_list_append_number(l, ((fp != NULL) - ? (varnumber_T)(fp->col == MAXCOL ? MAXCOL : fp->col + 1) - : (varnumber_T)0)); - tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0); - if (getcurpos) { - const int save_set_curswant = curwin->w_set_curswant; - const colnr_T save_curswant = curwin->w_curswant; - const colnr_T save_virtcol = curwin->w_virtcol; - - update_curswant(); - tv_list_append_number(l, (curwin->w_curswant == MAXCOL - ? (varnumber_T)MAXCOL - : (varnumber_T)curwin->w_curswant + 1)); - - // Do not change "curswant", as it is unexpected that a get - // function has a side effect. - if (save_set_curswant) { - curwin->w_set_curswant = save_set_curswant; - curwin->w_curswant = save_curswant; - curwin->w_virtcol = save_virtcol; - curwin->w_valid &= ~VALID_VIRTCOL; - } - } + getpos_both(argvars, rettv, true, false); } -/* - * "getcurpos(string)" function - */ -static void f_getcurpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_getcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - getpos_both(argvars, rettv, true); + getpos_both(argvars, rettv, true, true); } -/* - * "getpos(string)" function - */ +/// "getpos(string)" function static void f_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - getpos_both(argvars, rettv, false); + getpos_both(argvars, rettv, false, false); } /// "getqflist()" functions @@ -3932,7 +3670,7 @@ static int getreg_get_regname(typval_T *argvars) } } else { // Default to v:register - strregname = get_vim_var_str(VV_REG); + strregname = (char_u *)get_vim_var_str(VV_REG); } return *strregname == 0 ? '"' : *strregname; @@ -3991,7 +3729,7 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, FunPtr fptr) MotionType reg_type = get_reg_type(regname, ®len); format_reg_type(reg_type, reglen, buf, ARRAY_SIZE(buf)); - rettv->vval.v_string = (char_u *)xstrdup(buf); + rettv->vval.v_string = xstrdup(buf); } /// "gettabinfo()" function @@ -4026,13 +3764,9 @@ static void f_gettabinfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "gettabvar()" function - */ +/// "gettabvar()" function static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - win_T *oldcurwin; - tabpage_T *oldtabpage; bool done = false; rettv->v_type = VAR_STRING; @@ -4046,7 +3780,8 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) win_T *const window = tp == curtab || tp->tp_firstwin == NULL ? firstwin : tp->tp_firstwin; - if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) { + switchwin_T switchwin; + if (switch_win(&switchwin, window, tp, true) == OK) { // look up the variable // Let gettabvar({nr}, "") return the "t:" dictionary. const dictitem_T *const v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', @@ -4059,7 +3794,7 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } // restore previous notion of curwin - restore_win(oldcurwin, oldtabpage, true); + restore_win(&switchwin, true); } if (!done && argvars[2].v_type != VAR_UNKNOWN) { @@ -4067,15 +3802,13 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "gettabwinvar()" function - */ +/// "gettabwinvar()" function static void f_gettabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { getwinvar(argvars, rettv, 1); } -// "gettagstack()" function +/// "gettagstack()" function static void f_gettagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp = curwin; // default is current window @@ -4100,7 +3833,7 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_alloc_ret(rettv, kListLenMayKnow); if (argvars[0].v_type != VAR_UNKNOWN) { - wparg = win_id2wp(argvars); + wparg = win_id2wp(tv_get_number(&argvars[0])); if (wparg == NULL) { return; } @@ -4127,12 +3860,11 @@ static void f_getwininfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// Dummy timer callback. Used by f_wait(). +/// Dummy timer callback. Used by f_wait(). static void dummy_timer_due_cb(TimeWatcher *tw, void *data) -{ -} +{} -// Dummy timer close callback. Used by f_wait(). +/// Dummy timer close callback. Used by f_wait(). static void dummy_timer_close_cb(TimeWatcher *tw, void *data) { xfree(tw); @@ -4170,15 +3902,14 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr) typval_T argv = TV_INITIAL_VALUE; typval_T exprval = TV_INITIAL_VALUE; bool error = false; - int save_called_emsg = called_emsg; - called_emsg = false; + const int called_emsg_before = called_emsg; LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, timeout, eval_expr_typval(&expr, &argv, 0, &exprval) != OK || tv_get_number_chk(&exprval, &error) - || called_emsg || error || got_int); + || called_emsg > called_emsg_before || error || got_int); - if (called_emsg || error) { + if (called_emsg > called_emsg_before || error) { rettv->vval.v_number = -3; } else if (got_int) { got_int = false; @@ -4188,14 +3919,12 @@ static void f_wait(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 0; } - called_emsg = save_called_emsg; - // Stop dummy timer time_watcher_stop(tw); time_watcher_close(tw, dummy_timer_close_cb); } -// "win_screenpos()" function +/// "win_screenpos()" function static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_alloc_ret(rettv, 2); @@ -4204,16 +3933,14 @@ static void f_win_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); } -// -// Move the window wp into a new split of targetwin in a given direction -// +/// Move the window wp into a new split of targetwin in a given direction static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) { int dir; int height = wp->w_height; win_T *oldwin = curwin; - if (wp == targetwin) { + if (wp == targetwin || wp == aucmd_win) { return; } @@ -4244,7 +3971,7 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags } } -// "win_splitmove()" function +/// "win_splitmove()" function static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp; @@ -4284,7 +4011,7 @@ static void f_win_splitmove(typval_T *argvars, typval_T *rettv, FunPtr fptr) win_move_into_split(wp, targetwin, size, flags); } -// "getwinpos({timeout})" function +/// "getwinpos({timeout})" function static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_alloc_ret(rettv, 2); @@ -4292,17 +4019,13 @@ static void f_getwinpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_number(rettv->vval.v_list, -1); } -/* - * "getwinposx()" function - */ +/// "getwinposx()" function static void f_getwinposx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; } -/* - * "getwinposy()" function - */ +/// "getwinposy()" function static void f_getwinposy(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -4314,9 +4037,7 @@ static void f_getwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) getwinvar(argvars, rettv, 0); } -/* - * "glob()" function - */ +/// "glob()" function static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int options = WILD_SILENT|WILD_USE_NL; @@ -4347,8 +4068,9 @@ static void f_glob(typval_T *argvars, typval_T *rettv, FunPtr fptr) options += WILD_ICASE; } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, - WILD_ALL); + rettv->vval.v_string = (char *)ExpandOne(&xpc, (char_u *) + tv_get_string(&argvars[0]), NULL, options, + WILD_ALL); } else { ExpandOne(&xpc, (char_u *)tv_get_string(&argvars[0]), NULL, options, WILD_ALL_KEEP); @@ -4399,7 +4121,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) globpath((char_u *)tv_get_string(&argvars[0]), (char_u *)file, &ga, flags); if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = (char_u *)ga_concat_strings_sep(&ga, "\n"); + rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); } else { tv_list_alloc_ret(rettv, ga.ga_len); for (int i = 0; i < ga.ga_len; i++) { @@ -4414,16 +4136,13 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "glob2regpat()" function +/// "glob2regpat()" function static void f_glob2regpat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const pat = tv_get_string_chk(&argvars[0]); // NULL on type error rettv->v_type = VAR_STRING; - rettv->vval.v_string = ((pat == NULL) - ? NULL - : file_pat_to_reg_pat((char_u *)pat, NULL, NULL, - false)); + rettv->vval.v_string = (pat == NULL) ? NULL : file_pat_to_reg_pat(pat, NULL, NULL, false); } /// "has()" function @@ -4433,6 +4152,12 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) #if defined(BSD) && !defined(__APPLE__) "bsd", #endif +#ifdef __linux__ + "linux", +#endif +#ifdef SUN_SYSTEM + "sun", +#endif #ifdef UNIX "unix", #endif @@ -4504,6 +4229,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "mouse", "multi_byte", "multi_lang", + "nanotime", "num64", "packages", "path_extra", @@ -4555,6 +4281,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) "userreg", }; + // XXX: eval_has_provider() may shell out :( + const int save_shell_error = get_vim_var_nr(VV_SHELL_ERROR); bool n = false; const char *const name = tv_get_string(&argvars[0]); for (size_t i = 0; i < ARRAY_SIZE(has_list); i++) { @@ -4611,6 +4339,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr) n = true; } + set_vim_var_nr(VV_SHELL_ERROR, save_shell_error); rettv->vval.v_number = n; } @@ -4746,34 +4475,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "hasmapto()" function - */ -static void f_hasmapto(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - const char *mode; - const char *const name = tv_get_string(&argvars[0]); - bool abbr = false; - char buf[NUMBUFLEN]; - if (argvars[1].v_type == VAR_UNKNOWN) { - mode = "nvo"; - } else { - mode = tv_get_string_buf(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = tv_get_number(&argvars[2]); - } - } - - if (map_to_exists(name, mode, abbr)) { - rettv->vval.v_number = true; - } else { - rettv->vval.v_number = false; - } -} - -/* - * "histadd()" function - */ +/// "histadd()" function static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType histype; @@ -4796,9 +4498,7 @@ static void f_histadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "histdel()" function - */ +/// "histdel()" function static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n; @@ -4821,9 +4521,7 @@ static void f_histdel(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "histget()" function - */ +/// "histget()" function static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr) { HistoryType type; @@ -4840,14 +4538,12 @@ static void f_histget(typval_T *argvars, typval_T *rettv, FunPtr fptr) idx = (int)tv_get_number_chk(&argvars[1], NULL); } // -1 on type error - rettv->vval.v_string = vim_strsave(get_history_entry(type, idx)); + rettv->vval.v_string = (char *)vim_strsave(get_history_entry(type, idx)); } rettv->v_type = VAR_STRING; } -/* - * "histnr()" function - */ +/// "histnr()" function static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const history = tv_get_string_chk(&argvars[0]); @@ -4860,37 +4556,29 @@ static void f_histnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = i; } -/* - * "highlightID(name)" function - */ +/// "highlightID(name)" function static void f_hlID(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = syn_name2id(tv_get_string(&argvars[0])); } -/* - * "highlight_exists()" function - */ +/// "highlight_exists()" function static void f_hlexists(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = highlight_exists(tv_get_string(&argvars[0])); } -/* - * "hostname()" function - */ +/// "hostname()" function static void f_hostname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char hostname[256]; os_get_hostname(hostname, 256); rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_strsave((char_u *)hostname); + rettv->vval.v_string = (char *)vim_strsave((char_u *)hostname); } -/* - * iconv() function - */ +/// iconv() function static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { vimconv_T vimconv; @@ -4908,9 +4596,9 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) // If the encodings are equal, no conversion needed. if (vimconv.vc_type == CONV_NONE) { - rettv->vval.v_string = (char_u *)xstrdup(str); + rettv->vval.v_string = xstrdup(str); } else { - rettv->vval.v_string = string_convert(&vimconv, (char_u *)str, NULL); + rettv->vval.v_string = (char *)string_convert(&vimconv, (char_u *)str, NULL); } convert_setup(&vimconv, NULL, NULL); @@ -4918,9 +4606,7 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(to); } -/* - * "indent()" function - */ +/// "indent()" function static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const linenr_T lnum = tv_get_lnum(argvars); @@ -4931,9 +4617,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "index()" function - */ +/// "index()" function static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) { long idx = 0; @@ -5007,26 +4691,20 @@ static void f_index(typval_T *argvars, typval_T *rettv, FunPtr fptr) static bool inputsecret_flag = false; -/* - * "input()" function - * Also handles inputsecret() when inputsecret is set. - */ +/// "input()" function +/// Also handles inputsecret() when inputsecret is set. static void f_input(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_user_input(argvars, rettv, FALSE, inputsecret_flag); } -/* - * "inputdialog()" function - */ +/// "inputdialog()" function static void f_inputdialog(typval_T *argvars, typval_T *rettv, FunPtr fptr) { get_user_input(argvars, rettv, TRUE, inputsecret_flag); } -/* - * "inputlist()" function - */ +/// "inputlist()" function static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int selected; @@ -5057,7 +4735,6 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = selected; } - static garray_T ga_userinput = { 0, 0, sizeof(tasave_T), 4, NULL }; /// "inputrestore()" function @@ -5092,9 +4769,7 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, FunPtr fptr) inputsecret_flag = false; } -/* - * "insert()" function - */ +/// "insert()" function static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; @@ -5166,43 +4841,37 @@ static void f_insert(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "interrupt()" function +/// "interrupt()" function static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, typval_T *rettv FUNC_ATTR_UNUSED, FunPtr fptr FUNC_ATTR_UNUSED) { got_int = true; } -/* - * "invert(expr)" function - */ +/// "invert(expr)" function static void f_invert(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ~tv_get_number_chk(&argvars[0], NULL); } -/* - * "isdirectory()" function - */ +/// "isdirectory()" function static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = os_isdir((const char_u *)tv_get_string(&argvars[0])); } -/* - * "islocked()" function - */ +/// "islocked()" function static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) { lval_T lv; dictitem_T *di; rettv->vval.v_number = -1; - const char_u *const end = get_lval((char_u *)tv_get_string(&argvars[0]), - NULL, - &lv, false, false, - GLV_NO_AUTOLOAD|GLV_READ_ONLY, - FNE_CHECK_START); + const char_u *const end = (char_u *)get_lval((char *)tv_get_string(&argvars[0]), + NULL, + &lv, false, false, + GLV_NO_AUTOLOAD|GLV_READ_ONLY, + FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) { if (*end != NUL) { emsg(_(e_trailing)); @@ -5234,7 +4903,7 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr) clear_lval(&lv); } -// "isinf()" function +/// "isinf()" function static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type == VAR_FLOAT @@ -5243,7 +4912,7 @@ static void f_isinf(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "isnan()" function +/// "isnan()" function static void f_isnan(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT @@ -5257,19 +4926,16 @@ static void f_id(typval_T *argvars, typval_T *rettv, FunPtr fptr) const int len = vim_vsnprintf_typval(NULL, 0, "%p", dummy_ap, argvars); rettv->v_type = VAR_STRING; rettv->vval.v_string = xmalloc(len + 1); - vim_vsnprintf_typval((char *)rettv->vval.v_string, len + 1, "%p", - dummy_ap, argvars); + vim_vsnprintf_typval(rettv->vval.v_string, len + 1, "%p", dummy_ap, argvars); } -/* - * "items(dict)" function - */ +/// "items(dict)" function static void f_items(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 2); } -// "jobpid(id)" function +/// "jobpid(id)" function static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -5293,7 +4959,7 @@ static void f_jobpid(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = proc->pid; } -// "jobresize(job, width, height)" function +/// "jobresize(job, width, height)" function static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -5310,7 +4976,6 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - Channel *data = find_job(argvars[0].vval.v_number, true); if (!data) { return; @@ -5402,6 +5067,16 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en tv_dict_add_str(env, S_LEN("TERM"), pty_term_name); } + // Set $NVIM (in the child process) to v:servername. #3118 + char *nvim_addr = get_vim_var_str(VV_SEND_SERVER); + if (nvim_addr[0] != '\0') { + dictitem_T *dv = tv_dict_find(env, S_LEN("NVIM")); + if (dv) { + tv_dict_item_remove(env, dv); + } + tv_dict_add_str(env, S_LEN("NVIM"), nvim_addr); + } + if (job_env) { #ifdef WIN32 TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, { @@ -5440,7 +5115,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en return env; } -// "jobstart()" function +/// "jobstart()" function static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -5465,7 +5140,6 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - dict_T *job_opts = NULL; bool detach = false; bool rpc = false; @@ -5561,7 +5235,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "jobstop()" function +/// "jobstop()" function static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -5594,7 +5268,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "jobwait(ids[, timeout])" function +/// "jobwait(ids[, timeout])" function static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -5693,9 +5367,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_list = rv; } -/* - * "join()" function - */ +/// "join()" function static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_LIST) { @@ -5713,7 +5385,7 @@ static void f_join(typval_T *argvars, typval_T *rettv, FunPtr fptr) ga_init(&ga, (int)sizeof(char), 80); tv_list_join(&ga, argvars[0].vval.v_list, sep); ga_append(&ga, NUL); - rettv->vval.v_string = (char_u *)ga.ga_data; + rettv->vval.v_string = ga.ga_data; } else { rettv->vval.v_string = NULL; } @@ -5757,20 +5429,16 @@ static void f_json_decode(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void f_json_encode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)encode_tv2json(&argvars[0], NULL); + rettv->vval.v_string = encode_tv2json(&argvars[0], NULL); } -/* - * "keys()" function - */ +/// "keys()" function static void f_keys(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 0); } -/* - * "last_buffer_nr()" function. - */ +/// "last_buffer_nr()" function. static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n = 0; @@ -5784,9 +5452,7 @@ static void f_last_buffer_nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "len()" function - */ +/// "len()" function static void f_len(typval_T *argvars, typval_T *rettv, FunPtr fptr) { switch (argvars[0].v_type) { @@ -5830,19 +5496,17 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) return; } - const char *libname = (char *)argvars[0].vval.v_string; - const char *funcname = (char *)argvars[1].vval.v_string; + const char *libname = argvars[0].vval.v_string; + const char *funcname = argvars[1].vval.v_string; VarType in_type = argvars[2].v_type; // input variables - char *str_in = (in_type == VAR_STRING) - ? (char *)argvars[2].vval.v_string : NULL; + char *str_in = (in_type == VAR_STRING) ? argvars[2].vval.v_string : NULL; int int_in = argvars[2].vval.v_number; // output variables - char **str_out = (out_type == VAR_STRING) - ? (char **)&rettv->vval.v_string : NULL; + char **str_out = (out_type == VAR_STRING) ? &rettv->vval.v_string : NULL; int int_out = 0; bool success = os_libcall(libname, funcname, @@ -5859,23 +5523,19 @@ static void libcall_common(typval_T *argvars, typval_T *rettv, int out_type) } } -/* - * "libcall()" function - */ +/// "libcall()" function static void f_libcall(typval_T *argvars, typval_T *rettv, FunPtr fptr) { libcall_common(argvars, rettv, VAR_STRING); } -/* - * "libcallnr()" function - */ +/// "libcallnr()" function static void f_libcallnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { libcall_common(argvars, rettv, VAR_NUMBER); } -// "line(string, [winid])" function +/// "line(string, [winid])" function static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = 0; @@ -5883,23 +5543,21 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) int fnum; if (argvars[1].v_type != VAR_UNKNOWN) { - tabpage_T *tp; - win_T *save_curwin; - tabpage_T *save_curtab; - // use window specified in the second argument - win_T *wp = win_id2wp_tp(&argvars[1], &tp); + int id = (int)tv_get_number(&argvars[1]); + tabpage_T *tp; + win_T *wp = win_id2wp_tp(id, &tp); if (wp != NULL && tp != NULL) { - if (switch_win_noblock(&save_curwin, &save_curtab, wp, tp, true) - == OK) { + switchwin_T switchwin; + if (switch_win_noblock(&switchwin, wp, tp, true) == OK) { check_cursor(); - fp = var2fpos(&argvars[0], true, &fnum); + fp = var2fpos(&argvars[0], true, &fnum, false); } - restore_win_noblock(save_curwin, save_curtab, true); + restore_win_noblock(&switchwin, true); } } else { // use current window - fp = var2fpos(&argvars[0], true, &fnum); + fp = var2fpos(&argvars[0], true, &fnum, false); } if (fp != NULL) { @@ -5908,9 +5566,7 @@ static void f_line(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = lnum; } -/* - * "line2byte(lnum)" function - */ +/// "line2byte(lnum)" function static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const linenr_T lnum = tv_get_lnum(argvars); @@ -5924,9 +5580,7 @@ static void f_line2byte(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "lispindent(lnum)" function - */ +/// "lispindent(lnum)" function static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const pos_T pos = curwin->w_cursor; @@ -5940,7 +5594,7 @@ static void f_lispindent(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "list2str()" function +/// "list2str()" function static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; @@ -5958,10 +5612,10 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) } ga_init(&ga, 1, 80); - char_u buf[MB_MAXBYTES + 1]; + char buf[MB_MAXBYTES + 1]; TV_LIST_ITER_CONST(l, li, { - buf[utf_char2bytes(tv_get_number(TV_LIST_ITEM_TV(li)), buf)] = NUL; + buf[utf_char2bytes(tv_get_number(TV_LIST_ITEM_TV(li)), (char *)buf)] = NUL; ga_concat(&ga, (char *)buf); }); ga_append(&ga, NUL); @@ -5969,82 +5623,12 @@ static void f_list2str(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_string = ga.ga_data; } -/* - * "localtime()" function - */ +/// "localtime()" function static void f_localtime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (varnumber_T)time(NULL); } - -static void get_maparg(typval_T *argvars, typval_T *rettv, int exact) -{ - char_u *keys_buf = NULL; - char_u *rhs; - LuaRef rhs_lua; - int mode; - int abbr = FALSE; - int get_dict = FALSE; - mapblock_T *mp; - int buffer_local; - - // Return empty string for failure. - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - char_u *keys = (char_u *)tv_get_string(&argvars[0]); - if (*keys == NUL) { - return; - } - - char buf[NUMBUFLEN]; - const char *which; - if (argvars[1].v_type != VAR_UNKNOWN) { - which = tv_get_string_buf_chk(&argvars[1], buf); - if (argvars[2].v_type != VAR_UNKNOWN) { - abbr = tv_get_number(&argvars[2]); - if (argvars[3].v_type != VAR_UNKNOWN) { - get_dict = tv_get_number(&argvars[3]); - } - } - } else { - which = ""; - } - if (which == NULL) { - return; - } - - mode = get_map_mode((char_u **)&which, 0); - - keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true, - CPO_TO_CPO_FLAGS); - rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua); - xfree(keys_buf); - - if (!get_dict) { - // Return a string. - if (rhs != NULL) { - if (*rhs == NUL) { - rettv->vval.v_string = vim_strsave((char_u *)"<Nop>"); - } else { - rettv->vval.v_string = (char_u *)str2special_save((char *)rhs, false, false); - } - } else if (rhs_lua != LUA_NOREF) { - size_t msglen = 100; - char *msg = (char *)xmalloc(msglen); - snprintf(msg, msglen, "<Lua function %d>", mp->m_luaref); - rettv->vval.v_string = (char_u *)msg; - } - } else { - tv_dict_alloc_ret(rettv); - if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) { - // Return a dictionary. - mapblock_fill_dict(rettv->vval.v_dict, mp, buffer_local, true); - } - } -} - /// luaeval() function implementation static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL @@ -6057,31 +5641,12 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv); } -/* - * "map()" function - */ +/// "map()" function static void f_map(typval_T *argvars, typval_T *rettv, FunPtr fptr) { filter_map(argvars, rettv, TRUE); } -/* - * "maparg()" function - */ -static void f_maparg(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - get_maparg(argvars, rettv, TRUE); -} - -/* - * "mapcheck()" function - */ -static void f_mapcheck(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - get_maparg(argvars, rettv, FALSE); -} - - static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { @@ -6089,7 +5654,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, long len = 0; char_u *expr = NULL; regmatch_T regmatch; - char_u *save_cpo; + char *save_cpo; long start = 0; long nth = 1; colnr_T startcol = 0; @@ -6101,7 +5666,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; - p_cpo = (char_u *)""; + p_cpo = ""; rettv->vval.v_number = -1; switch (type) { @@ -6182,7 +5747,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } } - regmatch.regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; @@ -6215,7 +5780,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, idx++; } else { startcol = (colnr_T)(regmatch.startp[0] - + utfc_ptr2len(regmatch.startp[0]) - str); + + utfc_ptr2len((char *)regmatch.startp[0]) - str); if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) { match = false; break; @@ -6261,9 +5826,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, if (l != NULL) { tv_copy(TV_LIST_ITEM_TV(li), rettv); } else { - rettv->vval.v_string = (char_u *)xmemdupz((const char *)regmatch.startp[0], - (size_t)(regmatch.endp[0] - - regmatch.startp[0])); + rettv->vval.v_string = xmemdupz((const char *)regmatch.startp[0], + (size_t)(regmatch.endp[0] - + regmatch.startp[0])); } break; case kSomeMatch: @@ -6297,166 +5862,25 @@ theend: p_cpo = save_cpo; } -/* - * "match()" function - */ +/// "match()" function static void f_match(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, kSomeMatch); } -/* - * "matchadd()" function - */ -static void f_matchadd(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - char grpbuf[NUMBUFLEN]; - char patbuf[NUMBUFLEN]; - // group - const char *const grp = tv_get_string_buf_chk(&argvars[0], grpbuf); - // pattern - const char *const pat = tv_get_string_buf_chk(&argvars[1], patbuf); - // default priority - int prio = 10; - int id = -1; - bool error = false; - const char *conceal_char = NULL; - win_T *win = curwin; - - rettv->vval.v_number = -1; - - if (grp == NULL || pat == NULL) { - return; - } - if (argvars[2].v_type != VAR_UNKNOWN) { - prio = tv_get_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) { - id = tv_get_number_chk(&argvars[3], &error); - if (argvars[4].v_type != VAR_UNKNOWN - && matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL) { - return; - } - } - } - if (error) { - return; - } - if (id >= 1 && id <= 3) { - semsg(_("E798: ID is reserved for \":match\": %" PRId64), (int64_t)id); - return; - } - - rettv->vval.v_number = match_add(win, grp, pat, prio, id, NULL, conceal_char); -} - -static void f_matchaddpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - rettv->vval.v_number = -1; - - char buf[NUMBUFLEN]; - const char *const group = tv_get_string_buf_chk(&argvars[0], buf); - if (group == NULL) { - return; - } - - if (argvars[1].v_type != VAR_LIST) { - semsg(_(e_listarg), "matchaddpos()"); - return; - } - - list_T *l; - l = argvars[1].vval.v_list; - if (l == NULL) { - return; - } - - bool error = false; - int prio = 10; - int id = -1; - const char *conceal_char = NULL; - win_T *win = curwin; - - if (argvars[2].v_type != VAR_UNKNOWN) { - prio = tv_get_number_chk(&argvars[2], &error); - if (argvars[3].v_type != VAR_UNKNOWN) { - id = tv_get_number_chk(&argvars[3], &error); - if (argvars[4].v_type != VAR_UNKNOWN - && matchadd_dict_arg(&argvars[4], &conceal_char, &win) == FAIL) { - return; - } - } - } - if (error == true) { - return; - } - - // id == 3 is ok because matchaddpos() is supposed to substitute :3match - if (id == 1 || id == 2) { - semsg(_("E798: ID is reserved for \"match\": %" PRId64), (int64_t)id); - return; - } - - rettv->vval.v_number = match_add(win, group, NULL, prio, id, l, conceal_char); -} - -/* - * "matcharg()" function - */ -static void f_matcharg(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - const int id = tv_get_number(&argvars[0]); - - tv_list_alloc_ret(rettv, (id >= 1 && id <= 3 - ? 2 - : 0)); - - if (id >= 1 && id <= 3) { - matchitem_T *const m = get_match(curwin, id); - - if (m != NULL) { - tv_list_append_string(rettv->vval.v_list, - (const char *)syn_id2name(m->hlg_id), -1); - tv_list_append_string(rettv->vval.v_list, (const char *)m->pattern, -1); - } else { - tv_list_append_string(rettv->vval.v_list, NULL, 0); - tv_list_append_string(rettv->vval.v_list, NULL, 0); - } - } -} - -/* - * "matchdelete()" function - */ -static void f_matchdelete(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - win_T *win = get_optional_window(argvars, 1); - if (win == NULL) { - rettv->vval.v_number = -1; - } else { - rettv->vval.v_number = match_delete(win, - (int)tv_get_number(&argvars[0]), true); - } -} - -/* - * "matchend()" function - */ +/// "matchend()" function static void f_matchend(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, kSomeMatchEnd); } -/* - * "matchlist()" function - */ +/// "matchlist()" function static void f_matchlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, kSomeMatchList); } -/* - * "matchstr()" function - */ +/// "matchstr()" function static void f_matchstr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { find_some_match(argvars, rettv, kSomeMatchStr); @@ -6517,25 +5941,19 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool rettv->vval.v_number = n; } -/* - * "max()" function - */ +/// "max()" function static void f_max(typval_T *argvars, typval_T *rettv, FunPtr fptr) { max_min(argvars, rettv, TRUE); } -/* - * "min()" function - */ +/// "min()" function static void f_min(typval_T *argvars, typval_T *rettv, FunPtr fptr) { max_min(argvars, rettv, FALSE); } -/* - * "mkdir()" function - */ +/// "mkdir()" function static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int prot = 0755; // -V536 @@ -6551,9 +5969,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - if (*path_tail((char_u *)dir) == NUL) { + if (*path_tail(dir) == NUL) { // Remove trailing slashes. - *path_tail_with_sep((char_u *)dir) = NUL; + *path_tail_with_sep((char *)dir) = NUL; } if (argvars[1].v_type != VAR_UNKNOWN) { @@ -6583,15 +6001,17 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) /// "mode()" function static void f_mode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char *mode = get_mode(); + char buf[MODE_MAX_LENGTH]; + + get_mode(buf); // Clear out the minor mode when the argument is not a non-zero number or // non-empty string. if (!non_zero_arg(&argvars[0])) { - mode[1] = NUL; + buf[1] = NUL; } - rettv->vval.v_string = (char_u *)mode; + rettv->vval.v_string = xstrdup(buf); rettv->v_type = VAR_STRING; } @@ -6750,9 +6170,7 @@ static void f_msgpackparse(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "nextnonblank()" function - */ +/// "nextnonblank()" function static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum; @@ -6762,16 +6180,14 @@ static void f_nextnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) lnum = 0; break; } - if (*skipwhite(ml_get(lnum)) != NUL) { + if (*skipwhite((char *)ml_get(lnum)) != NUL) { break; } } rettv->vval.v_number = lnum; } -/* - * "nr2char()" function - */ +/// "nr2char()" function static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[1].v_type != VAR_UNKNOWN) { @@ -6796,37 +6212,42 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, FunPtr fptr) } char buf[MB_MAXBYTES]; - const int len = utf_char2bytes((int)num, (char_u *)buf); + const int len = utf_char2bytes((int)num, buf); rettv->v_type = VAR_STRING; rettv->vval.v_string = xmemdupz(buf, (size_t)len); } -/* - * "or(expr, expr)" function - */ +/// "or(expr, expr)" function static void f_or(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) | tv_get_number_chk(&argvars[1], NULL); } -/* - * "pathshorten()" function - */ +/// "pathshorten()" function static void f_pathshorten(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + int trim_len = 1; + + if (argvars[1].v_type != VAR_UNKNOWN) { + trim_len = (int)tv_get_number(&argvars[1]); + if (trim_len < 1) { + trim_len = 1; + } + } + rettv->v_type = VAR_STRING; - const char *const s = tv_get_string_chk(&argvars[0]); - if (!s) { - return; + const char_u *p = (char_u *)tv_get_string_chk(&argvars[0]); + if (p == NULL) { + rettv->vval.v_string = NULL; + } else { + rettv->vval.v_string = (char *)vim_strsave(p); + shorten_dir_len((char_u *)rettv->vval.v_string, trim_len); } - rettv->vval.v_string = shorten_dir((char_u *)xstrdup(s)); } -/* - * "pow()" function - */ +/// "pow()" function static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { float_T fx; @@ -6840,25 +6261,21 @@ static void f_pow(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "prevnonblank()" function - */ +/// "prevnonblank()" function static void f_prevnonblank(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = tv_get_lnum(argvars); if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) { lnum = 0; } else { - while (lnum >= 1 && *skipwhite(ml_get(lnum)) == NUL) { + while (lnum >= 1 && *skipwhite((char *)ml_get(lnum)) == NUL) { lnum--; } } rettv->vval.v_number = lnum; } -/* - * "printf()" function - */ +/// "printf()" function static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; @@ -6874,14 +6291,14 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr) len = vim_vsnprintf_typval(NULL, 0, fmt, dummy_ap, argvars + 1); if (!did_emsg) { char *s = xmalloc(len + 1); - rettv->vval.v_string = (char_u *)s; + rettv->vval.v_string = s; (void)vim_vsnprintf_typval(s, len + 1, fmt, dummy_ap, argvars + 1); } did_emsg |= saved_did_emsg; } } -// "prompt_setcallback({buffer}, {callback})" function +/// "prompt_setcallback({buffer}, {callback})" function static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -6905,7 +6322,7 @@ static void f_prompt_setcallback(typval_T *argvars, typval_T *rettv, FunPtr fptr buf->b_prompt_callback = prompt_callback; } -// "prompt_setinterrupt({buffer}, {callback})" function +/// "prompt_setinterrupt({buffer}, {callback})" function static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fptr) { buf_T *buf; @@ -6930,7 +6347,7 @@ static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, FunPtr fpt } /// "prompt_getprompt({buffer})" function -void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { // return an empty string by default, e.g. it's not a prompt buffer @@ -6946,38 +6363,33 @@ void f_prompt_getprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - rettv->vval.v_string = vim_strsave(buf_prompt_text(buf)); + rettv->vval.v_string = (char *)vim_strsave(buf_prompt_text(buf)); } -// "prompt_setprompt({buffer}, {text})" function +/// "prompt_setprompt({buffer}, {text})" function static void f_prompt_setprompt(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - buf_T *buf; - const char_u *text; - if (check_secure()) { return; } - buf = tv_get_buf(&argvars[0], false); + buf_T *buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { return; } - text = (const char_u *)tv_get_string(&argvars[1]); + const char *text = tv_get_string(&argvars[1]); xfree(buf->b_prompt_text); - buf->b_prompt_text = vim_strsave(text); + buf->b_prompt_text = xstrdup(text); } -// "pum_getpos()" function +/// "pum_getpos()" function static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_dict_alloc_ret(rettv); pum_set_event_info(rettv->vval.v_dict); } -/* - * "pumvisible()" function - */ +/// "pumvisible()" function static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (pum_visible()) { @@ -6985,50 +6397,183 @@ static void f_pumvisible(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "pyeval()" function - */ -static void f_pyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +/// "py3eval()" and "pyxeval()" functions (always python3) +static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - script_host_eval("python", argvars, rettv); + script_host_eval("python3", argvars, rettv); } -/* - * "py3eval()" function - */ -static void f_py3eval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static void init_srand(uint32_t *const x) + FUNC_ATTR_NONNULL_ALL { - script_host_eval("python3", argvars, rettv); +#ifndef MSWIN + static int dev_urandom_state = NOTDONE; // FAIL or OK once tried + + if (dev_urandom_state != FAIL) { + const int fd = os_open("/dev/urandom", O_RDONLY, 0); + struct { + union { + uint32_t number; + char bytes[sizeof(uint32_t)]; + } contents; + } buf; + + // Attempt reading /dev/urandom. + if (fd == -1) { + dev_urandom_state = FAIL; + } else { + buf.contents.number = 0; + if (read(fd, buf.contents.bytes, sizeof(uint32_t)) != sizeof(uint32_t)) { + dev_urandom_state = FAIL; + } else { + dev_urandom_state = OK; + *x = buf.contents.number; + } + os_close(fd); + } + } + if (dev_urandom_state != OK) { + // Reading /dev/urandom doesn't work, fall back to time(). +#endif + // uncrustify:off + *x = time(NULL); +#ifndef MSWIN + } +#endif + // uncrustify:on } -// "pyxeval()" function -static void f_pyxeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) +static inline uint32_t splitmix32(uint32_t *const x) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE { - init_pyxversion(); - if (p_pyx == 2) { - f_pyeval(argvars, rettv, NULL); + uint32_t z = (*x += 0x9e3779b9); + z = (z ^ (z >> 16)) * 0x85ebca6b; + z = (z ^ (z >> 13)) * 0xc2b2ae35; + return z ^ (z >> 16); +} + +static inline uint32_t shuffle_xoshiro128starstar(uint32_t *const x, uint32_t *const y, + uint32_t *const z, uint32_t *const w) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_ALWAYS_INLINE +{ +#define ROTL(x, k) (((x) << (k)) | ((x) >> (32 - (k)))) + const uint32_t result = ROTL(*y * 5, 7) * 9; + const uint32_t t = *y << 9; + *z ^= *x; + *w ^= *y; + *y ^= *z; + *x ^= *w; + *z ^= t; + *w = ROTL(*w, 11); +#undef ROTL + return result; +} + +/// "rand()" function +static void f_rand(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + uint32_t result; + + if (argvars[0].v_type == VAR_UNKNOWN) { + static uint32_t gx, gy, gz, gw; + static bool initialized = false; + + // When no argument is given use the global seed list. + if (!initialized) { + // Initialize the global seed list. + uint32_t x; + init_srand(&x); + + gx = splitmix32(&x); + gy = splitmix32(&x); + gz = splitmix32(&x); + gw = splitmix32(&x); + initialized = true; + } + + result = shuffle_xoshiro128starstar(&gx, &gy, &gz, &gw); + } else if (argvars[0].v_type == VAR_LIST) { + list_T *const l = argvars[0].vval.v_list; + if (tv_list_len(l) != 4) { + goto theend; + } + + typval_T *const tvx = TV_LIST_ITEM_TV(tv_list_find(l, 0L)); + typval_T *const tvy = TV_LIST_ITEM_TV(tv_list_find(l, 1L)); + typval_T *const tvz = TV_LIST_ITEM_TV(tv_list_find(l, 2L)); + typval_T *const tvw = TV_LIST_ITEM_TV(tv_list_find(l, 3L)); + if (tvx->v_type != VAR_NUMBER) { + goto theend; + } + if (tvy->v_type != VAR_NUMBER) { + goto theend; + } + if (tvz->v_type != VAR_NUMBER) { + goto theend; + } + if (tvw->v_type != VAR_NUMBER) { + goto theend; + } + uint32_t x = tvx->vval.v_number; + uint32_t y = tvy->vval.v_number; + uint32_t z = tvz->vval.v_number; + uint32_t w = tvw->vval.v_number; + + result = shuffle_xoshiro128starstar(&x, &y, &z, &w); + + tvx->vval.v_number = (varnumber_T)x; + tvy->vval.v_number = (varnumber_T)y; + tvz->vval.v_number = (varnumber_T)z; + tvw->vval.v_number = (varnumber_T)w; } else { - f_py3eval(argvars, rettv, NULL); + goto theend; } + + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = (varnumber_T)result; + return; + +theend: + semsg(_(e_invarg2), tv_get_string(&argvars[0])); + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = -1; +} + +/// "srand()" function +static void f_srand(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + uint32_t x = 0; + + tv_list_alloc_ret(rettv, 4); + if (argvars[0].v_type == VAR_UNKNOWN) { + init_srand(&x); + } else { + bool error = false; + x = tv_get_number_chk(&argvars[0], &error); + if (error) { + return; + } + } + + tv_list_append_number(rettv->vval.v_list, (varnumber_T)splitmix32(&x)); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)splitmix32(&x)); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)splitmix32(&x)); + tv_list_append_number(rettv->vval.v_list, (varnumber_T)splitmix32(&x)); } -/// /// "perleval()" function -/// static void f_perleval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { script_host_eval("perl", argvars, rettv); } -// "rubyeval()" function +/// "rubyeval()" function static void f_rubyeval(typval_T *argvars, typval_T *rettv, FunPtr fptr) { script_host_eval("ruby", argvars, rettv); } -/* - * "range()" function - */ +/// "range()" function static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) { varnumber_T start; @@ -7063,19 +6608,25 @@ static void f_range(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// Evaluate "expr" for readdir(). -static varnumber_T readdir_checkitem(typval_T *expr, const char *name) +/// Evaluate "expr" (= "context") for readdir(). +static varnumber_T readdir_checkitem(void *context, const char *name) + FUNC_ATTR_NONNULL_ALL { + typval_T *expr = (typval_T *)context; typval_T save_val; typval_T rettv; typval_T argv[2]; varnumber_T retval = 0; bool error = false; + if (expr->v_type == VAR_UNKNOWN) { + return 1; + } + prepare_vimvar(VV_VAL, &save_val); set_vim_var_string(VV_VAL, name, -1); argv[0].v_type = VAR_STRING; - argv[0].vval.v_string = (char_u *)name; + argv[0].vval.v_string = (char *)name; if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) { goto theend; @@ -7094,65 +6645,25 @@ theend: return retval; } -// "readdir()" function +/// "readdir()" function static void f_readdir(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - typval_T *expr; - const char *path; - garray_T ga; - Directory dir; - tv_list_alloc_ret(rettv, kListLenUnknown); - path = tv_get_string(&argvars[0]); - expr = &argvars[1]; - ga_init(&ga, (int)sizeof(char *), 20); - if (!os_scandir(&dir, path)) { - smsg(_(e_notopen), path); - } else { - for (;;) { - bool ignore; - - path = os_scandir_next(&dir); - if (path == NULL) { - break; - } - - ignore = (path[0] == '.' - && (path[1] == NUL || (path[1] == '.' && path[2] == NUL))); - if (!ignore && expr->v_type != VAR_UNKNOWN) { - varnumber_T r = readdir_checkitem(expr, path); - - if (r < 0) { - break; - } - if (r == 0) { - ignore = true; - } - } - - if (!ignore) { - ga_grow(&ga, 1); - ((char **)ga.ga_data)[ga.ga_len++] = xstrdup(path); - } - } - - os_closedir(&dir); - } - - if (rettv->vval.v_list != NULL && ga.ga_len > 0) { - sort_strings((char_u **)ga.ga_data, ga.ga_len); + const char *path = tv_get_string(&argvars[0]); + typval_T *expr = &argvars[1]; + garray_T ga; + int ret = readdir_core(&ga, path, (void *)expr, readdir_checkitem); + if (ret == OK && ga.ga_len > 0) { for (int i = 0; i < ga.ga_len; i++) { - path = ((const char **)ga.ga_data)[i]; - tv_list_append_string(rettv->vval.v_list, path, -1); + const char *p = ((const char **)ga.ga_data)[i]; + tv_list_append_string(rettv->vval.v_list, p, -1); } } ga_clear_strings(&ga); } -/* - * "readfile()" function - */ +/// "readfile()" function static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool binary = false; @@ -7250,7 +6761,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_owned_tv(l, (typval_T) { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = s, + .vval.v_string = (char *)s, }); start = p + 1; // Step over newline. @@ -7386,13 +6897,13 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "reg_executing()" function +/// "reg_executing()" function static void f_reg_executing(typval_T *argvars, typval_T *rettv, FunPtr fptr) { return_register(reg_executing, rettv); } -// "reg_recording()" function +/// "reg_recording()" function static void f_reg_recording(typval_T *argvars, typval_T *rettv, FunPtr fptr) { return_register(reg_recording, rettv); @@ -7490,13 +7001,11 @@ static void f_reltimestr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; if (list2proftime(&argvars[0], &tm) == OK) { - rettv->vval.v_string = (char_u *)xstrdup(profile_msg(tm)); + rettv->vval.v_string = xstrdup(profile_msg(tm)); } } -/* - * "remove()" function - */ +/// "remove()" function static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) { list_T *l; @@ -7630,9 +7139,7 @@ static void f_remove(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "rename({from}, {to})" function - */ +/// "rename({from}, {to})" function static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_secure()) { @@ -7644,9 +7151,7 @@ static void f_rename(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "repeat()" function - */ +/// "repeat()" function static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) { varnumber_T n = tv_get_number(&argvars[1]); @@ -7679,13 +7184,11 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, FunPtr fptr) memmove(r + i * slen, p, slen); } - rettv->vval.v_string = (char_u *)r; + rettv->vval.v_string = r; } } -/* - * "resolve()" function - */ +/// "resolve()" function static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; @@ -7765,11 +7268,11 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) q[-1] = NUL; } - q = (char *)path_tail((char_u *)p); + q = path_tail(p); if (q > p && *q == NUL) { // Ignore trailing path separator. q[-1] = NUL; - q = (char *)path_tail((char_u *)p); + q = path_tail(p); } if (q > p && !path_is_absolute((const char_u *)buf)) { // Symlink is relative to directory of argument. Replace the @@ -7777,7 +7280,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) const size_t p_len = strlen(p); const size_t buf_len = strlen(buf); p = xrealloc(p, p_len + buf_len + 1); - memcpy(path_tail((char_u *)p), buf, buf_len + 1); + memcpy(path_tail(p), buf, buf_len + 1); } else { xfree(p); p = xstrdup(buf); @@ -7838,11 +7341,11 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!has_trailing_pathsep) { q = p + strlen(p); if (after_pathsep(p, q)) { - *path_tail_with_sep((char_u *)p) = NUL; + *path_tail_with_sep(p) = NUL; } } - rettv->vval.v_string = (char_u *)p; + rettv->vval.v_string = p; xfree(buf); } # else @@ -7851,12 +7354,10 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, FunPtr fptr) # endif #endif - simplify_filename(rettv->vval.v_string); + simplify_filename((char_u *)rettv->vval.v_string); } -/* - * "reverse({list})" function - */ +/// "reverse({list})" function static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type == VAR_BLOB) { @@ -7881,6 +7382,102 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +/// "reduce(list, { accumulator, element -> value } [, initial])" function +static void f_reduce(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) { + emsg(_(e_listblobreq)); + return; + } + + const char *func_name; + partial_T *partial = NULL; + if (argvars[1].v_type == VAR_FUNC) { + func_name = argvars[1].vval.v_string; + } else if (argvars[1].v_type == VAR_PARTIAL) { + partial = argvars[1].vval.v_partial; + func_name = partial_name(partial); + } else { + func_name = tv_get_string(&argvars[1]); + } + if (*func_name == NUL) { + return; // type error or empty name + } + + funcexe_T funcexe = FUNCEXE_INIT; + funcexe.evaluate = true; + funcexe.partial = partial; + + typval_T initial; + typval_T argv[3]; + if (argvars[0].v_type == VAR_LIST) { + list_T *const l = argvars[0].vval.v_list; + const listitem_T *li; + + if (argvars[2].v_type == VAR_UNKNOWN) { + if (tv_list_len(l) == 0) { + semsg(_(e_reduceempty), "List"); + return; + } + const listitem_T *const first = tv_list_first(l); + initial = *TV_LIST_ITEM_TV(first); + li = TV_LIST_ITEM_NEXT(l, first); + } else { + initial = argvars[2]; + li = tv_list_first(l); + } + + tv_copy(&initial, rettv); + + if (l != NULL) { + const VarLockStatus prev_locked = tv_list_locked(l); + const int called_emsg_start = called_emsg; + + tv_list_set_lock(l, VAR_FIXED); // disallow the list changing here + for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { + argv[0] = *rettv; + argv[1] = *TV_LIST_ITEM_TV(li); + rettv->v_type = VAR_UNKNOWN; + const int r = call_func((char *)func_name, -1, rettv, 2, argv, &funcexe); + tv_clear(&argv[0]); + if (r == FAIL || called_emsg != called_emsg_start) { + break; + } + } + tv_list_set_lock(l, prev_locked); + } + } else { + const blob_T *const b = argvars[0].vval.v_blob; + int i; + + if (argvars[2].v_type == VAR_UNKNOWN) { + if (tv_blob_len(b) == 0) { + semsg(_(e_reduceempty), "Blob"); + return; + } + initial.v_type = VAR_NUMBER; + initial.vval.v_number = tv_blob_get(b, 0); + i = 1; + } else if (argvars[2].v_type != VAR_NUMBER) { + emsg(_(e_number_exp)); + return; + } else { + initial = argvars[2]; + i = 0; + } + + tv_copy(&initial, rettv); + for (; i < tv_blob_len(b); i++) { + argv[0] = *rettv; + argv[1].v_type = VAR_NUMBER; + argv[1].vval.v_number = tv_blob_get(b, i); + if (call_func((char *)func_name, -1, rettv, 2, argv, &funcexe) == FAIL) { + return; + } + } + } +} + #define SP_NOMOVE 0x01 ///< don't move cursor #define SP_REPEAT 0x02 ///< repeat to find outer pair #define SP_RETCOUNT 0x04 ///< return matchcount @@ -7890,11 +7487,10 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, FunPtr fptr) #define SP_END 0x40 ///< leave cursor at end of match #define SP_COLUMN 0x80 ///< start at cursor column -/* - * Get flags for a search function. - * Possibly sets "p_ws". - * Returns BACKWARD, FORWARD or zero (for an error). - */ +/// Get flags for a search function. +/// Possibly sets "p_ws". +/// +/// @return BACKWARD, FORWARD or zero (for an error). static int get_search_arg(typval_T *varp, int *flagsp) { int dir = FORWARD; @@ -7952,7 +7548,7 @@ static int get_search_arg(typval_T *varp, int *flagsp) return dir; } -// Shared by search() and searchpos() functions. +/// Shared by search() and searchpos() functions. static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { int flags; @@ -7967,6 +7563,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) int options = SEARCH_KEEP; int subpatnum; searchit_arg_T sia; + bool use_skip = false; const char *const pat = tv_get_string(&argvars[0]); dir = get_search_arg(&argvars[1], flagsp); // May set p_ws. @@ -7984,7 +7581,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) options |= SEARCH_COL; } - // Optional arguments: line number to stop searching and timeout. + // Optional arguments: line number to stop searching, timeout and skip. if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { lnum_stop = tv_get_number_chk(&argvars[2], NULL); if (lnum_stop < 0) { @@ -7995,6 +7592,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) if (time_limit < 0) { goto theend; } + use_skip = eval_expr_valid_arg(&argvars[4]); } } @@ -8014,11 +7612,49 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) } pos = save_cursor = curwin->w_cursor; + pos_T firstpos = { 0 }; memset(&sia, 0, sizeof(sia)); sia.sa_stop_lnum = (linenr_T)lnum_stop; sia.sa_tm = &tm; - subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, - options, RE_SEARCH, &sia); + + // Repeat until {skip} returns false. + for (;;) { + subpatnum + = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, options, RE_SEARCH, &sia); + // finding the first match again means there is no match where {skip} + // evaluates to zero. + if (firstpos.lnum != 0 && equalpos(pos, firstpos)) { + subpatnum = FAIL; + } + + if (subpatnum == FAIL || !use_skip) { + // didn't find it or no skip argument + break; + } + firstpos = pos; + + // If the skip expression matches, ignore this match. + { + const pos_T save_pos = curwin->w_cursor; + + curwin->w_cursor = pos; + bool err = false; + const bool do_skip = eval_expr_to_bool(&argvars[4], &err); + curwin->w_cursor = save_pos; + if (err) { + // Evaluating {skip} caused an error, break here. + subpatnum = FAIL; + break; + } + if (!do_skip) { + break; + } + } + + // clear the start flag to avoid getting stuck here + options &= ~SEARCH_START; + } + if (subpatnum != FAIL) { if (flags & SP_SUBPAT) { retval = subpatnum; @@ -8051,7 +7687,7 @@ theend: return retval; } -// "rpcnotify()" function +/// "rpcnotify()" function static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -8086,7 +7722,7 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = 1; } -// "rpcrequest()" function +/// "rpcrequest()" function static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -8114,7 +7750,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } sctx_T save_current_sctx; - uint8_t *save_sourcing_name, *save_autocmd_fname, *save_autocmd_match; + char *save_sourcing_name, *save_autocmd_fname, *save_autocmd_match; linenr_T save_sourcing_lnum; int save_autocmd_bufnr; funccal_entry_T funccal_entry; @@ -8139,13 +7775,13 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) set_current_funccal((funccall_T *)(provider_caller_scope.funccalp)); } - Error err = ERROR_INIT; uint64_t chan_id = (uint64_t)argvars[0].vval.v_number; const char *method = tv_get_string(&argvars[1]); - Object result = rpc_send_call(chan_id, method, args, &err); + ArenaMem res_mem = NULL; + Object result = rpc_send_call(chan_id, method, args, &res_mem, &err); if (l_provider_call_nesting) { current_sctx = save_current_sctx; @@ -8180,11 +7816,11 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, FunPtr fptr) } end: - api_free_object(result); + arena_mem_free(res_mem, NULL); api_clear_error(&err); } -// "rpcstart()" function (DEPRECATED) +/// "rpcstart()" function (DEPRECATED) static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -8228,7 +7864,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) char **argv = xmalloc(sizeof(char_u *) * argvl); // Copy program name - argv[0] = xstrdup((char *)argvars[0].vval.v_string); + argv[0] = xstrdup(argvars[0].vval.v_string); int i = 1; // Copy arguments to the vector @@ -8251,7 +7887,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "rpcstop()" function +/// "rpcstop()" function static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_NUMBER; @@ -8281,54 +7917,57 @@ static void f_rpcstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "screenattr()" function +/// "screenattr()" function static void f_screenattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int c; + ScreenGrid *grid; int row = (int)tv_get_number_chk(&argvars[0], NULL) - 1; int col = (int)tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= default_grid.Rows - || col < 0 || col >= default_grid.Columns) { + + screenchar_adjust(&grid, &row, &col); + + if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - ScreenGrid *grid = &default_grid; - screenchar_adjust_grid(&grid, &row, &col); c = grid->attrs[grid->line_offset[row] + col]; } rettv->vval.v_number = c; } -// "screenchar()" function +/// "screenchar()" function static void f_screenchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int c; + ScreenGrid *grid; int row = tv_get_number_chk(&argvars[0], NULL) - 1; int col = tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= default_grid.Rows - || col < 0 || col >= default_grid.Columns) { + + screenchar_adjust(&grid, &row, &col); + + if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - ScreenGrid *grid = &default_grid; - screenchar_adjust_grid(&grid, &row, &col); - c = utf_ptr2char(grid->chars[grid->line_offset[row] + col]); + c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + col]); } rettv->vval.v_number = c; } -// "screenchars()" function +/// "screenchars()" function static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { + ScreenGrid *grid; int row = tv_get_number_chk(&argvars[0], NULL) - 1; int col = tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= default_grid.Rows - || col < 0 || col >= default_grid.Columns) { + + screenchar_adjust(&grid, &row, &col); + + if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { tv_list_alloc_ret(rettv, 0); return; } - ScreenGrid *grid = &default_grid; - screenchar_adjust_grid(&grid, &row, &col); int pcc[MAX_MCO]; int c = utfc_ptr2char(grid->chars[grid->line_offset[row] + col], pcc); int composing_len = 0; @@ -8342,9 +7981,9 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "screencol()" function -// -// First column is 1 to be consistent with virtcol(). +/// "screencol()" function +/// +/// First column is 1 to be consistent with virtcol(). static void f_screencol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ui_current_col() + 1; @@ -8376,29 +8015,32 @@ static void f_screenpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_nr(dict, S_LEN("endcol"), ecol); } -// "screenrow()" function +/// "screenrow()" function static void f_screenrow(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = ui_current_row() + 1; } -// "screenstring()" function +/// "screenstring()" function static void f_screenstring(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_string = NULL; rettv->v_type = VAR_STRING; + + ScreenGrid *grid; int row = tv_get_number_chk(&argvars[0], NULL) - 1; int col = tv_get_number_chk(&argvars[1], NULL) - 1; - if (row < 0 || row >= default_grid.Rows - || col < 0 || col >= default_grid.Columns) { + + screenchar_adjust(&grid, &row, &col); + + if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { return; } - ScreenGrid *grid = &default_grid; - screenchar_adjust_grid(&grid, &row, &col); - rettv->vval.v_string = vim_strsave(grid->chars[grid->line_offset[row] + col]); + + rettv->vval.v_string = (char *)vim_strsave(grid->chars[grid->line_offset[row] + col]); } -// "search()" function +/// "search()" function static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int flags = 0; @@ -8406,9 +8048,7 @@ static void f_search(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = search_cmn(argvars, NULL, &flags); } -/* - * "searchdecl()" function - */ +/// "searchdecl()" function static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int locally = 1; @@ -8430,9 +8070,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * Used by searchpair() and searchpairpos() - */ +/// Used by searchpair() and searchpairpos() static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) { bool save_p_ws = p_ws; @@ -8478,13 +8116,9 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) || argvars[4].v_type == VAR_UNKNOWN) { skip = NULL; } else { + // Type is checked later. skip = &argvars[4]; - if (skip->v_type != VAR_FUNC - && skip->v_type != VAR_PARTIAL - && skip->v_type != VAR_STRING) { - semsg(_(e_invarg2), tv_get_string(&argvars[4])); - goto theend; // Type error. - } + if (argvars[5].v_type != VAR_UNKNOWN) { lnum_stop = tv_get_number_chk(&argvars[5], NULL); if (lnum_stop < 0) { @@ -8510,17 +8144,13 @@ theend: return retval; } -/* - * "searchpair()" function - */ +/// "searchpair()" function static void f_searchpair(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = searchpair_cmn(argvars, NULL); } -/* - * "searchpairpos()" function - */ +/// "searchpairpos()" function static void f_searchpairpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T match_pos; @@ -8556,7 +8186,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir long time_limit) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { - char_u *save_cpo; + char *save_cpo; char_u *pat, *pat2 = NULL, *pat3 = NULL; long retval = 0; pos_T pos; @@ -8572,7 +8202,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; - p_cpo = empty_option; + p_cpo = (char *)empty_option; // Set the time limit, if there is one. tm = profile_setlimit(time_limit); @@ -8595,10 +8225,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir } if (skip != NULL) { - // Empty string means to not use the skip expression. - if (skip->v_type == VAR_STRING || skip->v_type == VAR_FUNC) { - use_skip = skip->vval.v_string != NULL && *skip->vval.v_string != NUL; - } + use_skip = eval_expr_valid_arg(skip); } save_cursor = curwin->w_cursor; @@ -8699,19 +8326,17 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir xfree(pat2); xfree(pat3); - if (p_cpo == empty_option) { + if ((char_u *)p_cpo == empty_option) { p_cpo = save_cpo; } else { // Darn, evaluating the {skip} expression changed the value. - free_string_option(save_cpo); + free_string_option((char_u *)save_cpo); } return retval; } -/* - * "searchpos()" function - */ +/// "searchpos()" function static void f_searchpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { pos_T match_pos; @@ -8765,7 +8390,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) address = xstrdup(tv_get_string(argvars)); } } else { - address = server_address_new(); + address = server_address_new(NULL); } int result = server_start(address); @@ -8781,7 +8406,7 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "localhost:" will now have a port), return the final value to the user. size_t n; char **addrs = server_address_list(&n); - rettv->vval.v_string = (char_u *)addrs[n - 1]; + rettv->vval.v_string = addrs[n - 1]; n--; for (size_t i = 0; i < n; i++) { @@ -8805,7 +8430,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; if (argvars[0].vval.v_string) { - bool rv = server_stop((char *)argvars[0].vval.v_string); + bool rv = server_stop(argvars[0].vval.v_string); rettv->vval.v_number = (rv ? 1 : 0); } } @@ -8825,9 +8450,7 @@ static void f_setbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "setbufvar()" function - */ +/// "setbufvar()" function static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_secure() @@ -8871,6 +8494,49 @@ static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +/// Set the cursor or mark position. +/// If 'charpos' is TRUE, then use the column number as a character offset. +/// Otherwise use the column number as a byte offset. +static void set_position(typval_T *argvars, typval_T *rettv, bool charpos) +{ + pos_T pos; + int fnum; + colnr_T curswant = -1; + + rettv->vval.v_number = -1; + const char *const name = tv_get_string_chk(argvars); + if (name != NULL) { + if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) == OK) { + if (pos.col != MAXCOL && --pos.col < 0) { + pos.col = 0; + } + if (name[0] == '.' && name[1] == NUL) { + // set cursor; "fnum" is ignored + curwin->w_cursor = pos; + if (curswant >= 0) { + curwin->w_curswant = curswant - 1; + curwin->w_set_curswant = false; + } + check_cursor(); + rettv->vval.v_number = 0; + } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { + // set mark + if (setmark_pos((uint8_t)name[1], &pos, fnum, NULL) == OK) { + rettv->vval.v_number = 0; + } + } else { + emsg(_(e_invarg)); + } + } + } +} + +/// "setcharpos()" function +static void f_setcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + set_position(argvars, rettv, true); +} + static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *d; @@ -8886,7 +8552,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (csearch != NULL) { int pcc[MAX_MCO]; const int c = utfc_ptr2char(csearch, pcc); - set_last_csearch(c, csearch, utfc_ptr2len(csearch)); + set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch)); } di = tv_dict_find(d, S_LEN("forward")); @@ -8901,9 +8567,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "setcmdpos()" function - */ +/// "setcmdpos()" function static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const int pos = (int)tv_get_number(&argvars[0]) - 1; @@ -8913,6 +8577,12 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } +/// "setcursorcharpos" function +static void f_setcursorcharpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + set_cursorpos(argvars, rettv, true); +} + /// "setenv()" function static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -8959,9 +8629,7 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = os_setperm(fname, mode) == OK; } -/* - * "setline()" function - */ +/// "setline()" function static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { linenr_T lnum = tv_get_lnum(&argvars[0]); @@ -8988,7 +8656,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) { static char *e_invact = N_("E927: Invalid action: '%s'"); const char *title = NULL; - int action = ' '; + char action = ' '; static int recursive = 0; rettv->vval.v_number = -1; dict_T *what = NULL; @@ -9043,15 +8711,13 @@ skip_args: recursive++; list_T *const l = list_arg->vval.v_list; - if (set_errorlist(wp, l, action, (char_u *)title, what) == OK) { + if (set_errorlist(wp, l, action, (char *)title, what) == OK) { rettv->vval.v_number = 0; } recursive--; } -/* - * "setloclist()" function - */ +/// "setloclist()" function static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *win; @@ -9064,151 +8730,13 @@ static void f_setloclist(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "setmatches()" function - */ -static void f_setmatches(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - dict_T *d; - list_T *s = NULL; - win_T *win = get_optional_window(argvars, 1); - - rettv->vval.v_number = -1; - if (argvars[0].v_type != VAR_LIST) { - emsg(_(e_listreq)); - return; - } - if (win == NULL) { - return; - } - - list_T *const l = argvars[0].vval.v_list; - // To some extent make sure that we are dealing with a list from - // "getmatches()". - int li_idx = 0; - TV_LIST_ITER_CONST(l, li, { - if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT - || (d = TV_LIST_ITEM_TV(li)->vval.v_dict) == NULL) { - semsg(_("E474: List item %d is either not a dictionary " - "or an empty one"), li_idx); - return; - } - if (!(tv_dict_find(d, S_LEN("group")) != NULL - && (tv_dict_find(d, S_LEN("pattern")) != NULL - || tv_dict_find(d, S_LEN("pos1")) != NULL) - && tv_dict_find(d, S_LEN("priority")) != NULL - && tv_dict_find(d, S_LEN("id")) != NULL)) { - semsg(_("E474: List item %d is missing one of the required keys"), - li_idx); - return; - } - li_idx++; - }); - - clear_matches(win); - bool match_add_failed = false; - TV_LIST_ITER_CONST(l, li, { - int i = 0; - - d = TV_LIST_ITEM_TV(li)->vval.v_dict; - dictitem_T *const di = tv_dict_find(d, S_LEN("pattern")); - if (di == NULL) { - if (s == NULL) { - s = tv_list_alloc(9); - } - - // match from matchaddpos() - for (i = 1; i < 9; i++) { - char buf[30]; // use 30 to avoid compiler warning - snprintf(buf, sizeof(buf), "pos%d", i); - dictitem_T *const pos_di = tv_dict_find(d, buf, -1); - if (pos_di != NULL) { - if (pos_di->di_tv.v_type != VAR_LIST) { - return; - } - - tv_list_append_tv(s, &pos_di->di_tv); - tv_list_ref(s); - } else { - break; - } - } - } - - // Note: there are three number buffers involved: - // - group_buf below. - // - numbuf in tv_dict_get_string(). - // - mybuf in tv_get_string(). - // - // If you change this code make sure that buffers will not get - // accidentally reused. - char group_buf[NUMBUFLEN]; - const char *const group = tv_dict_get_string_buf(d, "group", group_buf); - const int priority = (int)tv_dict_get_number(d, "priority"); - const int id = (int)tv_dict_get_number(d, "id"); - dictitem_T *const conceal_di = tv_dict_find(d, S_LEN("conceal")); - const char *const conceal = (conceal_di != NULL - ? tv_get_string(&conceal_di->di_tv) - : NULL); - if (i == 0) { - if (match_add(win, group, - tv_dict_get_string(d, "pattern", false), - priority, id, NULL, conceal) != id) { - match_add_failed = true; - } - } else { - if (match_add(win, group, NULL, priority, id, s, conceal) != id) { - match_add_failed = true; - } - tv_list_unref(s); - s = NULL; - } - }); - if (!match_add_failed) { - rettv->vval.v_number = 0; - } -} - -/* - * "setpos()" function - */ +/// "setpos()" function static void f_setpos(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - pos_T pos; - int fnum; - colnr_T curswant = -1; - - rettv->vval.v_number = -1; - const char *const name = tv_get_string_chk(argvars); - if (name != NULL) { - if (list2fpos(&argvars[1], &pos, &fnum, &curswant) == OK) { - if (pos.col != MAXCOL && --pos.col < 0) { - pos.col = 0; - } - if (name[0] == '.' && name[1] == NUL) { - // set cursor; "fnum" is ignored - curwin->w_cursor = pos; - if (curswant >= 0) { - curwin->w_curswant = curswant - 1; - curwin->w_set_curswant = false; - } - check_cursor(); - rettv->vval.v_number = 0; - } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { - // set mark - if (setmark_pos((uint8_t)name[1], &pos, fnum) == OK) { - rettv->vval.v_number = 0; - } - } else { - emsg(_(e_invarg)); - } - } - } + set_position(argvars, rettv, false); } -/* - * "setqflist()" function - */ +/// "setqflist()" function static void f_setqflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { set_qf_ll_list(NULL, argvars, rettv); @@ -9244,12 +8772,9 @@ static int get_yank_type(char_u **const pp, MotionType *const yank_type, long *c return OK; } -/* - * "setreg()" function - */ +/// "setreg()" function static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - int regname; bool append = false; MotionType yank_type; long block_len; @@ -9263,13 +8788,13 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (strregname == NULL) { return; // Type error; errmsg already given. } - regname = (uint8_t)(*strregname); + char regname = (uint8_t)(*strregname); if (regname == 0 || regname == '@') { regname = '"'; } const typval_T *regcontents = NULL; - int pointreg = 0; + char pointreg = 0; if (argvars[1].v_type == VAR_DICT) { dict_T *const d = argvars[1].vval.v_dict; @@ -9387,14 +8912,11 @@ free_lstval: if (set_unnamed) { // Discard the result. We already handle the error case. - if (op_reg_set_previous(regname)) { - } + op_reg_set_previous(regname); } } -/* - * "settabvar()" function - */ +/// "settabvar()" function static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; @@ -9425,21 +8947,19 @@ static void f_settabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "settabwinvar()" function - */ +/// "settabwinvar()" function static void f_settabwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { setwinvar(argvars, rettv, 1); } -// "settagstack()" function +/// "settagstack()" function static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { static char *e_invact2 = N_("E962: Invalid action: '%s'"); win_T *wp; dict_T *d; - int action = 'r'; + char action = 'r'; rettv->vval.v_number = -1; @@ -9486,9 +9006,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "setwinvar()" function - */ +/// "setwinvar()" function static void f_setwinvar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { setwinvar(argvars, rettv, 0); @@ -9501,26 +9019,22 @@ static void f_sha256(typval_T *argvars, typval_T *rettv, FunPtr fptr) const char *hash = sha256_bytes((const uint8_t *)p, strlen(p), NULL, 0); // make a copy of the hash (sha256_bytes returns a static buffer) - rettv->vval.v_string = (char_u *)xstrdup(hash); + rettv->vval.v_string = xstrdup(hash); rettv->v_type = VAR_STRING; } -/* - * "shellescape({string})" function - */ +/// "shellescape({string})" function static void f_shellescape(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const bool do_special = non_zero_arg(&argvars[1]); - rettv->vval.v_string = vim_strsave_shellescape((const char_u *)tv_get_string( - &argvars[0]), do_special, - do_special); + rettv->vval.v_string = + (char *)vim_strsave_shellescape((const char_u *)tv_get_string(&argvars[0]), do_special, + do_special); rettv->v_type = VAR_STRING; } -/* - * shiftwidth() function - */ +/// shiftwidth() function static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = 0; @@ -9538,280 +9052,12 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = get_sw_value(curbuf); } -/// "sign_define()" function -static void f_sign_define(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - const char *name; - - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_UNKNOWN) { - // Define multiple signs - tv_list_alloc_ret(rettv, kListLenMayKnow); - - sign_define_multiple(argvars[0].vval.v_list, rettv->vval.v_list); - return; - } - - // Define a single sign - rettv->vval.v_number = -1; - - name = tv_get_string_chk(&argvars[0]); - if (name == NULL) { - return; - } - - if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_DICT) { - emsg(_(e_dictreq)); - return; - } - - rettv->vval.v_number = sign_define_from_dict(name, - argvars[1].v_type == - VAR_DICT ? argvars[1].vval.v_dict : NULL); -} - -/// "sign_getdefined()" function -static void f_sign_getdefined(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - const char *name = NULL; - - tv_list_alloc_ret(rettv, 0); - - if (argvars[0].v_type != VAR_UNKNOWN) { - name = tv_get_string(&argvars[0]); - } - - sign_getlist((const char_u *)name, rettv->vval.v_list); -} - -/// "sign_getplaced()" function -static void f_sign_getplaced(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - buf_T *buf = NULL; - dict_T *dict; - dictitem_T *di; - linenr_T lnum = 0; - int sign_id = 0; - const char *group = NULL; - bool notanum = false; - - tv_list_alloc_ret(rettv, 0); - - if (argvars[0].v_type != VAR_UNKNOWN) { - // get signs placed in the specified buffer - buf = get_buf_arg(&argvars[0]); - if (buf == NULL) { - return; - } - - if (argvars[1].v_type != VAR_UNKNOWN) { - if (argvars[1].v_type != VAR_DICT - || ((dict = argvars[1].vval.v_dict) == NULL)) { - emsg(_(e_dictreq)); - return; - } - if ((di = tv_dict_find(dict, "lnum", -1)) != NULL) { - // get signs placed at this line - lnum = (linenr_T)tv_get_number_chk(&di->di_tv, ¬anum); - if (notanum) { - return; - } - (void)lnum; - lnum = tv_get_lnum(&di->di_tv); - } - if ((di = tv_dict_find(dict, "id", -1)) != NULL) { - // get sign placed with this identifier - sign_id = (int)tv_get_number_chk(&di->di_tv, ¬anum); - if (notanum) { - return; - } - } - if ((di = tv_dict_find(dict, "group", -1)) != NULL) { - group = tv_get_string_chk(&di->di_tv); - if (group == NULL) { - return; - } - if (*group == '\0') { // empty string means global group - group = NULL; - } - } - } - } - - sign_get_placed(buf, lnum, sign_id, (const char_u *)group, - rettv->vval.v_list); -} - -/// "sign_jump()" function -static void f_sign_jump(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - int sign_id; - char *sign_group = NULL; - buf_T *buf; - bool notanum = false; - - rettv->vval.v_number = -1; - - // Sign identifier - sign_id = (int)tv_get_number_chk(&argvars[0], ¬anum); - if (notanum) { - return; - } - if (sign_id <= 0) { - emsg(_(e_invarg)); - return; - } - - // Sign group - const char *sign_group_chk = tv_get_string_chk(&argvars[1]); - if (sign_group_chk == NULL) { - return; - } - if (sign_group_chk[0] == '\0') { - sign_group = NULL; // global sign group - } else { - sign_group = xstrdup(sign_group_chk); - } - - // Buffer to place the sign - buf = get_buf_arg(&argvars[2]); - if (buf == NULL) { - goto cleanup; - } - - rettv->vval.v_number = sign_jump(sign_id, (char_u *)sign_group, buf); - -cleanup: - xfree(sign_group); -} - -/// "sign_place()" function -static void f_sign_place(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - dict_T *dict = NULL; - - rettv->vval.v_number = -1; - - if (argvars[4].v_type != VAR_UNKNOWN - && (argvars[4].v_type != VAR_DICT - || ((dict = argvars[4].vval.v_dict) == NULL))) { - emsg(_(e_dictreq)); - return; - } - - rettv->vval.v_number = sign_place_from_dict(&argvars[0], &argvars[1], &argvars[2], &argvars[3], - dict); -} - -/// "sign_placelist()" function. Place multiple signs. -static void f_sign_placelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - int sign_id; - - tv_list_alloc_ret(rettv, kListLenMayKnow); - - if (argvars[0].v_type != VAR_LIST) { - emsg(_(e_listreq)); - return; - } - - // Process the List of sign attributes - TV_LIST_ITER_CONST(argvars[0].vval.v_list, li, { - sign_id = -1; - if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { - sign_id = sign_place_from_dict(NULL, NULL, NULL, NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); - } else { - emsg(_(e_dictreq)); - } - tv_list_append_number(rettv->vval.v_list, sign_id); - }); -} - -/// "sign_undefine()" function -static void f_sign_undefine(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - const char *name; - - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_UNKNOWN) { - // Undefine multiple signs - tv_list_alloc_ret(rettv, kListLenMayKnow); - - sign_undefine_multiple(argvars[0].vval.v_list, rettv->vval.v_list); - return; - } - - rettv->vval.v_number = -1; - - if (argvars[0].v_type == VAR_UNKNOWN) { - // Free all the signs - free_signs(); - rettv->vval.v_number = 0; - } else { - // Free only the specified sign - name = tv_get_string_chk(&argvars[0]); - if (name == NULL) { - return; - } - - if (sign_undefine_by_name((const char_u *)name) == OK) { - rettv->vval.v_number = 0; - } - } -} - -/// "sign_unplace()" function -static void f_sign_unplace(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - dict_T *dict = NULL; - - rettv->vval.v_number = -1; - - if (argvars[0].v_type != VAR_STRING) { - emsg(_(e_invarg)); - return; - } - - if (argvars[1].v_type != VAR_UNKNOWN) { - if (argvars[1].v_type != VAR_DICT) { - emsg(_(e_dictreq)); - return; - } - dict = argvars[1].vval.v_dict; - } - - rettv->vval.v_number = sign_unplace_from_dict(&argvars[0], dict); -} - -/// "sign_unplacelist()" function -static void f_sign_unplacelist(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - int retval; - - tv_list_alloc_ret(rettv, kListLenMayKnow); - - if (argvars[0].v_type != VAR_LIST) { - emsg(_(e_listreq)); - return; - } - - TV_LIST_ITER_CONST(argvars[0].vval.v_list, li, { - retval = -1; - if (TV_LIST_ITEM_TV(li)->v_type == VAR_DICT) { - retval = sign_unplace_from_dict(NULL, TV_LIST_ITEM_TV(li)->vval.v_dict); - } else { - emsg(_(e_dictreq)); - } - tv_list_append_number(rettv->vval.v_list, retval); - }); -} - -/* - * "simplify()" function - */ +/// "simplify()" function static void f_simplify(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const p = tv_get_string(&argvars[0]); - rettv->vval.v_string = (char_u *)xstrdup(p); - simplify_filename(rettv->vval.v_string); // Simplify in place. + rettv->vval.v_string = xstrdup(p); + simplify_filename((char_u *)rettv->vval.v_string); // Simplify in place. rettv->v_type = VAR_STRING; } @@ -9883,9 +9129,7 @@ static sortinfo_T *sortinfo = NULL; #define ITEM_COMPARE_FAIL 999 -/* - * Compare functions for f_sort() and f_uniq() below. - */ +/// Compare functions for f_sort() and f_uniq() below. static int item_compare(const void *s1, const void *s2, bool keep_zero) { ListSortItem *const si1 = (ListSortItem *)s1; @@ -9924,7 +9168,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) if (tv2->v_type != VAR_STRING || sortinfo->item_compare_numeric) { p1 = "'"; } else { - p1 = (char *)tv1->vval.v_string; + p1 = tv1->vval.v_string; } } else { tofree1 = p1 = encode_tv2string(tv1, NULL); @@ -9933,7 +9177,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) if (tv1->v_type != VAR_STRING || sortinfo->item_compare_numeric) { p2 = "'"; } else { - p2 = (char *)tv2->vval.v_string; + p2 = tv2->vval.v_string; } } else { tofree2 = p2 = encode_tv2string(tv2, NULL); @@ -10014,7 +9258,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) funcexe.evaluate = true; funcexe.partial = partial; funcexe.selfdict = sortinfo->item_compare_selfdict; - res = call_func((const char_u *)func_name, -1, &rettv, 2, argv, &funcexe); + res = call_func(func_name, -1, &rettv, 2, argv, &funcexe); tv_clear(&argv[0]); tv_clear(&argv[1]); @@ -10022,6 +9266,11 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) res = ITEM_COMPARE_FAIL; } else { res = tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err); + if (res > 0) { + res = 1; + } else if (res < 0) { + res = -1; + } } if (sortinfo->item_compare_func_err) { res = ITEM_COMPARE_FAIL; // return value has wrong type @@ -10049,9 +9298,7 @@ static int item_compare2_not_keeping_zero(const void *s1, const void *s2) return item_compare2(s1, s2, false); } -/* - * "sort({list})" function - */ +/// "sort({list})" function static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) { ListSortItem *ptrs; @@ -10209,7 +9456,6 @@ static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - bool rpc = false; CallbackReader on_stdin = CALLBACK_READER_INIT; dict_T *opts = argvars[0].vval.v_dict; @@ -10218,6 +9464,10 @@ static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!tv_dict_get_callback(opts, S_LEN("on_stdin"), &on_stdin.cb)) { return; } + if (!tv_dict_get_callback(opts, S_LEN("on_print"), &on_print)) { + return; + } + on_stdin.buffered = tv_dict_get_number(opts, "stdin_buffered"); if (on_stdin.buffered && on_stdin.cb.type == kCallbackNone) { on_stdin.self = opts; @@ -10229,7 +9479,6 @@ static void f_stdioopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) semsg(e_stdiochan2, error); } - rettv->vval.v_number = (varnumber_T)id; rettv->v_type = VAR_NUMBER; } @@ -10240,7 +9489,7 @@ static void f_uniq(typval_T *argvars, typval_T *rettv, FunPtr fptr) do_sort_uniq(argvars, rettv, false); } -// "reltimefloat()" function +/// "reltimefloat()" function static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr) FUNC_ATTR_NONNULL_ALL { @@ -10253,19 +9502,15 @@ static void f_reltimefloat(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "soundfold({word})" function - */ +/// "soundfold({word})" function static void f_soundfold(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; const char *const s = tv_get_string(&argvars[0]); - rettv->vval.v_string = (char_u *)eval_soundfold(s); + rettv->vval.v_string = eval_soundfold(s); } -/* - * "spellbadword()" function - */ +/// "spellbadword()" function static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *word = ""; @@ -10324,9 +9569,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, FunPtr fptr) NULL), -1); } -/* - * "spellsuggest()" function - */ +/// "spellsuggest()" function static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool typeerr = false; @@ -10346,26 +9589,24 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, FunPtr fptr) return; } - if (*curwin->w_s->b_p_spl != NUL) { - const char *const str = tv_get_string(&argvars[0]); - if (argvars[1].v_type != VAR_UNKNOWN) { - maxcount = tv_get_number_chk(&argvars[1], &typeerr); - if (maxcount <= 0) { + const char *const str = tv_get_string(&argvars[0]); + if (argvars[1].v_type != VAR_UNKNOWN) { + maxcount = tv_get_number_chk(&argvars[1], &typeerr); + if (maxcount <= 0) { + goto f_spellsuggest_return; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + need_capital = tv_get_number_chk(&argvars[2], &typeerr); + if (typeerr) { goto f_spellsuggest_return; } - if (argvars[2].v_type != VAR_UNKNOWN) { - need_capital = tv_get_number_chk(&argvars[2], &typeerr); - if (typeerr) { - goto f_spellsuggest_return; - } - } - } else { - maxcount = 25; } - - spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false); + } else { + maxcount = 25; } + spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false); + f_spellsuggest_return: tv_list_alloc_ret(rettv, (ptrdiff_t)ga.ga_len); for (int i = 0; i < ga.ga_len; i++) { @@ -10378,7 +9619,7 @@ f_spellsuggest_return: static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *save_cpo; + char *save_cpo; int match; colnr_T col = 0; bool keepempty = false; @@ -10386,7 +9627,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) // Make 'cpoptions' empty, the 'l' flag should not be used here. save_cpo = p_cpo; - p_cpo = (char_u *)""; + p_cpo = ""; const char *str = tv_get_string(&argvars[0]); const char *pat = NULL; @@ -10411,7 +9652,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) } regmatch_T regmatch = { - .regprog = vim_regcomp((char_u *)pat, RE_MAGIC + RE_STRING), + .regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING), .startp = { NULL }, .endp = { NULL }, .rm_ic = false, @@ -10443,7 +9684,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, FunPtr fptr) col = 0; } else { // Don't get stuck at the same match. - col = utfc_ptr2len(regmatch.endp[0]); + col = utfc_ptr2len((char *)regmatch.endp[0]); } str = (const char *)regmatch.endp[0]; } @@ -10467,11 +9708,17 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) } if (strequal(p, "config")) { - rettv->vval.v_string = (char_u *)get_xdg_home(kXDGConfigHome); + rettv->vval.v_string = get_xdg_home(kXDGConfigHome); } else if (strequal(p, "data")) { - rettv->vval.v_string = (char_u *)get_xdg_home(kXDGDataHome); + rettv->vval.v_string = get_xdg_home(kXDGDataHome); } else if (strequal(p, "cache")) { - rettv->vval.v_string = (char_u *)get_xdg_home(kXDGCacheHome); + rettv->vval.v_string = get_xdg_home(kXDGCacheHome); + } else if (strequal(p, "state")) { + rettv->vval.v_string = get_xdg_home(kXDGStateHome); + } else if (strequal(p, "log")) { + rettv->vval.v_string = get_xdg_home(kXDGStateHome); + } else if (strequal(p, "run")) { + rettv->vval.v_string = stdpaths_get_xdg_var(kXDGRuntimeDir); } else if (strequal(p, "config_dirs")) { get_xdg_var_list(kXDGConfigDirs, rettv); } else if (strequal(p, "data_dirs")) { @@ -10481,36 +9728,34 @@ static void f_stdpath(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "str2float()" function - */ +/// "str2float()" function static void f_str2float(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + char *p = skipwhite(tv_get_string(&argvars[0])); bool isneg = (*p == '-'); if (*p == '+' || *p == '-') { p = skipwhite(p + 1); } - (void)string2float((char *)p, &rettv->vval.v_float); + (void)string2float(p, &rettv->vval.v_float); if (isneg) { rettv->vval.v_float *= -1; } rettv->v_type = VAR_FLOAT; } -// "str2list()" function +/// "str2list()" function static void f_str2list(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_alloc_ret(rettv, kListLenUnknown); const char_u *p = (const char_u *)tv_get_string(&argvars[0]); - for (; *p != NUL; p += utf_ptr2len(p)) { - tv_list_append_number(rettv->vval.v_list, utf_ptr2char(p)); + for (; *p != NUL; p += utf_ptr2len((char *)p)) { + tv_list_append_number(rettv->vval.v_list, utf_ptr2char((char *)p)); } } -// "str2nr()" function +/// "str2nr()" function static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int base = 10; @@ -10528,10 +9773,10 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } - char_u *p = skipwhite((const char_u *)tv_get_string(&argvars[0])); + char_u *p = (char_u *)skipwhite(tv_get_string(&argvars[0])); bool isneg = (*p == '-'); if (*p == '+' || *p == '-') { - p = skipwhite(p + 1); + p = (char_u *)skipwhite((char *)p + 1); } switch (base) { case 2: @@ -10553,9 +9798,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "strftime({format}[, {time}])" function - */ +/// "strftime({format}[, {time}])" function static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { time_t seconds; @@ -10573,7 +9816,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) struct tm *curtime_ptr = os_localtime_r(&seconds, &curtime); // MSVC returns NULL for an invalid value of seconds. if (curtime_ptr == NULL) { - rettv->vval.v_string = vim_strsave((char_u *)_("(Invalid)")); + rettv->vval.v_string = xstrdup(_("(Invalid)")); } else { vimconv_T conv; char_u *enc; @@ -10596,9 +9839,9 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } convert_setup(&conv, enc, p_enc); if (conv.vc_type != CONV_NONE) { - rettv->vval.v_string = string_convert(&conv, (char_u *)result_buf, NULL); + rettv->vval.v_string = (char *)string_convert(&conv, (char_u *)result_buf, NULL); } else { - rettv->vval.v_string = (char_u *)xstrdup(result_buf); + rettv->vval.v_string = xstrdup(result_buf); } // Release conversion descriptors. @@ -10607,7 +9850,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "strgetchar()" function +/// "strgetchar()" function static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -10627,17 +9870,15 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) while (charidx >= 0 && byteidx < len) { if (charidx == 0) { - rettv->vval.v_number = utf_ptr2char((const char_u *)str + byteidx); + rettv->vval.v_number = utf_ptr2char(str + byteidx); break; } charidx--; - byteidx += utf_ptr2len((const char_u *)str + byteidx); + byteidx += utf_ptr2len(str + byteidx); } } -/* - * "stridx()" function - */ +/// "stridx()" function static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = -1; @@ -10669,26 +9910,20 @@ static void f_stridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "string()" function - */ -void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr) +/// "string()" function +static void f_string(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)encode_tv2string(&argvars[0], NULL); + rettv->vval.v_string = encode_tv2string(&argvars[0], NULL); } -/* - * "strlen()" function - */ +/// "strlen()" function static void f_strlen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); } -/* - * "strchars()" function - */ +/// "strchars()" function static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *s = tv_get_string(&argvars[0]); @@ -10711,9 +9946,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "strdisplaywidth()" function - */ +/// "strdisplaywidth()" function static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const s = tv_get_string(&argvars[0]); @@ -10726,17 +9959,15 @@ static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char_u *)s) - col); } -/* - * "strwidth()" function - */ +/// "strwidth()" function static void f_strwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const s = tv_get_string(&argvars[0]); - rettv->vval.v_number = (varnumber_T)mb_string2cells((const char_u *)s); + rettv->vval.v_number = (varnumber_T)mb_string2cells(s); } -// "strcharpart()" function +/// "strcharpart()" function static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const p = tv_get_string(&argvars[0]); @@ -10748,7 +9979,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (!error) { if (nchar > 0) { while (nchar > 0 && (size_t)nbyte < slen) { - nbyte += utf_ptr2len((const char_u *)p + nbyte); + nbyte += utf_ptr2len(p + nbyte); nchar--; } } else { @@ -10764,7 +9995,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (off < 0) { len += 1; } else { - len += utf_ptr2len((const char_u *)p + off); + len += utf_ptr2len(p + off); } charlen--; } @@ -10787,12 +10018,10 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) } rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)xstrndup(p + nbyte, (size_t)len); + rettv->vval.v_string = xstrndup(p + nbyte, (size_t)len); } -/* - * "strpart()" function - */ +/// "strpart()" function static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool error = false; @@ -10829,16 +10058,16 @@ static void f_strpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) // length in characters for (off = n; off < (int)slen && len > 0; len--) { - off += utfc_ptr2len((char_u *)p + off); + off += utfc_ptr2len(p + off); } len = off - n; } rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)xmemdupz(p + n, (size_t)len); + rettv->vval.v_string = xmemdupz(p + n, (size_t)len); } -// "strptime({format}, {timestring})" function +/// "strptime({format}, {timestring})" function static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char fmt_buf[NUMBUFLEN]; @@ -10870,9 +10099,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(enc); } -/* - * "strridx()" function - */ +/// "strridx()" function static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf[NUMBUFLEN]; @@ -10915,18 +10142,14 @@ static void f_strridx(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "strtrans()" function - */ +/// "strtrans()" function static void f_strtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)transstr(tv_get_string(&argvars[0]), true); + rettv->vval.v_string = transstr(tv_get_string(&argvars[0]), true); } -/* - * "submatch()" function - */ +/// "submatch()" function static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) { bool error = false; @@ -10950,16 +10173,14 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (retList == 0) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = reg_submatch(no); + rettv->vval.v_string = (char *)reg_submatch(no); } else { rettv->v_type = VAR_LIST; rettv->vval.v_list = reg_submatch_list(no); } } -/* - * "substitute()" function - */ +/// "substitute()" function static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char patbuf[NUMBUFLEN]; @@ -10983,8 +10204,8 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, FunPtr fptr) || flg == NULL) { rettv->vval.v_string = NULL; } else { - rettv->vval.v_string = do_string_sub((char_u *)str, (char_u *)pat, - (char_u *)sub, expr, (char_u *)flg); + rettv->vval.v_string = do_string_sub((char *)str, (char *)pat, + (char *)sub, expr, (char *)flg); } } @@ -11005,7 +10226,7 @@ static void f_swapname(typval_T *argvars, typval_T *rettv, FunPtr fptr) || buf->b_ml.ml_mfp->mf_fname == NULL) { rettv->vval.v_string = NULL; } else { - rettv->vval.v_string = vim_strsave(buf->b_ml.ml_mfp->mf_fname); + rettv->vval.v_string = (char *)vim_strsave(buf->b_ml.ml_mfp->mf_fname); } } @@ -11028,9 +10249,7 @@ static void f_synID(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = id; } -/* - * "synIDattr(id, what [, mode])" function - */ +/// "synIDattr(id, what [, mode])" function static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const int id = (int)tv_get_number(&argvars[0]); @@ -11049,7 +10268,6 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) modec = 'c'; } - const char *p = NULL; switch (TOLOWER_ASC(what[0])) { case 'b': @@ -11086,21 +10304,35 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } break; case 'u': - if (STRLEN(what) <= 5 || TOLOWER_ASC(what[5]) != 'c') { // underline - p = highlight_has_attr(id, HL_UNDERLINE, modec); - } else { // undercurl - p = highlight_has_attr(id, HL_UNDERCURL, modec); + if (STRLEN(what) >= 9) { + if (TOLOWER_ASC(what[5]) == 'l') { + // underline + p = highlight_has_attr(id, HL_UNDERLINE, modec); + } else if (TOLOWER_ASC(what[5]) != 'd') { + // undercurl + p = highlight_has_attr(id, HL_UNDERCURL, modec); + } else if (TOLOWER_ASC(what[6]) != 'o') { + // underdashed + p = highlight_has_attr(id, HL_UNDERDASHED, modec); + } else if (TOLOWER_ASC(what[7]) == 'u') { + // underdouble + p = highlight_has_attr(id, HL_UNDERDOUBLE, modec); + } else { + // underdotted + p = highlight_has_attr(id, HL_UNDERDOTTED, modec); + } + } else { + // ul + p = highlight_color(id, what, modec); } break; } rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)(p == NULL ? p : xstrdup(p)); + rettv->vval.v_string = (char *)(p == NULL ? p : xstrdup(p)); } -/* - * "synIDtrans(id)" function - */ +/// "synIDtrans(id)" function static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int id = tv_get_number(&argvars[0]); @@ -11114,9 +10346,7 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = id; } -/* - * "synconcealed(lnum, col)" function - */ +/// "synconcealed(lnum, col)" function static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int syntax_flags = 0; @@ -11146,7 +10376,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) : curwin->w_p_lcs_chars.conceal; } if (cchar != NUL) { - utf_char2bytes(cchar, str); + utf_char2bytes(cchar, (char *)str); } } } @@ -11158,9 +10388,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_list_append_number(rettv->vval.v_list, matchid); } -/* - * "synstack(lnum, col)" function - */ +/// "synstack(lnum, col)" function static void f_synstack(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_list_set_ret(rettv, NULL); @@ -11195,10 +10423,7 @@ static void f_systemlist(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_system_output_as_rettv(argvars, rettv, true); } - -/* - * "tabpagebuflist()" function - */ +/// "tabpagebuflist()" function static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { win_T *wp = NULL; @@ -11220,9 +10445,7 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "tabpagenr()" function - */ +/// "tabpagenr()" function static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; @@ -11234,9 +10457,7 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (strcmp(arg, "$") == 0) { nr = tabpage_index(NULL) - 1; } else if (strcmp(arg, "#") == 0) { - nr = valid_tabpage(lastused_tabpage) - ? tabpage_index(lastused_tabpage) - : nr; + nr = valid_tabpage(lastused_tabpage) ? tabpage_index(lastused_tabpage) : 0; } else { semsg(_(e_invexpr2), arg); } @@ -11247,10 +10468,7 @@ static void f_tabpagenr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = nr; } - -/* - * Common code for tabpagewinnr() and winnr(). - */ +/// Common code for tabpagewinnr() and winnr(). static int get_winnr(tabpage_T *tp, typval_T *argvar) { win_T *twin; @@ -11315,9 +10533,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) return nr; } -/* - * "tabpagewinnr()" function - */ +/// "tabpagewinnr()" function static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; @@ -11330,9 +10546,7 @@ static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = nr; } -/* - * "tagfiles()" function - */ +/// "tagfiles()" function static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char *fname; @@ -11351,9 +10565,7 @@ static void f_tagfiles(typval_T *argvars, typval_T *rettv, FunPtr fptr) xfree(fname); } -/* - * "taglist()" function - */ +/// "taglist()" function static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) { const char *const tag_pattern = tv_get_string(&argvars[0]); @@ -11371,16 +10583,14 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, FunPtr fptr) (char_u *)tag_pattern, (char_u *)fname); } -/* - * "tempname()" function - */ +/// "tempname()" function static void f_tempname(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = vim_tempname(); + rettv->vval.v_string = (char *)vim_tempname(); } -// "termopen(cmd[, cwd])" function +/// "termopen(cmd[, cwd])" function static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (check_secure()) { @@ -11466,19 +10676,25 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) // "./…" => "/home/foo/…" vim_FullName(cwd, (char *)NameBuff, sizeof(NameBuff), false); // "/home/foo/…" => "~/…" - size_t len = home_replace(NULL, NameBuff, IObuff, sizeof(IObuff), true); + size_t len = home_replace(NULL, (char *)NameBuff, (char *)IObuff, sizeof(IObuff), true); // Trim slash. - if (IObuff[len - 1] == '\\' || IObuff[len - 1] == '/') { + if (len != 1 && (IObuff[len - 1] == '\\' || IObuff[len - 1] == '/')) { IObuff[len - 1] = '\0'; } + if (len == 1 && IObuff[0] == '/') { + // Avoid ambiguity in the URI when CWD is root directory. + IObuff[1] = '.'; + IObuff[2] = '\0'; + } + // Terminal URI: "term://$CWD//$PID:$CMD" snprintf((char *)NameBuff, sizeof(NameBuff), "term://%s//%d:%s", (char *)IObuff, pid, cmd); // at this point the buffer has no terminal instance associated yet, so unset // the 'swapfile' option to ensure no swap file will be created curbuf->b_p_swf = false; - (void)setfname(curbuf, NameBuff, NULL, true); + (void)setfname(curbuf, (char *)NameBuff, NULL, true); // Save the job id and pid in b:terminal_job_{id,pid} Error err = ERROR_INIT; // deprecated: use 'channel' buffer option @@ -11493,24 +10709,6 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr) channel_create_event(chan, NULL); } -// "test_garbagecollect_now()" function -static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr) -{ - // This is dangerous, any Lists and Dicts used internally may be freed - // while still in use. - garbage_collect(true); -} - -// "test_write_list_log()" function -static void f_test_write_list_log(typval_T *const argvars, typval_T *const rettv, FunPtr fptr) -{ - const char *const fname = tv_get_string_chk(&argvars[0]); - if (fname == NULL) { - return; - } - list_write_log(fname); -} - /// "timer_info([timer])" function static void f_timer_info(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -11583,8 +10781,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr) timer_start(tv_get_number(&argvars[0]), repeat, &callback); } - -// "timer_stop(timerid)" function +/// "timer_stop(timerid)" function static void f_timer_stop(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (argvars[0].v_type != VAR_NUMBER) { @@ -11605,29 +10802,21 @@ static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr) timer_stop_all(); } -/* - * "tolower(string)" function - */ +/// "tolower(string)" function static void f_tolower(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), - false); + rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), false); } -/* - * "toupper(string)" function - */ +/// "toupper(string)" function static void f_toupper(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)strcase_save(tv_get_string(&argvars[0]), - true); + rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), true); } -/* - * "tr(string, fromstr, tostr)" function - */ +/// "tr(string, fromstr, tostr)" function static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf[NUMBUFLEN]; @@ -11650,16 +10839,16 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) bool first = true; while (*in_str != NUL) { const char *cpstr = in_str; - const int inlen = utfc_ptr2len((const char_u *)in_str); + const int inlen = utfc_ptr2len(in_str); int cplen = inlen; int idx = 0; int fromlen; for (const char *p = fromstr; *p != NUL; p += fromlen) { - fromlen = utfc_ptr2len((const char_u *)p); + fromlen = utfc_ptr2len(p); if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { int tolen; for (p = tostr; *p != NUL; p += tolen) { - tolen = utfc_ptr2len((const char_u *)p); + tolen = utfc_ptr2len(p); if (idx-- == 0) { cplen = tolen; cpstr = (char *)p; @@ -11681,7 +10870,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) first = false; int tolen; for (const char *p = tostr; *p != NUL; p += tolen) { - tolen = utfc_ptr2len((const char_u *)p); + tolen = utfc_ptr2len(p); idx--; } if (idx != 0) { @@ -11704,10 +10893,9 @@ static void f_tr(typval_T *argvars, typval_T *rettv, FunPtr fptr) error: semsg(_(e_invarg2), fromstr); ga_clear(&ga); - return; } -// "trim({expr})" function +/// "trim({expr})" function static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char buf1[NUMBUFLEN]; @@ -11745,14 +10933,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (dir == 0 || dir == 1) { // Trim leading characters while (*head != NUL) { - c1 = utf_ptr2char(head); + c1 = utf_ptr2char((char *)head); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char(p)) { + if (c1 == utf_ptr2char((char *)p)) { break; } } @@ -11770,14 +10958,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) for (; tail > head; tail = prev) { prev = tail; MB_PTR_BACK(head, prev); - c1 = utf_ptr2char(prev); + c1 = utf_ptr2char((char *)prev); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char(p)) { + if (c1 == utf_ptr2char((char *)p)) { break; } } @@ -11787,12 +10975,10 @@ static void f_trim(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } - rettv->vval.v_string = vim_strnsave(head, tail - head); + rettv->vval.v_string = (char *)vim_strnsave(head, tail - head); } -/* - * "type(expr)" function - */ +/// "type(expr)" function static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int n = -1; @@ -11824,9 +11010,7 @@ static void f_type(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = n; } -/* - * "undofile(name)" function - */ +/// "undofile(name)" function static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; @@ -11839,15 +11023,13 @@ static void f_undofile(typval_T *argvars, typval_T *rettv, FunPtr fptr) char *ffname = FullName_save(fname, true); if (ffname != NULL) { - rettv->vval.v_string = (char_u *)u_get_undo_file_name(ffname, false); + rettv->vval.v_string = u_get_undo_file_name(ffname, false); } xfree(ffname); } } -/* - * "undotree()" function - */ +/// "undotree()" function static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tv_dict_alloc_ret(rettv); @@ -11865,24 +11047,20 @@ static void f_undotree(typval_T *argvars, typval_T *rettv, FunPtr fptr) tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead)); } -/* - * "values(dict)" function - */ +/// "values(dict)" function static void f_values(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_list(argvars, rettv, 1); } -/* - * "virtcol(string)" function - */ +/// "virtcol(string)" function static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { colnr_T vcol = 0; pos_T *fp; int fnum = curbuf->b_fnum; - fp = var2fpos(&argvars[0], FALSE, &fnum); + fp = var2fpos(&argvars[0], false, &fnum, false); if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count && fnum == curbuf->b_fnum) { // Limit the column to a valid value, getvvcol() doesn't check. @@ -11901,9 +11079,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = vcol; } -/* - * "visualmode()" function - */ +/// "visualmode()" function static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { char_u str[2]; @@ -11911,7 +11087,7 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; str[0] = curbuf->b_visual_mode_eval; str[1] = NUL; - rettv->vval.v_string = vim_strsave(str); + rettv->vval.v_string = (char *)vim_strsave(str); // A non-zero number or non-empty string argument: reset mode. if (non_zero_arg(&argvars[0])) { @@ -11919,12 +11095,10 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "wildmenumode()" function - */ +/// "wildmenumode()" function static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr) { - if (wild_menu_showing || ((State & CMDLINE) && pum_visible())) { + if (wild_menu_showing || ((State & MODE_CMDLINE) && pum_visible())) { rettv->vval.v_number = 1; } } @@ -11952,21 +11126,20 @@ static void f_win_gettype(typval_T *argvars, typval_T *rettv, FunPtr fptr) if (argvars[0].v_type != VAR_UNKNOWN) { wp = find_win_by_nr_or_id(&argvars[0]); if (wp == NULL) { - rettv->vval.v_string = vim_strsave((char_u *)"unknown"); + rettv->vval.v_string = (char *)vim_strsave((char_u *)"unknown"); return; } } if (wp == aucmd_win) { - rettv->vval.v_string = vim_strsave((char_u *)"autocmd"); + rettv->vval.v_string = xstrdup("autocmd"); } else if (wp->w_p_pvw) { - rettv->vval.v_string = vim_strsave((char_u *)"preview"); + rettv->vval.v_string = xstrdup("preview"); } else if (wp->w_floating) { - rettv->vval.v_string = vim_strsave((char_u *)"popup"); + rettv->vval.v_string = xstrdup("popup"); } else if (wp == curwin && cmdwin_type != 0) { - rettv->vval.v_string = vim_strsave((char_u *)"command"); + rettv->vval.v_string = xstrdup("command"); } else if (bt_quickfix(wp->w_buffer)) { - rettv->vval.v_string = vim_strsave((char_u *)(wp->w_llist_ref != NULL ? - "loclist" : "quickfix")); + rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix")); } } @@ -11988,6 +11161,42 @@ static void f_win_id2win(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = win_id2win(argvars); } +/// "win_move_separator()" function +static void f_win_move_separator(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp; + int offset; + + rettv->vval.v_number = false; + + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || wp->w_floating) { + return; + } + + offset = (int)tv_get_number(&argvars[1]); + win_drag_vsep_line(wp, offset); + rettv->vval.v_number = true; +} + +/// "win_move_statusline()" function +static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, FunPtr fptr) +{ + win_T *wp; + int offset; + + rettv->vval.v_number = false; + + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || wp->w_floating) { + return; + } + + offset = (int)tv_get_number(&argvars[1]); + win_drag_status_line(wp, offset); + rettv->vval.v_number = true; +} + /// "winbufnr(nr)" function static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { @@ -11999,9 +11208,7 @@ static void f_winbufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "wincol()" function - */ +/// "wincol()" function static void f_wincol(typval_T *argvars, typval_T *rettv, FunPtr fptr) { validate_cursor(); @@ -12019,7 +11226,7 @@ static void f_winheight(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "winlayout()" function +/// "winlayout()" function static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr) { tabpage_T *tp; @@ -12038,18 +11245,14 @@ static void f_winlayout(typval_T *argvars, typval_T *rettv, FunPtr fptr) get_framelayout(tp->tp_topframe, rettv->vval.v_list, true); } -/* - * "winline()" function - */ +/// "winline()" function static void f_winline(typval_T *argvars, typval_T *rettv, FunPtr fptr) { validate_cursor(); rettv->vval.v_number = curwin->w_wrow + 1; } -/* - * "winnr()" function - */ +/// "winnr()" function static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) { int nr = 1; @@ -12058,9 +11261,7 @@ static void f_winnr(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->vval.v_number = nr; } -/* - * "winrestcmd()" function - */ +/// "winrestcmd()" function static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) { garray_T ga; @@ -12087,9 +11288,7 @@ static void f_winrestcmd(typval_T *argvars, typval_T *rettv, FunPtr fptr) rettv->v_type = VAR_STRING; } -/* - * "winrestview()" function - */ +/// "winrestview()" function static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; @@ -12140,9 +11339,7 @@ static void f_winrestview(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -/* - * "winsaveview()" function - */ +/// "winsaveview()" function static void f_winsaveview(typval_T *argvars, typval_T *rettv, FunPtr fptr) { dict_T *dict; @@ -12173,11 +11370,11 @@ static void f_winwidth(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } -// "windowsversion()" function +/// "windowsversion()" function static void f_windowsversion(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char_u *)xstrdup(windowsVersion); + rettv->vval.v_string = xstrdup(windowsVersion); } /// "wordcount()" function @@ -12264,9 +11461,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, FunPtr fptr) } } } -/* - * "xor(expr, expr)" function - */ + +/// "xor(expr, expr)" function static void f_xor(typval_T *argvars, typval_T *rettv, FunPtr fptr) { rettv->vval.v_number = tv_get_number_chk(&argvars[0], NULL) diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index c6a0cb959e..5f8d81c989 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -9,19 +9,20 @@ typedef void (*FunPtr)(void); /// Prototype of C function that implements VimL function typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, FunPtr data); -/// Special flags for base_arg @see VimLFuncDef +/// Special flags for base_arg @see EvalFuncDef #define BASE_NONE 0 ///< Not a method (no base argument). #define BASE_LAST UINT8_MAX ///< Use the last argument as the method base. /// Structure holding VimL function definition -typedef struct fst { +typedef struct { char *name; ///< Name of the function. uint8_t min_argc; ///< Minimal number of arguments. uint8_t max_argc; ///< Maximal number of arguments. uint8_t base_arg; ///< Method base arg # (1-indexed), BASE_NONE or BASE_LAST. + bool fast; ///< Can be run in |api-fast| events VimLFunc func; ///< Function implementation. FunPtr data; ///< Userdata for function implementation. -} VimLFuncDef; +} EvalFuncDef; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/funcs.h.generated.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 42ac1839e6..e19cf411c0 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -8,6 +8,7 @@ #include <stdlib.h> #include <string.h> +#include "lauxlib.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/charset.h" @@ -28,11 +29,11 @@ #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/os/fileio.h" #include "nvim/os/input.h" #include "nvim/pos.h" #include "nvim/types.h" #include "nvim/vim.h" -#include "nvim/os/fileio.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/typval.c.generated.h" @@ -564,7 +565,7 @@ void tv_list_append_allocated_string(list_T *const l, char *const str) tv_list_append_owned_tv(l, (typval_T) { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = (char_u *)str, + .vval.v_string = str, }); } @@ -878,9 +879,9 @@ void tv_list_reverse(list_T *const l) list_log(l, NULL, NULL, "reverse"); #define SWAP(a, b) \ do { \ - tmp = a; \ - a = b; \ - b = tmp; \ + tmp = (a); \ + (a) = (b); \ + (b) = tmp; \ } while (0) listitem_T *tmp; @@ -1123,6 +1124,8 @@ bool tv_callback_equal(const Callback *cb1, const Callback *cb2) // FIXME: this is inconsistent with tv_equal but is needed for precision // maybe change dictwatcheradd to return a watcher id instead? return cb1->data.partial == cb2->data.partial; + case kCallbackLua: + return cb1->data.luaref == cb2->data.luaref; case kCallbackNone: return true; } @@ -1136,12 +1139,15 @@ void callback_free(Callback *callback) { switch (callback->type) { case kCallbackFuncref: - func_unref(callback->data.funcref); + func_unref((char_u *)callback->data.funcref); xfree(callback->data.funcref); break; case kCallbackPartial: partial_unref(callback->data.partial); break; + case kCallbackLua: + NLUA_CLEAR_REF(callback->data.luaref); + break; case kCallbackNone: break; } @@ -1161,9 +1167,14 @@ void callback_put(Callback *cb, typval_T *tv) break; case kCallbackFuncref: tv->v_type = VAR_FUNC; - tv->vval.v_string = vim_strsave(cb->data.funcref); - func_ref(cb->data.funcref); + tv->vval.v_string = xstrdup(cb->data.funcref); + func_ref((char_u *)cb->data.funcref); break; + case kCallbackLua: + // TODO(tjdevries): Unified Callback. + // At this point this isn't possible, but it'd be nice to put + // these handled more neatly in one place. + // So instead, we just do the default and put nil default: tv->v_type = VAR_SPECIAL; tv->vval.v_special = kSpecialVarNull; @@ -1182,8 +1193,11 @@ void callback_copy(Callback *dest, Callback *src) dest->data.partial->pt_refcount++; break; case kCallbackFuncref: - dest->data.funcref = vim_strsave(src->data.funcref); - func_ref(src->data.funcref); + dest->data.funcref = xstrdup(src->data.funcref); + func_ref((char_u *)src->data.funcref); + break; + case kCallbackLua: + dest->data.luaref = api_new_luaref(src->data.luaref); break; default: dest->data.funcref = NULL; @@ -1191,6 +1205,30 @@ void callback_copy(Callback *dest, Callback *src) } } +/// Generate a string description of a callback +char *callback_to_string(Callback *cb) +{ + size_t msglen = 100; + char *msg = (char *)xmallocz(msglen); + + switch (cb->type) { + case kCallbackLua: + snprintf(msg, msglen, "<lua: %d>", cb->data.luaref); + break; + case kCallbackFuncref: + // TODO(tjdevries): Is this enough space for this? + snprintf(msg, msglen, "<vim function: %s>", cb->data.funcref); + break; + case kCallbackPartial: + snprintf(msg, msglen, "<vim partial: %s>", cb->data.partial->pt_name); + break; + default: + snprintf(msg, msglen, "%s", ""); + break; + } + return msg; +} + /// Remove watcher from a dictionary /// /// @param dict Dictionary to remove watcher from. @@ -1274,7 +1312,7 @@ void tv_dict_watcher_notify(dict_T *const dict, const char *const key, typval_T argv[0].vval.v_dict = dict; argv[1].v_type = VAR_STRING; argv[1].v_lock = VAR_UNLOCKED; - argv[1].vval.v_string = (char_u *)xstrdup(key); + argv[1].vval.v_string = xstrdup(key); argv[2].v_type = VAR_DICT; argv[2].v_lock = VAR_UNLOCKED; argv[2].vval.v_dict = tv_dict_alloc(); @@ -1396,7 +1434,7 @@ dictitem_T *tv_dict_item_copy(dictitem_T *const di) void tv_dict_item_remove(dict_T *const dict, dictitem_T *const item) FUNC_ATTR_NONNULL_ALL { - hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key); + hashitem_T *const hi = hash_find(&dict->dv_hashtab, (char *)item->di_key); if (HASHITEM_EMPTY(hi)) { semsg(_(e_intern2), "tv_dict_item_remove()"); } else { @@ -1501,7 +1539,6 @@ void tv_dict_free(dict_T *const d) } } - /// Unreference a dictionary /// /// Decrements the reference count and frees dictionary when it becomes zero. @@ -1530,7 +1567,7 @@ dictitem_T *tv_dict_find(const dict_T *const d, const char *const key, const ptr return NULL; } hashitem_T *const hi = (len < 0 - ? hash_find(&d->dv_hashtab, (const char_u *)key) + ? hash_find(&d->dv_hashtab, key) : hash_find_len(&d->dv_hashtab, key, (size_t)len)); if (HASHITEM_EMPTY(hi)) { return NULL; @@ -1574,8 +1611,6 @@ varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key) } /// Converts a dict to an environment -/// -/// char **tv_dict_to_env(dict_T *denv) { size_t env_size = (size_t)tv_dict_len(denv); @@ -1894,7 +1929,7 @@ int tv_dict_add_allocated_str(dict_T *const d, const char *const key, const size dictitem_T *const item = tv_dict_item_alloc_len(key, key_len); item->di_tv.v_type = VAR_STRING; - item->di_tv.vval.v_string = (char_u *)val; + item->di_tv.vval.v_string = val; if (tv_dict_add(d, item) == FAIL) { tv_dict_item_free(item); return FAIL; @@ -2251,36 +2286,36 @@ void tv_blob_copy(typval_T *const from, typval_T *const to) #define TYPVAL_ENCODE_CONV_NIL(tv) \ do { \ - tv->vval.v_special = kSpecialVarNull; \ - tv->v_lock = VAR_UNLOCKED; \ + (tv)->vval.v_special = kSpecialVarNull; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ do { \ - tv->vval.v_bool = kBoolVarFalse; \ - tv->v_lock = VAR_UNLOCKED; \ + (tv)->vval.v_bool = kBoolVarFalse; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_NUMBER(tv, num) \ do { \ - (void)num; \ - tv->vval.v_number = 0; \ - tv->v_lock = VAR_UNLOCKED; \ + (void)(num); \ + (tv)->vval.v_number = 0; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) #define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \ do { \ - tv->vval.v_float = 0; \ - tv->v_lock = VAR_UNLOCKED; \ + (tv)->vval.v_float = 0; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ xfree(buf); \ - tv->vval.v_string = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ + (tv)->vval.v_string = NULL; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) #define TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len) @@ -2289,9 +2324,9 @@ void tv_blob_copy(typval_T *const from, typval_T *const to) #define TYPVAL_ENCODE_CONV_BLOB(tv, blob, len) \ do { \ - tv_blob_unref(tv->vval.v_blob); \ - tv->vval.v_blob = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ + tv_blob_unref((tv)->vval.v_blob); \ + (tv)->vval.v_blob = NULL; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun) @@ -2348,9 +2383,9 @@ static inline void _nothing_conv_func_end(typval_T *const tv, const int copyID) #define TYPVAL_ENCODE_CONV_EMPTY_LIST(tv) \ do { \ - tv_list_unref(tv->vval.v_list); \ - tv->vval.v_list = NULL; \ - tv->v_lock = VAR_UNLOCKED; \ + tv_list_unref((tv)->vval.v_list); \ + (tv)->vval.v_list = NULL; \ + (tv)->v_lock = VAR_UNLOCKED; \ } while (0) static inline void _nothing_conv_empty_dict(typval_T *const tv, dict_T **const dictp) @@ -2364,8 +2399,8 @@ static inline void _nothing_conv_empty_dict(typval_T *const tv, dict_T **const d } #define TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, dict) \ do { \ - assert((void *)&dict != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ - _nothing_conv_empty_dict(tv, ((dict_T **)&dict)); \ + assert((void *)&(dict) != (void *)&TYPVAL_ENCODE_NODICT_VAR); \ + _nothing_conv_empty_dict(tv, ((dict_T **)&(dict))); \ } while (0) static inline int _nothing_conv_real_list_after_start(typval_T *const tv, @@ -2386,7 +2421,7 @@ static inline int _nothing_conv_real_list_after_start(typval_T *const tv, #define TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, mpsv) \ do { \ - if (_nothing_conv_real_list_after_start(tv, &mpsv) != NOTDONE) { \ + if (_nothing_conv_real_list_after_start(tv, &(mpsv)) != NOTDONE) { \ goto typval_encode_stop_converting_one_item; \ } \ } while (0) @@ -2426,8 +2461,9 @@ static inline int _nothing_conv_real_dict_after_start(typval_T *const tv, dict_T #define TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, dict, mpsv) \ do { \ - if (_nothing_conv_real_dict_after_start(tv, (dict_T **)&dict, (void *)&TYPVAL_ENCODE_NODICT_VAR, \ - &mpsv) != NOTDONE) { \ + if (_nothing_conv_real_dict_after_start(tv, (dict_T **)&(dict), \ + (void *)&TYPVAL_ENCODE_NODICT_VAR, &(mpsv)) \ + != NOTDONE) { \ goto typval_encode_stop_converting_one_item; \ } \ } while (0) @@ -2446,7 +2482,7 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic } } #define TYPVAL_ENCODE_CONV_DICT_END(tv, dict) \ - _nothing_conv_dict_end(tv, (dict_T **)&dict, \ + _nothing_conv_dict_end(tv, (dict_T **)&(dict), \ (void *)&TYPVAL_ENCODE_NODICT_VAR) #define TYPVAL_ENCODE_CONV_RECURSE(val, conv_type) @@ -2520,7 +2556,7 @@ void tv_free(typval_T *tv) partial_unref(tv->vval.v_partial); break; case VAR_FUNC: - func_unref(tv->vval.v_string); + func_unref((char_u *)tv->vval.v_string); FALLTHROUGH; case VAR_STRING: xfree(tv->vval.v_string); @@ -2571,9 +2607,9 @@ void tv_copy(const typval_T *const from, typval_T *const to) case VAR_STRING: case VAR_FUNC: if (from->vval.v_string != NULL) { - to->vval.v_string = vim_strsave(from->vval.v_string); + to->vval.v_string = xstrdup(from->vval.v_string); if (from->v_type == VAR_FUNC) { - func_ref(to->vval.v_string); + func_ref((char_u *)to->vval.v_string); } } break; @@ -2628,9 +2664,9 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const boo // lock/unlock the item itself #define CHANGE_LOCK(lock, var) \ do { \ - var = ((VarLockStatus[]) { \ - [VAR_UNLOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ - [VAR_LOCKED] = (lock ? VAR_LOCKED : VAR_UNLOCKED), \ + (var) = ((VarLockStatus[]) { \ + [VAR_UNLOCKED] = ((lock) ? VAR_LOCKED : VAR_UNLOCKED), \ + [VAR_LOCKED] = ((lock) ? VAR_LOCKED : VAR_UNLOCKED), \ [VAR_FIXED] = VAR_FIXED, \ })[var]; \ } while (0) @@ -3059,7 +3095,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(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, + vim_str2nr((char_u *)tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false); } return n; @@ -3091,7 +3127,7 @@ linenr_T tv_get_lnum(const typval_T *const tv) linenr_T lnum = (linenr_T)tv_get_number_chk(tv, NULL); if (lnum == 0) { // No valid number, try using same function as line() does. int fnum; - pos_T *const fp = var2fpos(tv, true, &fnum); + pos_T *const fp = var2fpos(tv, true, &fnum, false); if (fp != NULL) { lnum = fp->lnum; } @@ -3205,8 +3241,9 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) case VAR_BLOB: case VAR_UNKNOWN: emsg(_(str_errors[tv->v_type])); - return false; + return NULL; } + abort(); return NULL; } diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index d1275d6512..c02351947b 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -72,16 +72,20 @@ typedef enum { kCallbackNone = 0, kCallbackFuncref, kCallbackPartial, + kCallbackLua, } CallbackType; typedef struct { union { - char_u *funcref; + char *funcref; partial_T *partial; + LuaRef luaref; } data; CallbackType type; } Callback; -#define CALLBACK_NONE ((Callback){ .type = kCallbackNone }) + +#define CALLBACK_INIT { .type = kCallbackNone } +#define CALLBACK_NONE ((Callback)CALLBACK_INIT) /// Structure holding dictionary watcher typedef struct dict_watcher { @@ -129,19 +133,19 @@ typedef enum { /// Structure that holds an internal variable value typedef struct { - VarType v_type; ///< Variable type. - VarLockStatus v_lock; ///< Variable lock status. + VarType v_type; ///< Variable type. + VarLockStatus v_lock; ///< Variable lock status. union typval_vval_union { - varnumber_T v_number; ///< Number, for VAR_NUMBER. + 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_u *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. + 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 diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index ece51cb046..73b36b8611 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -1,3 +1,5 @@ +// uncrustify:off + /// @file eval/typval_encode.c.h /// /// Contains set of macros used to convert (possibly recursive) typval_T into @@ -250,6 +252,8 @@ #include "nvim/func_attr.h" #include "nvim/lib/kvec.h" +// -V::1063 + /// Dummy variable used because some macros need lvalue /// /// Must not be written to, if needed one must check that address of the @@ -335,7 +339,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( tv_blob_len(tv->vval.v_blob)); break; case VAR_FUNC: - TYPVAL_ENCODE_CONV_FUNC_START(tv, tv->vval.v_string); + TYPVAL_ENCODE_CONV_FUNC_START(tv, (char_u *)tv->vval.v_string); TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, 0); TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); TYPVAL_ENCODE_CONV_FUNC_END(tv); @@ -343,8 +347,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_PARTIAL: { partial_T *const pt = tv->vval.v_partial; (void)pt; - TYPVAL_ENCODE_CONV_FUNC_START( // -V547 - tv, (pt == NULL ? NULL : partial_name(pt))); + TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : (char_u *)partial_name(pt))); // -V547 _mp_push(*mpstack, ((MPConvStackVal) { // -V779 .type = kMPConvPartial, .tv = tv, diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index d5cf431870..ed70ba87ec 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -85,9 +85,7 @@ static inline size_t tv_strlen(const typval_T *const tv) static inline size_t tv_strlen(const typval_T *const tv) { assert(tv->v_type == VAR_STRING); - return (tv->vval.v_string == NULL - ? 0 - : strlen((char *)tv->vval.v_string)); + return (tv->vval.v_string == NULL ? 0 : strlen(tv->vval.v_string)); } /// Code for checking whether container references itself diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index eb241eb8ae..c2579944e4 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -70,7 +70,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i bool mustend = false; char_u *arg = *argp; char_u *p = arg; - int c; + char_u c; int i; if (newargs != NULL) { @@ -125,14 +125,14 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i *p = c; } - if (*skipwhite(p) == '=' && default_args != NULL) { + if (*skipwhite((char *)p) == '=' && default_args != NULL) { typval_T rettv; any_default = true; - p = skipwhite(p) + 1; - p = skipwhite(p); + p = (char_u *)skipwhite((char *)p) + 1; + p = (char_u *)skipwhite((char *)p); char_u *expr = p; - if (eval1(&p, &rettv, false) != FAIL) { + if (eval1((char **)&p, &rettv, false) != FAIL) { ga_grow(default_args, 1); // trim trailing whitespace @@ -159,7 +159,7 @@ static int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, i mustend = true; } } - p = skipwhite(p); + p = (char_u *)skipwhite((char *)p); if (mustend && *p != endchar) { if (!skip) { semsg(_(e_invarg2), *argp); @@ -200,8 +200,7 @@ static void register_closure(ufunc_T *fp) [current_funccal->fc_funcs.ga_len++] = fp; } - -/// Get a name for a lambda. Returned in static memory. +/// @return a name for a lambda. Returned in static memory. char_u *get_lambda_name(void) { static char_u name[30]; @@ -222,7 +221,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) partial_T *pt = NULL; int varargs; int ret; - char_u *start = skipwhite(*arg + 1); + char_u *start = (char_u *)skipwhite((char *)(*arg) + 1); char_u *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; @@ -239,7 +238,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) } else { pnewargs = NULL; } - *arg = skipwhite(*arg + 1); + *arg = (char_u *)skipwhite((char *)(*arg) + 1); ret = get_function_args(arg, '-', pnewargs, &varargs, NULL, false); if (ret == FAIL || **arg != '>') { goto errret; @@ -251,21 +250,21 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) } // Get the start and the end of the expression. - *arg = skipwhite(*arg + 1); + *arg = (char_u *)skipwhite((char *)(*arg) + 1); s = *arg; - ret = skip_expr(arg); + ret = skip_expr((char **)arg); if (ret == FAIL) { goto errret; } e = *arg; - *arg = skipwhite(*arg); + *arg = (char_u *)skipwhite((char *)(*arg)); if (**arg != '}') { goto errret; } (*arg)++; if (evaluate) { - int len, flags = 0; + int flags = 0; char_u *p; garray_T newlines; @@ -278,7 +277,7 @@ int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) ga_grow(&newlines, 1); // Add "return " before the expression. - len = 7 + e - s + 1; + size_t len = (size_t)(7 + e - s + 1); p = (char_u *)xmalloc(len); ((char_u **)(newlines.ga_data))[newlines.ga_len++] = p; STRCPY(p, "return "); @@ -359,7 +358,7 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, return (char_u *)""; } *lenp = (int)STRLEN(v->di_tv.vval.v_string); - return v->di_tv.vval.v_string; + return (char_u *)v->di_tv.vval.v_string; } if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) { @@ -372,7 +371,7 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, if (partialp != NULL) { *partialp = pt; } - char_u *s = partial_name(pt); + char_u *s = (char_u *)partial_name(pt); *lenp = (int)STRLEN(s); return s; } @@ -422,11 +421,11 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char_u **arg, func argp = *arg; while (argcount < MAX_FUNC_ARGS - (funcexe->partial == NULL ? 0 : funcexe->partial->pt_argc)) { - argp = skipwhite(argp + 1); // skip the '(' or ',' + argp = (char_u *)skipwhite((char *)argp + 1); // skip the '(' or ',' if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) { + if (eval1((char **)&argp, &argvars[argcount], funcexe->evaluate) == FAIL) { ret = FAIL; break; } @@ -455,7 +454,7 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char_u **arg, func ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i]; } } - ret = call_func(name, len, rettv, argcount, argvars, funcexe); + ret = call_func((char *)name, len, rettv, argcount, argvars, funcexe); funcargs.ga_len -= i; } else if (!aborting()) { @@ -470,7 +469,7 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char_u **arg, func tv_clear(&argvars[argcount]); } - *arg = skipwhite(argp); + *arg = (char_u *)skipwhite((char *)argp); return ret; } @@ -516,22 +515,22 @@ static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf if (llen > 0) { fname_buf[0] = K_SPECIAL; fname_buf[1] = KS_EXTRA; - fname_buf[2] = (int)KE_SNR; + 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, FLEN_FIXED + 1 - i, "%" PRId64 "_", + snprintf((char *)fname_buf + i, (size_t)(FLEN_FIXED + 1 - i), "%" PRId64 "_", (int64_t)current_sctx.sc_sid); i = (int)STRLEN(fname_buf); } } - if (i + STRLEN(name + llen) < FLEN_FIXED) { + if ((size_t)i + STRLEN(name + llen) < FLEN_FIXED) { STRCPY(fname_buf + i, name + llen); fname = fname_buf; } else { - fname = xmalloc(i + STRLEN(name + llen) + 1); + fname = xmalloc((size_t)i + STRLEN(name + llen) + 1); *tofree = fname; memmove(fname, fname_buf, (size_t)i); STRCPY(fname + i, name + llen); @@ -544,23 +543,20 @@ static char_u *fname_trans_sid(const char_u *const name, char_u *const fname_buf } /// Find a function by name, return pointer to it in ufuncs. -/// @return NULL for unknown function. +/// +/// @return NULL for unknown function. ufunc_T *find_func(const char_u *name) { - hashitem_T *hi; - - hi = hash_find(&func_hashtab, name); + hashitem_T *hi = hash_find(&func_hashtab, (char *)name); if (!HASHITEM_EMPTY(hi)) { return HI2UF(hi); } return NULL; } -/* - * Copy the function name of "fp" to buffer "buf". - * "buf" must be able to hold the function name plus three bytes. - * Takes care of script-local function names. - */ +/// Copy the function name of "fp" to buffer "buf". +/// "buf" must be able to hold the function name plus three bytes. +/// Takes care of script-local function names. static void cat_func_name(char_u *buf, ufunc_T *fp) { if (fp->uf_name[0] == K_SPECIAL) { @@ -571,9 +567,7 @@ static void cat_func_name(char_u *buf, ufunc_T *fp) } } -/* - * Add a number variable "name" to dict "dp" with value "nr". - */ +/// Add a number variable "name" to dict "dp" with value "nr". static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) { #ifndef __clang_analyzer__ @@ -586,7 +580,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) v->di_tv.vval.v_number = nr; } -// Free "fc" +/// Free "fc" static void free_funccal(funccall_T *fc) { for (int i = 0; i < fc->fc_funcs.ga_len; i++) { @@ -606,9 +600,9 @@ static void free_funccal(funccall_T *fc) xfree(fc); } -// Free "fc" and what it contains. -// Can be called only when "fc" is kept beyond the period of it called, -// i.e. after cleanup_function_call(fc). +/// Free "fc" and what it contains. +/// Can be called only when "fc" is kept beyond the period of it called, +/// i.e. after cleanup_function_call(fc). static void free_funccal_contents(funccall_T *fc) { // Free all l: variables. @@ -728,7 +722,7 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) /// @return true if the entry was deleted, false if it wasn't found. static bool func_remove(ufunc_T *fp) { - hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp)); + hashitem_T *hi = hash_find(&func_hashtab, (char *)UF2HIKEY(fp)); if (!HASHITEM_EMPTY(hi)) { hash_remove(&func_hashtab, hi); @@ -757,7 +751,7 @@ static void func_clear_items(ufunc_T *fp) /// Free all things that a function contains. Does not free the function /// itself, use func_free() for that. /// -/// param[in] force When true, we are exiting. +/// @param[in] force When true, we are exiting. static void func_clear(ufunc_T *fp, bool force) { if (fp->uf_cleared) { @@ -773,7 +767,7 @@ static void func_clear(ufunc_T *fp, bool force) /// Free a function and remove it from the list of functions. Does not free /// what a function contains, call func_clear() first. /// -/// param[in] fp The function to free. +/// @param[in] fp The function to free. static void func_free(ufunc_T *fp) { // only remove it when not done already, otherwise we would remove a newer @@ -786,7 +780,7 @@ static void func_free(ufunc_T *fp) /// Free all things that a function contains and free the function itself. /// -/// param[in] force When true, we are exiting. +/// @param[in] force When true, we are exiting. static void func_clear_free(ufunc_T *fp, bool force) { func_clear(fp, force); @@ -795,13 +789,13 @@ static void func_clear_free(ufunc_T *fp, bool force) /// Call a user function /// -/// @param fp Function to call. -/// @param[in] argcount Number of arguments. -/// @param argvars Arguments. -/// @param[out] rettv Return value. -/// @param[in] firstline First line of range. -/// @param[in] lastline Last line of range. -/// @param selfdict Dictionary for "self" for dictionary functions. +/// @param fp Function to call. +/// @param[in] argcount Number of arguments. +/// @param argvars Arguments. +/// @param[out] rettv Return value. +/// @param[in] firstline First line of range. +/// @param[in] lastline Last line of range. +/// @param selfdict Dictionary for "self" for dictionary functions. void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, linenr_T firstline, linenr_T lastline, dict_T *selfdict) FUNC_ATTR_NONNULL_ARG(1, 3, 4) @@ -944,7 +938,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett default_expr = ((char_u **)(fp->uf_def_args.ga_data)) [ai + fp->uf_def_args.ga_len]; - if (eval1(&default_expr, &def_rettv, true) == FAIL) { + if (eval1((char **)&default_expr, &def_rettv, true) == FAIL) { default_arg_err = true; break; } @@ -997,7 +991,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Don't redraw while executing the function. RedrawingDisabled++; - save_sourcing_name = sourcing_name; + save_sourcing_name = (char_u *)sourcing_name; save_sourcing_lnum = sourcing_lnum; sourcing_lnum = 1; @@ -1017,7 +1011,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett { if (save_sourcing_name != NULL && STRNCMP(save_sourcing_name, "function ", 9) == 0) { - vim_snprintf((char *)sourcing_name, + vim_snprintf(sourcing_name, len, "%s[%" PRId64 "]..", save_sourcing_name, @@ -1025,7 +1019,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett } else { STRCPY(sourcing_name, "function "); } - cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); + cat_func_name((char_u *)sourcing_name + STRLEN(sourcing_name), fp); if (p_verbose >= 12) { ++no_wait_return; @@ -1048,9 +1042,8 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett if (tofree != NULL) { char *s = tofree; char buf[MSG_BUF_LEN]; - if (vim_strsize((char_u *)s) > MSG_BUF_CLEN) { - trunc_string((char_u *)s, (char_u *)buf, MSG_BUF_CLEN, - sizeof(buf)); + if (vim_strsize(s) > MSG_BUF_CLEN) { + trunc_string(s, buf, MSG_BUF_CLEN, sizeof(buf)); s = buf; } msg_puts(s); @@ -1106,7 +1099,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // A Lambda always has the command "return {expr}". It is much faster // to evaluate {expr} directly. ex_nesting_level++; - (void)eval1(&p, rettv, true); + (void)eval1((char **)&p, rettv, true); ex_nesting_level--; } else { // call do_cmdline() to execute the lines @@ -1153,14 +1146,14 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett smsg(_("%s returning #%" PRId64 ""), sourcing_name, (int64_t)fc->rettv->vval.v_number); } else { - char_u buf[MSG_BUF_LEN]; + char buf[MSG_BUF_LEN]; // The value may be very long. Skip the middle part, so that we // have some idea how it starts and ends. smsg() would always // truncate it at the end. Don't want errors such as E724 here. emsg_off++; - char_u *s = (char_u *)encode_tv2string(fc->rettv, NULL); - char_u *tofree = s; + char *s = encode_tv2string(fc->rettv, NULL); + char *tofree = s; emsg_off--; if (s != NULL) { if (vim_strsize(s) > MSG_BUF_CLEN) { @@ -1178,7 +1171,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett } xfree(sourcing_name); - sourcing_name = save_sourcing_name; + sourcing_name = (char *)save_sourcing_name; sourcing_lnum = save_sourcing_lnum; current_sctx = save_current_sctx; if (do_profiling_yes) { @@ -1230,8 +1223,8 @@ static bool func_name_refcount(char_u *name) static funccal_entry_T *funccal_stack = NULL; -// Save the current function call pointer, and set it to NULL. -// Used when executing autocommands and for ":source". +/// Save the current function call pointer, and set it to NULL. +/// Used when executing autocommands and for ":source". void save_funccal(funccal_entry_T *entry) { entry->top_funccal = current_funccal; @@ -1373,7 +1366,7 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict funcexe.evaluate = true; funcexe.partial = partial; funcexe.selfdict = selfdict; - r = call_func(name, -1, rettv, argc, argv, &funcexe); + r = call_func((char *)name, -1, rettv, argc, argv, &funcexe); func_call_skip_call: // Free the arguments. @@ -1384,8 +1377,8 @@ func_call_skip_call: return r; } -// Give an error message for the result of a function. -// Nothing if "error" is FCERR_NONE. +/// Give an error message for the result of a function. +/// Nothing if "error" is FCERR_NONE. static void user_func_error(int error, const char_u *name) FUNC_ATTR_NONNULL_ALL { @@ -1425,7 +1418,7 @@ static void argv_add_base(typval_T *const basetv, typval_T **const argvars, int { if (basetv != NULL) { // Method call: base->Method() - memmove(&new_argvars[1], *argvars, sizeof(typval_T) * (*argcount)); + memmove(&new_argvars[1], *argvars, sizeof(typval_T) * (size_t)(*argcount)); new_argvars[0] = *basetv; (*argcount)++; *argvars = new_argvars; @@ -1445,8 +1438,8 @@ static void argv_add_base(typval_T *const basetv, typval_T **const argvars, int /// @return FAIL if function cannot be called, else OK (even if an error /// occurred while executing the function! Set `msg_list` to capture /// the error, see do_cmdline()). -int call_func(const char_u *funcname, int len, typval_T *rettv, int argcount_in, - typval_T *argvars_in, funcexe_T *funcexe) +int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, + funcexe_T *funcexe) FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6) { int ret = FAIL; @@ -1478,7 +1471,7 @@ int call_func(const char_u *funcname, int len, typval_T *rettv, int argcount_in, 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(funcname, len); + name = vim_strnsave((char_u *)funcname, (size_t)len); fname = fname_trans_sid(name, fname_buf, &tofree, &error); } @@ -1525,11 +1518,11 @@ int call_func(const char_u *funcname, int len, typval_T *rettv, int argcount_in, if (len > 0) { error = ERROR_NONE; argv_add_base(funcexe->basetv, &argvars, &argcount, argv, &argv_base); - nlua_typval_call((const char *)funcname, len, argvars, argcount, rettv); + nlua_typval_call(funcname, (size_t)len, argvars, argcount, rettv); } else { // v:lua was called directly; show its name in the emsg XFREE_CLEAR(name); - funcname = (const char_u *)"v:lua"; + funcname = "v:lua"; } } else if (fp != NULL || !builtin_function((const char *)rfname, -1)) { // User defined function. @@ -1539,7 +1532,7 @@ int call_func(const char_u *funcname, int len, typval_T *rettv, int argcount_in, // Trigger FuncUndefined event, may load the function. if (fp == NULL - && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL) + && apply_autocmds(EVENT_FUNCUNDEFINED, (char *)rfname, (char *)rfname, true, NULL) && !aborting()) { // executed an autocommand, search for the function again fp = find_func(rfname); @@ -1611,7 +1604,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 : funcname); + user_func_error(error, (name != NULL) ? name : (char_u *)funcname); } // clear the copies made from the partial @@ -1713,10 +1706,10 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, // Check for hard coded <SNR>: already translated function ID (from a user // command). if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA - && (*pp)[2] == (int)KE_SNR) { + && (*pp)[2] == KE_SNR) { *pp += 3; len = get_id_len((const char **)pp) + 3; - return (char_u *)xmemdupz(start, len); + return (char_u *)xmemdupz(start, (size_t)len); } // A name starting with "<SID>" or "<SNR>" is local to a script. But @@ -1727,8 +1720,8 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, } // Note that TFN_ flags use the same values as GLV_ flags. - end = get_lval((char_u *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, - lead > 2 ? 0 : FNE_CHECK_START); + end = (char_u *)get_lval((char *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, + lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { if (!skip) { emsg(_("E129: Function name required")); @@ -1746,7 +1739,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, semsg(_(e_invarg2), start); } } else { - *pp = (char_u *)find_name_end(start, NULL, NULL, FNE_INCL_BR); + *pp = (char_u *)find_name_end((char *)start, NULL, NULL, FNE_INCL_BR); } goto theend; } @@ -1754,26 +1747,26 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, if (lv.ll_tv != NULL) { if (fdp != NULL) { fdp->fd_dict = lv.ll_dict; - fdp->fd_newkey = lv.ll_newkey; + fdp->fd_newkey = (char_u *)lv.ll_newkey; lv.ll_newkey = NULL; fdp->fd_di = lv.ll_di; } if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) { - name = vim_strsave(lv.ll_tv->vval.v_string); + name = vim_strsave((char_u *)lv.ll_tv->vval.v_string); *pp = (char_u *)end; } else if (lv.ll_tv->v_type == VAR_PARTIAL && lv.ll_tv->vval.v_partial != NULL) { if (is_luafunc(lv.ll_tv->vval.v_partial) && *end == '.') { - len = check_luafunc_name((const char *)end+1, true); + len = check_luafunc_name((const char *)end + 1, true); if (len == 0) { semsg(e_invexpr2, "v:lua"); goto theend; } - name = xmallocz(len); - memcpy(name, end+1, len); - *pp = (char_u *)end+1+len; + name = xmallocz((size_t)len); + memcpy(name, end + 1, (size_t)len); + *pp = (char_u *)end + 1 + len; } else { - name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial)); + name = vim_strsave((char_u *)partial_name(lv.ll_tv->vval.v_partial)); *pp = (char_u *)end; } if (partial != NULL) { @@ -1821,7 +1814,7 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, // Change "<SNR>" to the byte sequence. name[0] = K_SPECIAL; name[1] = KS_EXTRA; - name[2] = (int)KE_SNR; + name[2] = KE_SNR; memmove(name + 3, name + 5, strlen((char *)name + 5) + 1); } goto theend; @@ -1864,12 +1857,11 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, emsg(_(e_usingsid)); goto theend; } - sid_buf_len = snprintf(sid_buf, sizeof(sid_buf), - "%" PRIdSCID "_", current_sctx.sc_sid); - lead += sid_buf_len; + sid_buf_len = + (size_t)snprintf(sid_buf, sizeof(sid_buf), "%" PRIdSCID "_", current_sctx.sc_sid); + lead += (int)sid_buf_len; } - } else if (!(flags & TFN_INT) - && builtin_function(lv.ll_name, lv.ll_name_len)) { + } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, (int)lv.ll_name_len)) { semsg(_("E128: Function name must start with a capital or \"s:\": %s"), start); goto theend; @@ -1884,16 +1876,16 @@ char_u *trans_function_name(char_u **pp, bool skip, int flags, funcdict_T *fdp, } } - name = xmalloc(len + lead + 1); + name = xmalloc((size_t)len + (size_t)lead + 1); if (!skip && lead > 0) { name[0] = K_SPECIAL; name[1] = KS_EXTRA; - name[2] = (int)KE_SNR; + name[2] = KE_SNR; if (sid_buf_len > 0) { // If it's "<SID>" memcpy(name + 3, sid_buf, sid_buf_len); } } - memmove(name + lead, lv.ll_name, len); + memmove(name + lead, lv.ll_name, (size_t)len); name[lead + len] = NUL; *pp = (char_u *)end; @@ -1902,14 +1894,12 @@ theend: return name; } -/* - * ":function" - */ +/// ":function" void ex_function(exarg_T *eap) { char_u *theline; char_u *line_to_free = NULL; - int c; + char_u c; int saved_did_emsg; bool saved_wait_return = need_wait_return; char_u *name = NULL; @@ -1959,7 +1949,7 @@ void ex_function(exarg_T *eap) } } } - eap->nextcmd = check_nextcmd(eap->arg); + eap->nextcmd = (char *)check_nextcmd((char_u *)eap->arg); return; } @@ -1967,7 +1957,7 @@ void ex_function(exarg_T *eap) * ":function /pat": list functions matching pattern. */ if (*eap->arg == '/') { - p = skip_regexp(eap->arg + 1, '/', TRUE, NULL); + p = skip_regexp((char_u *)eap->arg + 1, '/', true, NULL); if (!eap->skip) { regmatch_T regmatch; @@ -1984,7 +1974,7 @@ void ex_function(exarg_T *eap) --todo; fp = HI2UF(hi); if (!isdigit(*fp->uf_name) - && vim_regexec(®match, fp->uf_name, 0)) { + && vim_regexec(®match, (char *)fp->uf_name, 0)) { list_func_head(fp, false, false); } } @@ -1995,7 +1985,7 @@ void ex_function(exarg_T *eap) if (*p == '/') { ++p; } - eap->nextcmd = check_nextcmd(p); + eap->nextcmd = (char *)check_nextcmd(p); return; } @@ -2013,9 +2003,9 @@ 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 = eap->arg; + p = (char_u *)eap->arg; name = trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL); - paren = (vim_strchr(p, '(') != NULL); + paren = (vim_strchr((char *)p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) { /* * Return on an invalid expression in braces, unless the expression @@ -2045,11 +2035,11 @@ void ex_function(exarg_T *eap) // - exclude line numbers from function body // if (!paren) { - if (!ends_excmd(*skipwhite(p))) { + if (!ends_excmd(*skipwhite((char *)p))) { emsg(_(e_trailing)); goto ret_free; } - eap->nextcmd = check_nextcmd(p); + eap->nextcmd = (char *)check_nextcmd(p); if (eap->nextcmd != NULL) { *p = NUL; } @@ -2089,18 +2079,18 @@ void ex_function(exarg_T *eap) /* * ":function name(arg1, arg2)" Define function. */ - p = skipwhite(p); + p = (char_u *)skipwhite((char *)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(p, '(') != NULL) { - p = vim_strchr(p, '('); + if (vim_strchr((char *)p, '(') != NULL) { + p = (char_u *)vim_strchr((char *)p, '('); } } - p = skipwhite(p + 1); + p = (char_u *)skipwhite((char *)p + 1); ga_init(&newargs, (int)sizeof(char_u *), 3); ga_init(&newlines, (int)sizeof(char_u *), 3); @@ -2141,7 +2131,7 @@ void ex_function(exarg_T *eap) // find extra arguments "range", "dict", "abort" and "closure" for (;;) { - p = skipwhite(p); + p = (char_u *)skipwhite((char *)p); if (STRNCMP(p, "range", 5) == 0) { flags |= FC_RANGE; p += 5; @@ -2213,7 +2203,7 @@ void ex_function(exarg_T *eap) if (line_arg != NULL) { // Use eap->arg, split up in parts by line breaks. theline = line_arg; - p = vim_strchr(theline, '\n'); + p = (char_u *)vim_strchr((char *)theline, '\n'); if (p == NULL) { line_arg += STRLEN(line_arg); } else { @@ -2225,7 +2215,7 @@ void ex_function(exarg_T *eap) if (eap->getline == NULL) { theline = getcmdline(':', 0L, indent, do_concat); } else { - theline = eap->getline(':', eap->cookie, indent, do_concat); + theline = (char_u *)eap->getline(':', eap->cookie, indent, do_concat); } line_to_free = theline; } @@ -2255,13 +2245,13 @@ void ex_function(exarg_T *eap) // * ":python <<EOF" and "EOF" // * ":let {var-name} =<< [trim] {marker}" and "{marker}" if (heredoc_trimmed == NULL - || (is_heredoc && skipwhite(theline) == theline) + || (is_heredoc && (char_u *)skipwhite((char *)theline) == theline) || STRNCMP(theline, heredoc_trimmed, STRLEN(heredoc_trimmed)) == 0) { if (heredoc_trimmed == NULL) { p = theline; } else if (is_heredoc) { - p = skipwhite(theline) == theline + p = (char_u *)skipwhite((char *)theline) == theline ? theline : theline + STRLEN(heredoc_trimmed); } else { p = theline + STRLEN(heredoc_trimmed); @@ -2275,18 +2265,17 @@ void ex_function(exarg_T *eap) } } else { // skip ':' and blanks - for (p = theline; ascii_iswhite(*p) || *p == ':'; p++) { - } + for (p = theline; ascii_iswhite(*p) || *p == ':'; p++) {} // Check for "endfunction". - if (checkforcmd(&p, "endfunction", 4) && nesting-- == 0) { + if (checkforcmd((char **)&p, "endfunction", 4) && nesting-- == 0) { if (*p == '!') { p++; } char_u *nextcmd = NULL; if (*p == '|') { nextcmd = p + 1; - } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) { + } else if (line_arg != NULL && *skipwhite((char *)line_arg) != NUL) { nextcmd = line_arg; } else if (*p != NUL && *p != '"' && p_verbose > 0) { give_warning2((char_u *)_("W22: Text found after :endfunction: %s"), @@ -2296,10 +2285,10 @@ void ex_function(exarg_T *eap) // Another command follows. If the line came from "eap" we // can simply point into it, otherwise we need to change // "eap->cmdlinep". - eap->nextcmd = nextcmd; + eap->nextcmd = (char *)nextcmd; if (line_to_free != NULL) { xfree(*eap->cmdlinep); - *eap->cmdlinep = line_to_free; + *eap->cmdlinep = (char *)line_to_free; line_to_free = NULL; } } @@ -2318,20 +2307,20 @@ void ex_function(exarg_T *eap) } // Check for defining a function inside this function. - if (checkforcmd(&p, "function", 2)) { + if (checkforcmd((char **)&p, "function", 2)) { if (*p == '!') { - p = skipwhite(p + 1); + p = (char_u *)skipwhite((char *)p + 1); } p += eval_fname_script((const char *)p); xfree(trans_function_name(&p, true, 0, NULL, NULL)); - if (*skipwhite(p) == '(') { + if (*skipwhite((char *)p) == '(') { nesting++; indent += 2; } } // Check for ":append", ":change", ":insert". - p = skip_range(p, NULL); + p = (char_u *)skip_range((char *)p, NULL); if ((p[0] == 'a' && (!ASCII_ISALPHA(p[1]) || p[1] == 'p')) || (p[0] == 'c' && (!ASCII_ISALPHA(p[1]) @@ -2347,7 +2336,7 @@ void ex_function(exarg_T *eap) } // heredoc: Check for ":python <<EOF", ":lua <<EOF", etc. - arg = skipwhite(skiptowhite(p)); + arg = (char_u *)skipwhite((char *)skiptowhite(p)); if (arg[0] == '<' && arg[1] == '<' && ((p[0] == 'p' && p[1] == 'y' && (!ASCII_ISALNUM(p[2]) || p[2] == 't' @@ -2364,7 +2353,7 @@ 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 = skipwhite(arg + 2); + p = (char_u *)skipwhite((char *)arg + 2); if (*p == NUL) { skip_until = vim_strsave((char_u *)"."); } else { @@ -2374,12 +2363,12 @@ void ex_function(exarg_T *eap) // Check for ":let v =<< [trim] EOF" // and ":let [a, b] =<< [trim] EOF" - arg = skipwhite(skiptowhite(p)); + arg = (char_u *)skipwhite((char *)skiptowhite(p)); if (*arg == '[') { - arg = vim_strchr(arg, ']'); + arg = (char_u *)vim_strchr((char *)arg, ']'); } if (arg != NULL) { - arg = skipwhite(skiptowhite(arg)); + arg = (char_u *)skipwhite((char *)skiptowhite(arg)); if (arg[0] == '=' && arg[1] == '<' && arg[2] == '<' @@ -2387,14 +2376,14 @@ void ex_function(exarg_T *eap) && p[1] == 'e' && (!ASCII_ISALNUM(p[2]) || (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) { - p = skipwhite(arg + 3); + p = (char_u *)skipwhite((char *)arg + 3); if (STRNCMP(p, "trim", 4) == 0) { // Ignore leading white space. - p = skipwhite(p + 4); + p = (char_u *)skipwhite((char *)p + 4); heredoc_trimmed = - vim_strnsave(theline, skipwhite(theline) - theline); + vim_strnsave(theline, (size_t)((char_u *)skipwhite((char *)theline) - theline)); } - skip_until = vim_strnsave(p, skiptowhite(p) - p); + skip_until = vim_strnsave(p, (size_t)(skiptowhite(p) - p)); do_concat = false; is_heredoc = true; } @@ -2402,7 +2391,7 @@ void ex_function(exarg_T *eap) } // Add the line to the function. - ga_grow(&newlines, 1 + sourcing_lnum_off); + ga_grow(&newlines, 1 + (int)sourcing_lnum_off); // Copy the line to newly allocated memory. get_one_sourceline() // allocates 250 bytes per line, this saves 80% on average. The cost @@ -2497,7 +2486,7 @@ void ex_function(exarg_T *eap) } if (fp == NULL) { - if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) { + if (fudi.fd_dict == NULL && vim_strchr((char *)name, AUTOLOAD_CHAR) != NULL) { int slen, plen; char_u *scriptname; @@ -2505,10 +2494,10 @@ void ex_function(exarg_T *eap) int j = FAIL; if (sourcing_name != NULL) { scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name)); - p = vim_strchr(scriptname, '/'); + p = (char_u *)vim_strchr((char *)scriptname, '/'); plen = (int)STRLEN(p); slen = (int)STRLEN(sourcing_name); - if (slen > plen && fnamecmp(p, + if (slen > plen && FNAMECMP(p, sourcing_name + slen - plen) == 0) { j = OK; } @@ -2537,7 +2526,7 @@ 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 = vim_strsave(name); + fudi.fd_di->di_tv.vval.v_string = (char *)vim_strsave(name); // behave like "dict" was used flags |= FC_DICT; @@ -2546,7 +2535,7 @@ void ex_function(exarg_T *eap) // insert the new function in the function list STRCPY(fp->uf_name, name); if (overwrite) { - hi = hash_find(&func_hashtab, name); + hi = hash_find(&func_hashtab, (char *)name); hi->hi_key = UF2HIKEY(fp); } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { xfree(fp); @@ -2573,6 +2562,7 @@ void ex_function(exarg_T *eap) fp->uf_calls = 0; fp->uf_script_ctx = current_sctx; fp->uf_script_ctx.sc_lnum += sourcing_lnum_top; + nlua_set_sctx(&fp->uf_script_ctx); goto ret_free; @@ -2592,13 +2582,11 @@ ret_free: if (show_block) { ui_ext_cmdline_block_leave(); } -} // NOLINT(readability/fn_size) +} -/* - * Return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). - * Return 2 if "p" starts with "s:". - * Return 0 otherwise. - */ +/// @return 5 if "p" starts with "<SID>" or "<SNR>" (ignoring case). +/// 2 if "p" starts with "s:". +/// 0 otherwise. int eval_fname_script(const char *const p) { // Use mb_strnicmp() because in Turkish comparing the "I" may not work with @@ -2624,10 +2612,10 @@ bool translated_function_exists(const char *name) /// Check whether function with the given name exists /// -/// @param[in] name Function name. -/// @param[in] no_deref Whether to dereference a Funcref. +/// @param[in] name Function name. +/// @param[in] no_deref Whether to dereference a Funcref. /// -/// @return True if it exists, false otherwise. +/// @return true if it exists, false otherwise. bool function_exists(const char *const name, bool no_deref) { const char_u *nm = (const char_u *)name; @@ -2639,7 +2627,7 @@ bool function_exists(const char *const name, bool no_deref) } char *const p = (char *)trans_function_name((char_u **)&nm, false, flag, NULL, NULL); - nm = skipwhite(nm); + nm = (char_u *)skipwhite((char *)nm); // Only accept "funcname", "funcname ", "funcname (..." and // "funcname(...", not "funcname!...". @@ -2650,11 +2638,9 @@ bool function_exists(const char *const name, bool no_deref) return n; } -/* - * Function given to ExpandGeneric() to obtain the list of user defined - * function names. - */ -char_u *get_user_func_name(expand_T *xp, int idx) +/// Function given to ExpandGeneric() to obtain the list of user defined +/// function names. +char *get_user_func_name(expand_T *xp, int idx) { static size_t done; static hashitem_T *hi; @@ -2676,11 +2662,11 @@ char_u *get_user_func_name(expand_T *xp, int idx) if ((fp->uf_flags & FC_DICT) || STRNCMP(fp->uf_name, "<lambda>", 8) == 0) { - return (char_u *)""; // don't show dict and lambda functions + return ""; // don't show dict and lambda functions } if (STRLEN(fp->uf_name) + 4 >= IOSIZE) { - return fp->uf_name; // Prevent overflow. + return (char *)fp->uf_name; // Prevent overflow. } cat_func_name(IObuff, fp); @@ -2690,7 +2676,7 @@ char_u *get_user_func_name(expand_T *xp, int idx) STRCAT(IObuff, ")"); } } - return IObuff; + return (char *)IObuff; } return NULL; } @@ -2703,7 +2689,7 @@ void ex_delfunction(exarg_T *eap) char_u *name; funcdict_T fudi; - p = eap->arg; + p = (char_u *)eap->arg; name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); xfree(fudi.fd_newkey); if (name == NULL) { @@ -2712,12 +2698,12 @@ void ex_delfunction(exarg_T *eap) } return; } - if (!ends_excmd(*skipwhite(p))) { + if (!ends_excmd(*skipwhite((char *)p))) { xfree(name); emsg(_(e_trailing)); return; } - eap->nextcmd = check_nextcmd(p); + eap->nextcmd = (char *)check_nextcmd(p); if (eap->nextcmd != NULL) { *p = NUL; } @@ -2770,10 +2756,8 @@ void ex_delfunction(exarg_T *eap) } } -/* - * Unreference a Function: decrement the reference count and free it when it - * becomes zero. - */ +/// Unreference a Function: decrement the reference count and free it when it +/// becomes zero. void func_unref(char_u *name) { ufunc_T *fp = NULL; @@ -2867,12 +2851,10 @@ static int can_free_funccal(funccall_T *fc, int copyID) && fc->fc_copyID != copyID; } -/* - * ":return [expr]" - */ +/// ":return [expr]" void ex_return(exarg_T *eap) { - char_u *arg = eap->arg; + char_u *arg = (char_u *)eap->arg; typval_T rettv; int returning = FALSE; @@ -2887,7 +2869,7 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') - && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { + && eval0((char *)arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -2910,7 +2892,7 @@ void ex_return(exarg_T *eap) if (returning) { eap->nextcmd = NULL; } else if (eap->nextcmd == NULL) { // no argument - eap->nextcmd = check_nextcmd(arg); + eap->nextcmd = (char *)check_nextcmd(arg); } if (eap->skip) { @@ -2920,12 +2902,10 @@ void ex_return(exarg_T *eap) // TODO(ZyX-I): move to eval/ex_cmds -/* - * ":1,25call func(arg1, arg2)" function call. - */ +/// ":1,25call func(arg1, arg2)" function call. void ex_call(exarg_T *eap) { - char_u *arg = eap->arg; + char_u *arg = (char_u *)eap->arg; char_u *startarg; char_u *name; char_u *tofree; @@ -2974,7 +2954,7 @@ void ex_call(exarg_T *eap) // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. - startarg = skipwhite(arg); + startarg = (char_u *)skipwhite((char *)arg); rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { @@ -3011,7 +2991,7 @@ void ex_call(exarg_T *eap) // Handle a function returning a Funcref, Dictionary or List. if (handle_subscript((const char **)&arg, &rettv, true, true, - (const char_u *)name, (const char_u **)&name) + (const char *)name, (const char **)&name) == FAIL) { failed = true; break; @@ -3031,16 +3011,17 @@ void ex_call(exarg_T *eap) } } - // When inside :try we need to check for following "| catch". - if (!failed || eap->cstack->cs_trylevel > 0) { + // 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)) { // Check for trailing illegal characters and a following command. if (!ends_excmd(*arg)) { - if (!failed) { + if (!failed && !aborting()) { emsg_severe = true; emsg(_(e_trailing)); } } else { - eap->nextcmd = check_nextcmd(arg); + eap->nextcmd = (char *)check_nextcmd(arg); } } @@ -3049,14 +3030,16 @@ end: xfree(tofree); } -/* - * Return from a function. Possibly makes the return pending. Also called - * for a pending return at the ":endtry" or after returning from an extra - * do_cmdline(). "reanimate" is used in the latter case. "is_cmd" is set - * when called due to a ":return" command. "rettv" may point to a typval_T - * with the return rettv. Returns TRUE when the return can be carried out, - * FALSE when the return gets pending. - */ +/// Return from a function. Possibly makes the return pending. Also called +/// for a pending return at the ":endtry" or after returning from an extra +/// do_cmdline(). "reanimate" is used in the latter case. +/// +/// @param reanimate used after returning from an extra do_cmdline(). +/// @param is_cmd set when called due to a ":return" command. +/// @param rettv may point to a typval_T with the return rettv. +/// +/// @return TRUE when the return can be carried out, +/// FALSE when the return gets pending. int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) { int idx; @@ -3067,12 +3050,10 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) current_funccal->returned = false; } - // // Cleanup (and deactivate) conditionals, but stop when a try conditional // not in its finally clause (which then is to be executed next) is found. // In this case, make the ":return" pending for execution at the ":endtry". // Otherwise, return normally. - // idx = cleanup_conditionals(eap->cstack, 0, true); if (idx >= 0) { cstack->cs_pending[idx] = CSTP_RETURN; @@ -3125,10 +3106,8 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) return idx < 0; } -/* - * Generate a return command for producing the value of "rettv". The result - * is an allocated string. Used by report_pending() for verbose messages. - */ +/// 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_u *s = NULL; @@ -3150,12 +3129,11 @@ char_u *get_return_cmd(void *rettv) return vim_strsave(IObuff); } -/* - * Get next function line. - * Called by do_cmdline() to get the next line. - * Returns allocated string, or NULL for end of function. - */ -char_u *get_func_line(int c, void *cookie, int indent, bool do_concat) +/// Get next function line. +/// Called by do_cmdline() to get the next line. +/// +/// @return allocated string, or NULL for end of function. +char *get_func_line(int c, void *cookie, int indent, bool do_concat) { funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->func; @@ -3202,13 +3180,11 @@ char_u *get_func_line(int c, void *cookie, int indent, bool do_concat) fcp->dbg_tick = debug_tick; } - return retval; + return (char *)retval; } -/* - * Return TRUE if the currently active function should be ended, because a - * return was encountered or an error occurred. Used inside a ":while". - */ +/// @return TRUE if the currently active function should be ended, because a +/// return was encountered or an error occurred. Used inside a ":while". int func_has_ended(void *cookie) { funccall_T *fcp = (funccall_T *)cookie; @@ -3219,9 +3195,7 @@ int func_has_ended(void *cookie) || fcp->returned; } -/* - * return TRUE if cookie indicates a function which "abort"s on errors. - */ +/// @return TRUE if cookie indicates a function which "abort"s on errors. int func_has_abort(void *cookie) { return ((funccall_T *)cookie)->func->uf_flags & FC_ABORT; @@ -3241,7 +3215,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) fp = rettv->vval.v_partial->pt_func; } else { fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING - ? rettv->vval.v_string + ? (char_u *)rettv->vval.v_string : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. fname = fname_trans_sid(fname, fname_buf, &tofree, &error); @@ -3258,7 +3232,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 = rettv->vval.v_string; + pt->pt_name = (char_u *)rettv->vval.v_string; } else { partial_T *ret_pt = rettv->vval.v_partial; int i; @@ -3274,7 +3248,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) func_ptr_ref(pt->pt_func); } if (ret_pt->pt_argc > 0) { - size_t arg_size = sizeof(typval_T) * ret_pt->pt_argc; + size_t arg_size = sizeof(typval_T) * (size_t)ret_pt->pt_argc; pt->pt_argv = (typval_T *)xmalloc(arg_size); pt->pt_argc = ret_pt->pt_argc; for (i = 0; i < pt->pt_argc; i++) { @@ -3288,41 +3262,31 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) } } -/* - * Return the name of the executed function. - */ +/// @return the name of the executed function. char_u *func_name(void *cookie) { return ((funccall_T *)cookie)->func->uf_name; } -/* - * Return the address holding the next breakpoint line for a funccall cookie. - */ +/// @return the address holding the next breakpoint line for a funccall cookie. linenr_T *func_breakpoint(void *cookie) { return &((funccall_T *)cookie)->breakpoint; } -/* - * Return the address holding the debug tick for a funccall cookie. - */ +/// @return the address holding the debug tick for a funccall cookie. int *func_dbg_tick(void *cookie) { return &((funccall_T *)cookie)->dbg_tick; } -/* - * Return the nesting level for a funccall cookie. - */ +/// @return the nesting level for a funccall cookie. int func_level(void *cookie) { return ((funccall_T *)cookie)->level; } -/* - * Return TRUE when a function was ended by a ":return" command. - */ +/// @return TRUE when a function was ended by a ":return" command. int current_func_returned(void) { return current_funccal->returned; @@ -3371,8 +3335,8 @@ funccall_T *get_funccal(void) return funccal; } -/// Return the hashtable used for local variables in the current funccal. -/// Return NULL if there is no current funccal. +/// @return hashtable used for local variables in the current funccal or +/// NULL if there is no current funccal. hashtab_T *get_funccal_local_ht(void) { if (current_funccal == NULL) { @@ -3381,8 +3345,8 @@ hashtab_T *get_funccal_local_ht(void) return &get_funccal()->l_vars.dv_hashtab; } -/// Return the l: scope variable. -/// Return NULL if there is no current funccal. +/// @return the l: scope variable or +/// NULL if there is no current funccal. dictitem_T *get_funccal_local_var(void) { if (current_funccal == NULL) { @@ -3391,8 +3355,8 @@ dictitem_T *get_funccal_local_var(void) return (dictitem_T *)&get_funccal()->l_vars_var; } -/// Return the hashtable used for argument in the current funccal. -/// Return NULL if there is no current funccal. +/// @return the hashtable used for argument in the current funccal or +/// NULL if there is no current funccal. hashtab_T *get_funccal_args_ht(void) { if (current_funccal == NULL) { @@ -3401,8 +3365,8 @@ hashtab_T *get_funccal_args_ht(void) return &get_funccal()->l_avars.dv_hashtab; } -/// Return the a: scope variable. -/// Return NULL if there is no current funccal. +/// @return the a: scope variable or +/// NULL if there is no current funccal. dictitem_T *get_funccal_args_var(void) { if (current_funccal == NULL) { @@ -3411,9 +3375,7 @@ dictitem_T *get_funccal_args_var(void) return (dictitem_T *)¤t_funccal->l_avars_var; } -/* - * List function variables, if there is a function. - */ +/// List function variables, if there is a function. void list_func_vars(int *first) { if (current_funccal != NULL) { @@ -3422,9 +3384,8 @@ void list_func_vars(int *first) } } -/// If "ht" is the hashtable for local variables in the current funccal, return -/// the dict that contains it. -/// Otherwise return NULL. +/// @return if "ht" is the hashtable for local variables in the current +/// funccal, return the dict that contains it. Otherwise return NULL. dict_T *get_current_funccal_dict(hashtab_T *ht) { if (current_funccal != NULL && ht == ¤t_funccal->l_vars.dv_hashtab) { @@ -3450,7 +3411,7 @@ hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) while (current_funccal != NULL) { hashtab_T *ht = find_var_ht(name, namelen, &varname); if (ht != NULL && *varname != NUL) { - hi = hash_find_len(ht, varname, namelen - (varname - name)); + hi = hash_find_len(ht, varname, namelen - (size_t)(varname - name)); if (!HASHITEM_EMPTY(hi)) { *pht = ht; break; @@ -3588,7 +3549,7 @@ bool set_ref_in_func_args(int copyID) /// "list_stack" is used to add lists to be marked. Can be NULL. /// "ht_stack" is used to add hashtabs to be marked. Can be NULL. /// -/// @return true if setting references failed somehow. +/// @return true if setting references failed somehow. bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) { ufunc_T *fp = fp_in; @@ -3633,5 +3594,6 @@ char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state) STRCPY(fp->uf_name, name); hash_add(&func_hashtab, UF2HIKEY(fp)); + // coverity[leaked_storage] return fp->uf_name; } |