From 88e906d165b5dd57fb13b190ec9cb2d67bc6b223 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 08:52:21 +0800 Subject: vim-patch:9.0.1245: code is indented more than necessary (#21998) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11879) https://github.com/vim/vim/commit/032713f8299abd92fcfb1e490d1ae5c1ecadde41 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 50 ++++++++++++++++--------------- src/nvim/eval/typval.c | 80 ++++++++++++++++++++++++++------------------------ 2 files changed, 68 insertions(+), 62 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5a31288ecd..c527b62c8f 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7823,34 +7823,35 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // MSVC returns NULL for an invalid value of seconds. if (curtime_ptr == NULL) { rettv->vval.v_string = xstrdup(_("(Invalid)")); - } else { - vimconv_T conv; + return; + } - conv.vc_type = CONV_NONE; - char *enc = enc_locale(); - convert_setup(&conv, p_enc, enc); - if (conv.vc_type != CONV_NONE) { - p = string_convert(&conv, p, NULL); - } - char result_buf[256]; - if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) { - result_buf[0] = NUL; - } + vimconv_T conv; - if (conv.vc_type != CONV_NONE) { - xfree(p); - } - convert_setup(&conv, enc, p_enc); - if (conv.vc_type != CONV_NONE) { - rettv->vval.v_string = string_convert(&conv, result_buf, NULL); - } else { - rettv->vval.v_string = xstrdup(result_buf); - } + conv.vc_type = CONV_NONE; + char *enc = enc_locale(); + convert_setup(&conv, p_enc, enc); + if (conv.vc_type != CONV_NONE) { + p = string_convert(&conv, p, NULL); + } + char result_buf[256]; + if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) { + result_buf[0] = NUL; + } - // Release conversion descriptors. - convert_setup(&conv, NULL, NULL); - xfree(enc); + if (conv.vc_type != CONV_NONE) { + xfree(p); } + convert_setup(&conv, enc, p_enc); + if (conv.vc_type != CONV_NONE) { + rettv->vval.v_string = string_convert(&conv, result_buf, NULL); + } else { + rettv->vval.v_string = xstrdup(result_buf); + } + + // Release conversion descriptors. + convert_setup(&conv, NULL, NULL); + xfree(enc); } /// "strgetchar()" function @@ -8654,6 +8655,7 @@ static void f_timer_pause(typval_T *argvars, typval_T *unused, EvalFuncData fptr emsg(_(e_number_exp)); return; } + int paused = (bool)tv_get_number(&argvars[1]); timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); if (timer != NULL) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 05b4737206..c298064d86 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3208,17 +3208,19 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic /// @param[in,out] tv Value to free. void tv_clear(typval_T *const tv) { - if (tv != NULL && tv->v_type != VAR_UNKNOWN) { - // WARNING: do not translate the string here, gettext is slow and function - // is used *very* often. At the current state encode_vim_to_nothing() does - // not error out and does not use the argument anywhere. - // - // If situation changes and this argument will be used, translate it in the - // place where it is used. - const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument"); - (void)evn_ret; - assert(evn_ret == OK); + if (tv == NULL || tv->v_type == VAR_UNKNOWN) { + return; } + + // WARNING: do not translate the string here, gettext is slow and function + // is used *very* often. At the current state encode_vim_to_nothing() does + // not error out and does not use the argument anywhere. + // + // If situation changes and this argument will be used, translate it in the + // place where it is used. + const int evn_ret = encode_vim_to_nothing(NULL, tv, "tv_clear() argument"); + (void)evn_ret; + assert(evn_ret == OK); } //{{{3 Free @@ -3228,35 +3230,37 @@ void tv_clear(typval_T *const tv) /// @param tv Object to free. void tv_free(typval_T *tv) { - if (tv != NULL) { - switch (tv->v_type) { - case VAR_PARTIAL: - partial_unref(tv->vval.v_partial); - break; - case VAR_FUNC: - func_unref(tv->vval.v_string); - FALLTHROUGH; - case VAR_STRING: - xfree(tv->vval.v_string); - break; - case VAR_BLOB: - tv_blob_unref(tv->vval.v_blob); - break; - case VAR_LIST: - tv_list_unref(tv->vval.v_list); - break; - case VAR_DICT: - tv_dict_unref(tv->vval.v_dict); - break; - case VAR_BOOL: - case VAR_SPECIAL: - case VAR_NUMBER: - case VAR_FLOAT: - case VAR_UNKNOWN: - break; - } - xfree(tv); + if (tv == NULL) { + return; + } + + switch (tv->v_type) { + case VAR_PARTIAL: + partial_unref(tv->vval.v_partial); + break; + case VAR_FUNC: + func_unref(tv->vval.v_string); + FALLTHROUGH; + case VAR_STRING: + xfree(tv->vval.v_string); + break; + case VAR_BLOB: + tv_blob_unref(tv->vval.v_blob); + break; + case VAR_LIST: + tv_list_unref(tv->vval.v_list); + break; + case VAR_DICT: + tv_dict_unref(tv->vval.v_dict); + break; + case VAR_BOOL: + case VAR_SPECIAL: + case VAR_NUMBER: + case VAR_FLOAT: + case VAR_UNKNOWN: + break; } + xfree(tv); } //{{{3 Copy -- cgit From 6320c91c50e4c0ee5c366241f9a413c4edbfdad8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 09:58:27 +0800 Subject: vim-patch:9.0.1231: completion of :runtime does not handle {where} argument Problem: Completion of :runtime does not handle {where} argument. Solution: Parse the {where} argument. (closes vim/vim#11863) https://github.com/vim/vim/commit/3770f4c9cde7b5fcd10b6fa2e665cd0b69450fb2 --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c527b62c8f..938fef9a52 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2983,7 +2983,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (file != NULL && !error) { garray_T ga; ga_init(&ga, (int)sizeof(char *), 10); - globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags); + globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags, false); if (rettv->v_type == VAR_STRING) { rettv->vval.v_string = ga_concat_strings_sep(&ga, "\n"); -- cgit From 41aa5ce3eb49705d26137ac2b34f5ad7cd43f2cf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 26 Jan 2023 21:05:34 +0800 Subject: vim-patch:9.0.1246: code is indented more than necessary (#22006) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11887) https://github.com/vim/vim/commit/142ed77898facf8f423fee2717efee1749c55f9a Omit function_using_block_scopes(): only affects Vim9 script. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 22c5b1954d..6c6dc3fa43 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -760,13 +760,12 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) static bool func_remove(ufunc_T *fp) { hashitem_T *hi = hash_find(&func_hashtab, (char *)UF2HIKEY(fp)); - - if (!HASHITEM_EMPTY(hi)) { - hash_remove(&func_hashtab, hi); - return true; + if (HASHITEM_EMPTY(hi)) { + return false; } - return false; + hash_remove(&func_hashtab, hi); + return true; } static void func_clear_items(ufunc_T *fp) -- cgit From 27b81af19c498892f4b0444ad29b7be842f8e7b8 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 30 Jan 2023 19:06:32 +0100 Subject: refactor!: remove has("debug") (#22060) This value can not be relied on as it doesn't work for multi-configuration generators. I don't think this undocumented option is used much, if at all, so I think we should remove it. --- src/nvim/eval/funcs.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 938fef9a52..48f3cd4293 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3064,9 +3064,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "conceal", "cursorbind", "cursorshape", -#ifdef DEBUG - "debug", -#endif "dialog_con", "diff", "digraphs", -- cgit From 4cc0d6b854b44c0b8466e0a84bbc9e350cda8c4f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 1 Feb 2023 21:53:32 +0800 Subject: vim-patch:9.0.1271: using sizeof() and subtract array size is tricky (#22087) Problem: Using sizeof() and subtract array size is tricky. Solution: Use offsetof() instead. (closes vim/vim#11926) https://github.com/vim/vim/commit/1b438a8228a415720efb5ca1c0503f5467292e8e --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3e593151fc..9ed245d6c4 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1347,7 +1347,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // Make sure dict is valid assert(dict != NULL); - v = xmalloc(sizeof(dictitem_T) + strlen(varname)); + v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1); STRCPY(v->di_key, varname); if (hash_add(ht, (char *)v->di_key) == FAIL) { xfree(v); -- cgit From 30b29a36e80bfeed50bb6ea618401fe35100490f Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 9 Feb 2023 20:56:30 +0100 Subject: refactor(ui): remove some superfluous ui_flush() calls - mapping has no business saving and restoring the low-level UI cursor. The cursor will be put in a reasonable position after input is processed, chill out. - TUI handles output needed for suspend - vgetc() family of function does flushing --- src/nvim/eval/userfunc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 6c6dc3fa43..957733ecd5 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2150,8 +2150,7 @@ void ex_function(exarg_T *eap) } } msg_prt_line(FUNCLINE(fp, j), false); - ui_flush(); // show a line at a time - os_breakcheck(); + line_breakcheck(); // show multiple lines at a time! } if (!got_int) { msg_putchar('\n'); -- cgit From 7224c889e0d5d70b99ae377036baa6377c33a568 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 10:25:24 +0100 Subject: build: enable MSVC level 3 warnings (#21934) MSVC has 4 different warning levels: 1 (severe), 2 (significant), 3 (production quality) and 4 (informational). Enabling level 3 warnings mostly revealed conversion problems, similar to GCC/clang -Wconversion flag. --- src/nvim/eval/funcs.c | 39 ++++++++++++++++++++------------------- src/nvim/eval/typval.c | 20 ++++++++++---------- src/nvim/eval/vars.c | 2 +- src/nvim/eval/window.c | 4 ++-- 4 files changed, 33 insertions(+), 32 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 48f3cd4293..884a50a433 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -492,7 +492,7 @@ buf_T *get_buf_arg(typval_T *arg) /// "byte2line(byte)" function static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - long boff = tv_get_number(&argvars[0]) - 1; + long boff = (long)tv_get_number(&argvars[0]) - 1; if (boff < 0) { rettv->vval.v_number = -1; } else { @@ -978,11 +978,11 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) listitem_T *li = tv_list_first(l); if (argvars[2].v_type != VAR_UNKNOWN) { if (argvars[3].v_type != VAR_UNKNOWN) { - long idx = tv_get_number_chk(&argvars[3], &error); + int64_t idx = tv_get_number_chk(&argvars[3], &error); if (!error) { li = tv_list_find(l, (int)idx); if (li == NULL) { - semsg(_(e_listidx), (int64_t)idx); + semsg(_(e_listidx), idx); } } } @@ -3589,7 +3589,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) semsg(_(e_listblobarg), "insert()"); } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), N_("insert() argument"), TV_TRANSLATE)) { - long before = 0; + int64_t before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); } @@ -3602,7 +3602,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (before != tv_list_len(l)) { item = tv_list_find(l, (int)before); if (item == NULL) { - semsg(_(e_listidx), (int64_t)before); + semsg(_(e_listidx), before); l = NULL; } } @@ -4371,11 +4371,11 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { char *str = NULL; - long len = 0; + int64_t len = 0; char *expr = NULL; regmatch_T regmatch; - long start = 0; - long nth = 1; + int64_t start = 0; + int64_t nth = 1; colnr_T startcol = 0; bool match = false; list_T *l = NULL; @@ -5387,7 +5387,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl char *prev = NULL; // previously read bytes, if any ptrdiff_t prevlen = 0; // length of data in prev ptrdiff_t prevsize = 0; // size of prev buffer - long maxline = MAXLNUM; + int64_t maxline = MAXLNUM; if (argvars[1].v_type != VAR_UNKNOWN) { if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { @@ -6161,8 +6161,8 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) { bool save_p_ws = p_ws; int retval = 0; // default: FAIL - long lnum_stop = 0; - long time_limit = 0; + linenr_T lnum_stop = 0; + int64_t time_limit = 0; int options = SEARCH_KEEP; bool use_skip = false; @@ -6184,7 +6184,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) // 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); + lnum_stop = (linenr_T)tv_get_number_chk(&argvars[2], NULL); if (lnum_stop < 0) { goto theend; } @@ -6214,7 +6214,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) pos_T pos = save_cursor = curwin->w_cursor; pos_T firstpos = { 0 }; searchit_arg_T sia = { - .sa_stop_lnum = (linenr_T)lnum_stop, + .sa_stop_lnum = lnum_stop, .sa_tm = &tm, }; @@ -6652,8 +6652,8 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) bool save_p_ws = p_ws; int flags = 0; int retval = 0; // default: FAIL - long lnum_stop = 0; - long time_limit = 0; + linenr_T lnum_stop = 0; + int64_t time_limit = 0; // Get the three pattern arguments: start, middle, end. Will result in an // error if not a valid argument. @@ -6695,7 +6695,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) skip = &argvars[4]; if (argvars[5].v_type != VAR_UNKNOWN) { - lnum_stop = tv_get_number_chk(&argvars[5], NULL); + lnum_stop = (linenr_T)tv_get_number_chk(&argvars[5], NULL); if (lnum_stop < 0) { semsg(_(e_invarg2), tv_get_string(&argvars[5])); goto theend; @@ -6711,7 +6711,7 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } retval = (int)do_searchpair(spat, mpat, epat, dir, skip, - flags, match_pos, (linenr_T)lnum_stop, time_limit); + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -6758,7 +6758,7 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, EvalFuncData fpt /// @returns 0 or -1 for no match, long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir, const typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, - long time_limit) + int64_t time_limit) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { long retval = 0; @@ -8695,7 +8695,8 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!callback_from_typval(&callback, &argvars[1])) { return; } - rettv->vval.v_number = (varnumber_T)timer_start(tv_get_number(&argvars[0]), repeat, &callback); + rettv->vval.v_number = (varnumber_T)timer_start((const long)tv_get_number(&argvars[0]), repeat, + &callback); } /// "timer_stop(timerid)" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c298064d86..6d1c17c97e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -905,14 +905,14 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) return; } - long idx = tv_get_number_chk(&argvars[1], &error); + int64_t idx = tv_get_number_chk(&argvars[1], &error); listitem_T *item; if (error) { // Type error: do nothing, errmsg already given. } else if ((item = tv_list_find(l, (int)idx)) == NULL) { - semsg(_(e_listidx), (int64_t)idx); + semsg(_(e_listidx), idx); } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. @@ -922,11 +922,11 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } else { listitem_T *item2; // Remove range of items, return list with values. - long end = tv_get_number_chk(&argvars[2], &error); + int64_t end = tv_get_number_chk(&argvars[2], &error); if (error) { // Type error: do nothing. } else if ((item2 = tv_list_find(l, (int)end)) == NULL) { - semsg(_(e_listidx), (int64_t)end); + semsg(_(e_listidx), end); } else { int cnt = 0; @@ -1140,7 +1140,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) { ListSortItem *ptrs; long len; - long i; + int i; // Pointer to current info struct used in compare function. Save and restore // the current one for nested calls. @@ -1184,7 +1184,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else { bool error = false; - i = tv_get_number_chk(&argvars[1], &error); + i = (int)tv_get_number_chk(&argvars[1], &error); if (error) { goto theend; // type error; errmsg already given } @@ -2715,7 +2715,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } bool error = false; - long idx = tv_get_number_chk(&argvars[1], &error); + int64_t idx = tv_get_number_chk(&argvars[1], &error); if (!error) { const int len = tv_blob_len(b); @@ -2725,7 +2725,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) idx = len + idx; } if (idx < 0 || idx >= len) { - semsg(_(e_blobidx), (int64_t)idx); + semsg(_(e_blobidx), idx); return; } if (argvars[2].v_type == VAR_UNKNOWN) { @@ -2736,7 +2736,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) b->bv_ga.ga_len--; } else { // Remove range of items, return blob with values. - long end = tv_get_number_chk(&argvars[2], &error); + int64_t end = tv_get_number_chk(&argvars[2], &error); if (error) { return; } @@ -2745,7 +2745,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) end = len + end; } if (end >= len || idx > end) { - semsg(_(e_blobidx), (int64_t)end); + semsg(_(e_blobidx), end); return; } blob_T *const blob = tv_blob_alloc(); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9ed245d6c4..3d9b476863 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -696,7 +696,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo if (!failed) { if (opt_type != gov_string || s != NULL) { - char *err = set_option_value(arg, n, s, scope); + char *err = set_option_value(arg, (long)n, s, scope); arg_end = p; if (err != NULL) { emsg(_(err)); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index f58a0c488a..c1d2e5b38f 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -192,9 +192,9 @@ win_T *find_tabwin(typval_T *wvp, typval_T *tvp) if (wvp->v_type != VAR_UNKNOWN) { if (tvp->v_type != VAR_UNKNOWN) { - long n = tv_get_number(tvp); + int n = (int)tv_get_number(tvp); if (n >= 0) { - tp = find_tabpage((int)n); + tp = find_tabpage(n); } } else { tp = curtab; -- cgit From 4be6c6cf0ddf5e31d4103cb5df06651ba6f4897b Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 11:05:57 +0100 Subject: refactor: replace char_u with char (#21901) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 10 +++++----- src/nvim/eval/userfunc.c | 20 ++++++++++---------- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 884a50a433..6f983d3208 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8769,7 +8769,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tolen = utfc_ptr2len(p); if (idx-- == 0) { cplen = tolen; - cpstr = (char *)p; + cpstr = p; break; } } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6d1c17c97e..9a3a1c3c0f 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -751,8 +751,8 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) } typedef struct { - char_u *s; - char_u *tofree; + char *s; + char *tofree; } Join; /// Join list into a string, helper function @@ -785,7 +785,7 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con sumlen += len; Join *const p = GA_APPEND_VIA_PTR(Join, join_gap); - p->tofree = p->s = (char_u *)s; + p->tofree = p->s = s; line_breakcheck(); }); @@ -806,7 +806,7 @@ static int list_join_inner(garray_T *const gap, list_T *const l, const char *con const Join *const p = ((const Join *)join_gap->ga_data) + i; if (p->s != NULL) { - ga_concat(gap, (char *)p->s); + ga_concat(gap, p->s); } line_breakcheck(); } @@ -1673,7 +1673,7 @@ char *callback_to_string(Callback *cb) } const size_t msglen = 100; - char *msg = (char *)xmallocz(msglen); + char *msg = xmallocz(msglen); switch (cb->type) { case kCallbackFuncref: diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 957733ecd5..2496cbc430 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -880,7 +880,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett fc->rettv = rettv; fc->level = ex_nesting_level; // Check if this function has a breakpoint. - fc->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, (linenr_T)0); + fc->breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); fc->dbg_tick = debug_tick; // Set up fields for closure. @@ -1075,7 +1075,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett bool func_not_yet_profiling_but_should = do_profiling_yes - && !fp->uf_profiling && has_profiling(false, (char *)fp->uf_name, NULL); + && !fp->uf_profiling && has_profiling(false, fp->uf_name, NULL); if (func_not_yet_profiling_but_should) { started_profiling = true; @@ -1669,7 +1669,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) if (fp->uf_name_exp != NULL) { msg_puts((const char *)fp->uf_name_exp); } else { - msg_puts((const char *)fp->uf_name); + msg_puts(fp->uf_name); } msg_putchar('('); int j; @@ -1999,10 +1999,10 @@ static void list_functions(regmatch_T *regmatch) todo--; if ((fp->uf_flags & FC_DEAD) == 0 && (regmatch == NULL - ? (!message_filtered((char *)fp->uf_name) + ? (!message_filtered(fp->uf_name) && !func_name_refcount(fp->uf_name)) : (!isdigit((uint8_t)(*fp->uf_name)) - && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { + && vim_regexec(regmatch, fp->uf_name, 0)))) { list_func_head(fp, false, false); if (changed != func_hashtab.ht_changed) { emsg(_("E454: function list was modified")); @@ -2194,7 +2194,7 @@ void ex_function(exarg_T *eap) j++; } if (arg[j] != NUL) { - emsg_funcname((char *)e_invarg2, arg); + emsg_funcname(e_invarg2, arg); } } // Disallow using the g: dict. @@ -2748,7 +2748,7 @@ char *get_user_func_name(expand_T *xp, int idx) } if (strlen(fp->uf_name) + 4 >= IOSIZE) { - return (char *)fp->uf_name; // Prevent overflow. + return fp->uf_name; // Prevent overflow. } cat_func_name(IObuff, fp); @@ -3228,7 +3228,7 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) // If breakpoints have been added/deleted need to check for it. if (fcp->dbg_tick != debug_tick) { - fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM); + fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); fcp->dbg_tick = debug_tick; } if (do_profiling == PROF_YES) { @@ -3258,9 +3258,9 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) // Did we encounter a breakpoint? if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) { - dbg_breakpoint((char *)fp->uf_name, SOURCING_LNUM); + dbg_breakpoint(fp->uf_name, SOURCING_LNUM); // Find next breakpoint. - fcp->breakpoint = dbg_find_breakpoint(false, (char *)fp->uf_name, SOURCING_LNUM); + fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); fcp->dbg_tick = debug_tick; } -- cgit From 27177e581902967dcf4f2f426464da1b636ca420 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 11 Feb 2023 14:14:24 +0100 Subject: refactor: reduce scope of locals as per the style guide (#22211) --- src/nvim/eval/userfunc.c | 12 ++++-------- src/nvim/eval/vars.c | 16 +++++----------- 2 files changed, 9 insertions(+), 19 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 2496cbc430..3c4cc34464 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -729,7 +729,6 @@ static void cleanup_function_call(funccall_T *fc) /// @param[in] force When true, we are exiting. static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) { - funccall_T **pfc; int i; if (fc == NULL) { @@ -738,7 +737,7 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) fc->fc_refcount--; if (force ? fc->fc_refcount <= 0 : !fc_referenced(fc)) { - for (pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { + for (funccall_T **pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { if (fc == *pfc) { *pfc = fc->caller; free_funccal_contents(fc); @@ -3289,7 +3288,6 @@ int func_has_abort(void *cookie) /// Changes "rettv" in-place. void make_partial(dict_T *const selfdict, typval_T *const rettv) { - char *fname; char *tofree = NULL; ufunc_T *fp; char fname_buf[FLEN_FIXED + 1]; @@ -3298,7 +3296,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) { fp = rettv->vval.v_partial->pt_func; } else { - fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING + char *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING ? rettv->vval.v_string : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. @@ -3319,7 +3317,6 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) pt->pt_name = rettv->vval.v_string; } else { partial_T *ret_pt = rettv->vval.v_partial; - int i; // Partial: copy the function name, use selfdict and copy // args. Can't take over name or args, the partial might @@ -3335,7 +3332,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) 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++) { + for (int i = 0; i < pt->pt_argc; i++) { tv_copy(&ret_pt->pt_argv[i], &pt->pt_argv[i]); } } @@ -3641,14 +3638,13 @@ bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) int error = FCERR_NONE; char fname_buf[FLEN_FIXED + 1]; char *tofree = NULL; - char *fname; bool abort = false; if (name == NULL && fp_in == NULL) { return false; } if (fp_in == NULL) { - fname = fname_trans_sid(name, fname_buf, &tofree, &error); + char *fname = fname_trans_sid(name, fname_buf, &tofree, &error); fp = find_func(fname); } if (fp != NULL) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3d9b476863..d80bdc70f6 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -369,12 +369,10 @@ int ex_let_vars(char *arg_start, typval_T *tv, int copy, int semicolon, int var_ /// @return NULL for an error. const char *skip_var_list(const char *arg, int *var_count, int *semicolon) { - const char *p; - const char *s; - if (*arg == '[') { + const char *s; // "[var, var]": find the matching ']'. - p = arg; + const char *p = arg; for (;;) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' s = skip_var_one((char *)p); @@ -575,7 +573,6 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT { char *arg_end = NULL; - int len; // ":let $VAR = expr": Set environment variable. if (*arg == '$') { @@ -586,7 +583,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo // Find the end of the name. arg++; char *name = arg; - len = get_env_len((const char **)&arg); + int len = get_env_len((const char **)&arg); if (len == 0) { semsg(_(e_invarg2), name - 1); } else { @@ -722,12 +719,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) { emsg(_(e_letunexp)); } else { - char *s; - char *ptofree = NULL; const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { - s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); + char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); if (s != NULL) { ptofree = concat_str(s, p); p = (const char *)ptofree; @@ -861,10 +856,9 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ { int forceit = eap->forceit; int ret = OK; - int cc; if (lp->ll_tv == NULL) { - cc = (uint8_t)(*name_end); + int cc = (uint8_t)(*name_end); *name_end = NUL; // Environment variable, normal name or expanded name. -- cgit From 904d0995837a2569ae640f5253da3dd4569fec6f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:03:28 +0800 Subject: vim-patch:8.2.2449: Vim9: flatten() always changes the list type Problem: Vim9: flatten() always changes the list type. Solution: Disallow using flatten() and add flattennew(). https://github.com/vim/vim/commit/3b690069730805a147d45d92eaca4dc838272d1d Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 41 +++++++++++++++++++++++++++++++++-------- src/nvim/eval/typval.c | 9 ++++----- 2 files changed, 37 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6f983d3208..3a58b90f96 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1870,8 +1870,8 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = cmdstr; } -/// "flatten(list[, {maxdepth}])" function -static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// "flatten()" and "flattennew()" functions +static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) { bool error = false; @@ -1895,13 +1895,38 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } list_T *list = argvars[0].vval.v_list; - if (list != NULL - && !value_check_lock(tv_list_locked(list), - N_("flatten() argument"), - TV_TRANSLATE) - && tv_list_flatten(list, maxdepth) == OK) { - tv_copy(&argvars[0], rettv); + rettv->v_type = VAR_LIST; + rettv->vval.v_list = list; + if (list == NULL) { + return; } + + if (make_copy) { + list = tv_list_copy(NULL, list, true, get_copyID()); + rettv->vval.v_list = list; + if (list == NULL) { + return; + } + } else { + if (value_check_lock(tv_list_locked(list), N_("flatten() argument"), TV_TRANSLATE)) { + return; + } + tv_list_ref(list); + } + + tv_list_flatten(list, maxdepth); +} + +/// "flatten(list[, {maxdepth}])" function +static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + flatten_common(argvars, rettv, false); +} + +/// "flattennew(list[, {maxdepth}])" function +static void f_flattennew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + flatten_common(argvars, rettv, true); } /// "extend(list, list [, idx])" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9a3a1c3c0f..ab4245b59a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -654,14 +654,14 @@ tv_list_copy_error: /// @param[in] maxdepth Maximum depth that will be flattened /// /// @return OK or FAIL -int tv_list_flatten(list_T *list, long maxdepth) - FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_WARN_UNUSED_RESULT +void tv_list_flatten(list_T *list, long maxdepth) + FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; listitem_T *to_free; int n; if (maxdepth == 0) { - return OK; + return; } n = 0; @@ -669,7 +669,7 @@ int tv_list_flatten(list_T *list, long maxdepth) while (item != NULL) { fast_breakcheck(); if (got_int) { - return FAIL; + return; } if (item->li_tv.v_type == VAR_LIST) { listitem_T *next = item->li_next; @@ -695,7 +695,6 @@ int tv_list_flatten(list_T *list, long maxdepth) item = item->li_next; } } - return OK; } /// Extend first list with the second -- cgit From d9263688bf0282918f5a9801dae8b85e4c85bd7e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:24:38 +0800 Subject: vim-patch:8.2.4627: flatten() does not use maxdepth correctly Problem: flatten() does not use maxdepth correctly. Solution: Use a recursive implementation. (closes vim/vim#10020) https://github.com/vim/vim/commit/acf7d73a7f5cdd63b34de777a4ce5eb3e2ba0ab3 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 42 ++++++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 21 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3a58b90f96..6ac94706c7 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1914,7 +1914,7 @@ static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) tv_list_ref(list); } - tv_list_flatten(list, maxdepth); + tv_list_flatten(list, NULL, tv_list_len(list), maxdepth); } /// "flatten(list[, {maxdepth}])" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ab4245b59a..125a4310d8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -647,53 +647,55 @@ tv_list_copy_error: return NULL; } -/// Flatten "list" in place to depth "maxdepth". +/// Flatten up to "maxitems" in "list", starting at "first" to depth "maxdepth". +/// When "first" is NULL use the first item. /// Does nothing if "maxdepth" is 0. /// /// @param[in,out] list List to flatten /// @param[in] maxdepth Maximum depth that will be flattened /// /// @return OK or FAIL -void tv_list_flatten(list_T *list, long maxdepth) +void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdepth) FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; listitem_T *to_free; - int n; + int done = 0; if (maxdepth == 0) { return; } - n = 0; - item = list->lv_first; - while (item != NULL) { + if (first == NULL) { + item = list->lv_first; + } else { + item = first; + } + + while (item != NULL && done < maxitems) { + listitem_T *next = item->li_next; + fast_breakcheck(); if (got_int) { return; } if (item->li_tv.v_type == VAR_LIST) { - listitem_T *next = item->li_next; + list_T *itemlist = item->li_tv.vval.v_list; tv_list_drop_items(list, item, item); - tv_list_extend(list, item->li_tv.vval.v_list, next); + tv_list_extend(list, itemlist, next); tv_clear(&item->li_tv); to_free = item; - if (item->li_prev == NULL) { - item = list->lv_first; - } else { - item = item->li_prev->li_next; + if (maxdepth > 0) { + tv_list_flatten(list, + item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, + itemlist->lv_len, maxdepth - 1); } xfree(to_free); - - if (++n >= maxdepth) { - n = 0; - item = next; - } - } else { - n = 0; - item = item->li_next; } + + done++; + item = next; } } -- cgit From ec2557236710f3e062164e7ff4b137b2a0d8dfa4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:31:43 +0800 Subject: vim-patch:8.2.4629: flattennew() makes a deep copy unnecessarily Problem: flattennew() makes a deep copy unnecessarily. Solution: Use a shallow copy. (issue vim/vim#10012) https://github.com/vim/vim/commit/c6c1ec4da53db9d292fa3dd081c20123f8261178 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6ac94706c7..f1852f1b6d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1902,7 +1902,7 @@ static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) } if (make_copy) { - list = tv_list_copy(NULL, list, true, get_copyID()); + list = tv_list_copy(NULL, list, false, get_copyID()); rettv->vval.v_list = list; if (list == NULL) { return; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 125a4310d8..9faf19c364 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -659,7 +659,6 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; - listitem_T *to_free; int done = 0; if (maxdepth == 0) { return; @@ -684,14 +683,13 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep tv_list_drop_items(list, item, item); tv_list_extend(list, itemlist, next); tv_clear(&item->li_tv); - to_free = item; if (maxdepth > 0) { tv_list_flatten(list, item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, itemlist->lv_len, maxdepth - 1); } - xfree(to_free); + xfree(item); } done++; -- cgit From c76dfe14b1422a1caccf13c3bc86754902eb0302 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 15:33:51 +0800 Subject: vim-patch:8.2.4632: using freed memory in flatten() Problem: Using freed memory in flatten(). Solution: Clear typval after recursing into list. https://github.com/vim/vim/commit/f3980dc5d0a5f873cf764b8ba3e567e42259e4e5 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9faf19c364..17499480ed 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -682,13 +682,13 @@ void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdep tv_list_drop_items(list, item, item); tv_list_extend(list, itemlist, next); - tv_clear(&item->li_tv); if (maxdepth > 0) { tv_list_flatten(list, item->li_prev == NULL ? list->lv_first : item->li_prev->li_next, itemlist->lv_len, maxdepth - 1); } + tv_clear(&item->li_tv); xfree(item); } -- cgit From 0972d7a12468d6914a70e453af85c307b167c55b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:13:12 +0800 Subject: vim-patch:9.0.0196: finding value in list may require a for loop Problem: Finding value in list may require a for loop. Solution: Add indexof(). (Yegappan Lakshmanan, closes vim/vim#10903) https://github.com/vim/vim/commit/b218655d5a485f5b193fb18d7240837d42b89812 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++ src/nvim/eval/typval.c | 50 +++++++++++++++++++++++ 2 files changed, 159 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f1852f1b6d..980a9fffa3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3488,6 +3488,115 @@ static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } +/// Evaluate "expr" with the v:key and v:val arguments and return the result. +/// The expression is expected to return a boolean value. The caller should set +/// the VV_KEY and VV_VAL vim variables before calling this function. +static varnumber_T indexof_eval_expr(typval_T *expr) +{ + typval_T argv[3]; + argv[0] = *get_vim_var_tv(VV_KEY); + argv[1] = *get_vim_var_tv(VV_VAL); + typval_T newtv; + newtv.v_type = VAR_UNKNOWN; + + if (eval_expr_typval(expr, argv, 2, &newtv) == FAIL) { + return false; + } + + bool error = false; + varnumber_T found = tv_get_bool_chk(&newtv, &error); + + return error ? false : found; +} + +/// "indexof()" function +static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; + + if (tv_check_for_list_or_blob_arg(argvars, 0) == FAIL + || tv_check_for_string_or_func_arg(argvars, 1) == FAIL + || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) { + return; + } + + if ((argvars[1].v_type == VAR_STRING && argvars[1].vval.v_string == NULL) + || (argvars[1].v_type == VAR_FUNC && argvars[1].vval.v_partial == NULL)) { + return; + } + + varnumber_T startidx = 0; + varnumber_T idx = 0; + if (argvars[2].v_type == VAR_DICT) { + startidx = tv_dict_get_number_def(argvars[2].vval.v_dict, "startidx", 0); + } + + typval_T save_val; + typval_T save_key; + prepare_vimvar(VV_VAL, &save_val); + prepare_vimvar(VV_KEY, &save_key); + + // We reset "did_emsg" to be able to detect whether an error occurred + // during evaluation of the expression. + const int save_did_emsg = did_emsg; + did_emsg = false; + + if (argvars[0].v_type == VAR_BLOB) { + blob_T *const b = argvars[0].vval.v_blob; + if (b == NULL) { + goto theend; + } + if (startidx < 0) { + startidx = tv_blob_len(b) + startidx; + if (startidx < 0) { + startidx = 0; + } + } + + for (idx = startidx; idx < tv_blob_len(b); idx++) { + set_vim_var_nr(VV_KEY, idx); + set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); + + if (indexof_eval_expr(&argvars[1])) { + rettv->vval.v_number = idx; + break; + } + } + } else { + list_T *const l = argvars[0].vval.v_list; + if (l == NULL) { + goto theend; + } + + listitem_T *item; + if (startidx == 0) { + item = tv_list_first(l); + } else { + // Start at specified item. Use the cached index that list_find() + // sets, so that a negative number also works. + item = tv_list_find(l, (int)startidx); + if (item != NULL) { + idx = l->lv_idx; + } + } + + for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { + set_vim_var_nr(VV_KEY, idx); + tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); + + if (indexof_eval_expr(&argvars[1])) { + rettv->vval.v_number = idx; + break; + } + } + } + +theend: + restore_vimvar(VV_KEY, &save_key); + restore_vimvar(VV_VAL, &save_val); + did_emsg |= save_did_emsg; +} + static bool inputsecret_flag = false; /// "input()" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 17499480ed..0a30cdb62e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -44,10 +44,16 @@ static char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); static char e_non_empty_string_required_for_argument_nr[] = N_("E1175: Non-empty string required for argument %d"); +static char e_dict_required_for_argument_nr[] + = N_("E1206: Dictionary required for argument %d"); static char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); static char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); +static char e_list_or_blob_required_for_argument_nr[] + = N_("E1226: List or Blob required for argument %d"); +static char e_string_or_function_required_for_argument_nr[] + = N_("E1256: String or function required for argument %d"); bool tv_in_free_unref_items = false; @@ -3905,6 +3911,25 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a dict. +int tv_check_for_dict_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_DICT) { + semsg(_(e_dict_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Check for an optional dict argument at "idx" +int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return (args[idx].v_type == VAR_UNKNOWN + || tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL; +} + /// Give an error and return FAIL unless "args[idx]" is a string or a list. int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE @@ -3916,6 +3941,31 @@ int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) return OK; } +/// Give an error and return FAIL unless "args[idx]" is a string +/// or a function reference. +int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_PARTIAL + && args[idx].v_type != VAR_FUNC + && args[idx].v_type != VAR_STRING) { + semsg(_(e_string_or_function_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Give an error and return FAIL unless "args[idx]" is a list or a blob. +int tv_check_for_list_or_blob_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_LIST && args[idx].v_type != VAR_BLOB) { + semsg(_(e_list_or_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Get the string value of a "stringish" VimL object. /// /// @param[in] tv Object to get value of. -- cgit From 13da3d469ae10201de00ae89277c53c40342f4df Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Feb 2023 23:50:35 +0800 Subject: vim-patch:partial:9.0.0202: code and help for indexof() is not ideal Problem: Code and help for indexof() is not ideal. Solution: Refactor the code, improve the help. (Yegappan Lakshmanan, closes vim/vim#10908) https://github.com/vim/vim/commit/3fbf6cd355de2212e9227f57d545592aae3f688f Skip CHECK_LIST_MATERIALIZE and set_vim_var_type(). Use tv_list_uidx() instead of lv_idx. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 115 +++++++++++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 48 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 980a9fffa3..8070dacc48 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3509,6 +3509,71 @@ static varnumber_T indexof_eval_expr(typval_T *expr) return error ? false : found; } +/// Evaluate "expr" for each byte in the Blob "b" starting with the byte at +/// "startidx" and return the index of the byte where "expr" is TRUE. Returns +/// -1 if "expr" doesn't evaluate to TRUE for any of the bytes. +static varnumber_T indexof_blob(blob_T *b, varnumber_T startidx, typval_T *expr) +{ + if (b == NULL) { + return -1; + } + + if (startidx < 0) { + // negative index: index from the last byte + startidx = tv_blob_len(b) + startidx; + if (startidx < 0) { + startidx = 0; + } + } + + for (varnumber_T idx = startidx; idx < tv_blob_len(b); idx++) { + set_vim_var_nr(VV_KEY, idx); + set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); + + if (indexof_eval_expr(expr)) { + return idx; + } + } + + return -1; +} + +/// Evaluate "expr" for each item in the List "l" starting with the item at +/// "startidx" and return the index of the item where "expr" is TRUE. Returns +/// -1 if "expr" doesn't evaluate to TRUE for any of the items. +static varnumber_T indexof_list(list_T *l, varnumber_T startidx, typval_T *expr) +{ + if (l == NULL) { + return -1; + } + + listitem_T *item; + varnumber_T idx = 0; + if (startidx == 0) { + item = tv_list_first(l); + } else { + // Start at specified item. + idx = tv_list_uidx(l, (int)startidx); + if (idx == -1) { + item = NULL; + } else { + item = tv_list_find(l, (int)idx); + assert(item != NULL); + } + } + + for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { + set_vim_var_nr(VV_KEY, idx); + tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); + + if (indexof_eval_expr(expr)) { + return idx; + } + } + + return -1; +} + /// "indexof()" function static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3526,7 +3591,6 @@ static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } varnumber_T startidx = 0; - varnumber_T idx = 0; if (argvars[2].v_type == VAR_DICT) { startidx = tv_dict_get_number_def(argvars[2].vval.v_dict, "startidx", 0); } @@ -3542,56 +3606,11 @@ static void f_indexof(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) did_emsg = false; if (argvars[0].v_type == VAR_BLOB) { - blob_T *const b = argvars[0].vval.v_blob; - if (b == NULL) { - goto theend; - } - if (startidx < 0) { - startidx = tv_blob_len(b) + startidx; - if (startidx < 0) { - startidx = 0; - } - } - - for (idx = startidx; idx < tv_blob_len(b); idx++) { - set_vim_var_nr(VV_KEY, idx); - set_vim_var_nr(VV_VAL, tv_blob_get(b, (int)idx)); - - if (indexof_eval_expr(&argvars[1])) { - rettv->vval.v_number = idx; - break; - } - } + rettv->vval.v_number = indexof_blob(argvars[0].vval.v_blob, startidx, &argvars[1]); } else { - list_T *const l = argvars[0].vval.v_list; - if (l == NULL) { - goto theend; - } - - listitem_T *item; - if (startidx == 0) { - item = tv_list_first(l); - } else { - // Start at specified item. Use the cached index that list_find() - // sets, so that a negative number also works. - item = tv_list_find(l, (int)startidx); - if (item != NULL) { - idx = l->lv_idx; - } - } - - for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { - set_vim_var_nr(VV_KEY, idx); - tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); - - if (indexof_eval_expr(&argvars[1])) { - rettv->vval.v_number = idx; - break; - } - } + rettv->vval.v_number = indexof_list(argvars[0].vval.v_list, startidx, &argvars[1]); } -theend: restore_vimvar(VV_KEY, &save_key); restore_vimvar(VV_VAL, &save_val); did_emsg |= save_did_emsg; -- cgit From 1f8cef53deb4b91a7249affca77bfb89ce0949b4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Feb 2023 00:00:01 +0800 Subject: vim-patch:9.0.0204: indexof() may leak memory Problem: indexof() may leak memory. Solution: Free allocated values. (Yegappan Lakshmanan, closes vim/vim#10916) https://github.com/vim/vim/commit/63acae13f57c5ad4c8ec3146d0c458550b9e984e Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8070dacc48..13d8f52768 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3505,6 +3505,7 @@ static varnumber_T indexof_eval_expr(typval_T *expr) bool error = false; varnumber_T found = tv_get_bool_chk(&newtv, &error); + tv_clear(&newtv); return error ? false : found; } @@ -3566,7 +3567,10 @@ static varnumber_T indexof_list(list_T *l, varnumber_T startidx, typval_T *expr) set_vim_var_nr(VV_KEY, idx); tv_copy(TV_LIST_ITEM_TV(item), get_vim_var_tv(VV_VAL)); - if (indexof_eval_expr(expr)) { + bool found = indexof_eval_expr(expr); + tv_clear(get_vim_var_tv(VV_VAL)); + + if (found) { return idx; } } -- cgit From 2c9fbe34b20266ef5ab54f6ed14fb38eef60430d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Feb 2023 10:10:42 +0800 Subject: vim-patch:8.2.2336: Vim9: not possible to extend dictionary with different type (#22425) Problem: Vim9: it is not possible to extend a dictionary with different item types. Solution: Add extendnew(). (closes vim/vim#7666) https://github.com/vim/vim/commit/b0e6b513648db7035046613431a4aa9d71ef4653 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 70 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 56 insertions(+), 14 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 13d8f52768..1baf96e281 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1929,18 +1929,22 @@ static void f_flattennew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) flatten_common(argvars, rettv, true); } -/// "extend(list, list [, idx])" function -/// "extend(dict, dict [, action])" function -static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// "extend()" or "extendnew()" function. "is_new" is true for extendnew(). +static void extend(typval_T *argvars, typval_T *rettv, char *arg_errmsg, bool is_new) { - const char *const arg_errmsg = N_("extend() argument"); - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { bool error = false; - list_T *const l1 = argvars[0].vval.v_list; + list_T *l1 = argvars[0].vval.v_list; list_T *const l2 = argvars[1].vval.v_list; - if (!value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + l1 = tv_list_copy(NULL, l1, false, get_copyID()); + if (l1 == NULL) { + return; + } + } + listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { long before = (long)tv_get_number_chk(&argvars[2], &error); @@ -1962,11 +1966,18 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } tv_list_extend(l1, l2, item); - tv_copy(&argvars[0], rettv); + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval.v_list = l1, + }; + } else { + tv_copy(&argvars[0], rettv); + } } - } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == - VAR_DICT) { - dict_T *const d1 = argvars[0].vval.v_dict; + } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { + dict_T *d1 = argvars[0].vval.v_dict; dict_T *const d2 = argvars[1].vval.v_dict; if (d1 == NULL) { const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); @@ -1975,7 +1986,14 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else if (d2 == NULL) { // Do nothing tv_copy(&argvars[0], rettv); - } else if (!value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + d1 = tv_dict_copy(NULL, d1, false, get_copyID()); + if (d1 == NULL) { + return; + } + } + const char *action = "force"; // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { @@ -1999,13 +2017,37 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_dict_extend(d1, d2, action); - tv_copy(&argvars[0], rettv); + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval.v_dict = d1, + }; + } else { + tv_copy(&argvars[0], rettv); + } } } else { - semsg(_(e_listdictarg), "extend()"); + semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()"); } } +/// "extend(list, list [, idx])" function +/// "extend(dict, dict [, action])" function +static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char *errmsg = N_("extend() argument"); + extend(argvars, rettv, errmsg, false); +} + +/// "extendnew(list, list [, idx])" function +/// "extendnew(dict, dict [, action])" function +static void f_extendnew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char *errmsg = N_("extendnew() argument"); + extend(argvars, rettv, errmsg, true); +} + /// "feedkeys()" function static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From ce597235a26839826de88ecd8b949ec54c310fbd Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Mon, 27 Feb 2023 16:31:05 +0100 Subject: feat(ui): restore has('gui_running') Problem: has('gui_running') is still common in the wild and our answer has changed over time, causing frustration. https://github.com/vimpostor/vim-tpipeline/commit/95a6ccbe9f33bc42dd4cee45731d8bc3fbcd92d1 Solution: Use stdin_tty/stdout_tty to decide if a UI is (not) a GUI. --- src/nvim/eval/funcs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1baf96e281..d97f7b6d35 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3228,7 +3228,9 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (!n) { - if (STRNICMP(name, "patch", 5) == 0) { + if (STRNICMP(name, "gui_running", 11) == 0) { + n = ui_gui_attached(); + } else if (STRNICMP(name, "patch", 5) == 0) { if (name[5] == '-' && strlen(name) >= 11 && ascii_isdigit(name[6]) -- cgit From adfa55ba99febaa1eb5ebe1800ec5f94c4b4b664 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 24 Feb 2023 14:36:20 +0800 Subject: vim-patch:8.2.2757: Vim9: blob tests for legacy and Vim9 script are separate Problem: Vim9: blob tests for legacy and Vim9 script are separate. Solution: Add CheckLegacyAndVim9Success(). Make blob index assign work. https://github.com/vim/vim/commit/68452177ca4cda4a9d5f93892e437447cf9404c8 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 0a30cdb62e..476faafb77 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2710,6 +2710,22 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } +/// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". +/// Caller must make sure "src" is a blob. +/// Returns FAIL if the number of bytes does not match. +int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) +{ + if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { + emsg(_("E972: Blob value does not have the right number of bytes")); + return FAIL; + } + + for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { + tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); + } + return OK; +} + /// "remove({blob})" function void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) { -- cgit From c554e989786be30fa306efcd7e504ba7cb97cb3b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 13:30:08 +0800 Subject: vim-patch:8.2.2765: Vim9: not all blob operations work Problem: Vim9: not all blob operations work. Solution: Run more tests also with Vim9 script and :def functions. Fix what doesn't work. https://github.com/vim/vim/commit/0e3ff1919603ee4c4a347fdf761dbdbdeb068015 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 476faafb77..878b85c49c 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2710,6 +2710,30 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } +/// Check if "n1" is a valid index for a blob with length "bloblen". +int tv_blob_check_index(int bloblen, varnumber_T n1, int is_range, bool quiet) +{ + if (n1 < 0 || n1 > bloblen) { + if (!quiet) { + semsg(_(e_blobidx), n1); + } + return FAIL; + } + return OK; +} + +/// Check if "n1"-"n2" is a valid range for a blob with length "bloblen". +int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) +{ + if (n2 < 0 || n2 >= bloblen || n2 < n1) { + if (!quiet) { + semsg(_(e_blobidx), n2); + } + return FAIL; + } + return OK; +} + /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. -- cgit From 1f1227f12b69616484cc0f8b49d555df4a94678b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 13:39:59 +0800 Subject: vim-patch:8.2.2767: compiler warning for unused argument Problem: Compiler warning for unused argument. Solution: Remove the argument. https://github.com/vim/vim/commit/bd6406f15db210b78fa24dece3bd021a7ac085dc Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 878b85c49c..7e94e03823 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2711,7 +2711,7 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) } /// Check if "n1" is a valid index for a blob with length "bloblen". -int tv_blob_check_index(int bloblen, varnumber_T n1, int is_range, bool quiet) +int tv_blob_check_index(int bloblen, varnumber_T n1, bool quiet) { if (n1 < 0 || n1 > bloblen) { if (!quiet) { -- cgit From 761a559dbfed99e588d7f306c89331907b2d5a92 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 14:27:47 +0800 Subject: vim-patch:8.2.2777: Vim9: blob operations not tested in all ways Problem: Vim9: blob operations not tested in all ways. Solution: Run tests with CheckLegacyAndVim9Success(). Make blob assign with index work. https://github.com/vim/vim/commit/51e933261b984db014e858d79387a826d2626fb6 Cherry-pick related changes from patches 8.2.{0633,0634}. N/A patches for version.c: vim-patch:8.2.2779: memory access error in remove() for blob Problem: Memory access error in remove() for blob. Solution: Adjust length for memmove(). https://github.com/vim/vim/commit/f7e92aae1581203306a340b4c0059cc74adea9d6 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 17 +++++++++++++++++ src/nvim/eval/typval.h | 6 +++--- 2 files changed, 20 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7e94e03823..d56efe30da 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2750,6 +2750,23 @@ int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) return OK; } +/// Store one byte "byte" in blob "blob" at "idx". +/// Append one byte if needed. +void tv_blob_set_append(blob_T *blob, int idx, uint8_t byte) +{ + garray_T *gap = &blob->bv_ga; + + // Allow for appending a byte. Setting a byte beyond + // the end is an error otherwise. + if (idx <= gap->ga_len) { + if (idx == gap->ga_len) { + ga_grow(gap, 1); + gap->ga_len++; + } + tv_blob_set(blob, idx, byte); + } +} + /// "remove({blob})" function void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) { diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 3f59cd3547..4a2654f03e 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -372,7 +372,7 @@ static inline uint8_t tv_blob_get(const blob_T *const b, int idx) return ((uint8_t *)b->bv_ga.ga_data)[idx]; } -static inline void tv_blob_set(blob_T *b, int idx, uint8_t c) +static inline void tv_blob_set(blob_T *blob, int idx, uint8_t c) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL; /// Store the byte `c` at index `idx` in the blob. @@ -380,9 +380,9 @@ static inline void tv_blob_set(blob_T *b, int idx, uint8_t c) /// @param[in] b Blob to index. Cannot be NULL. /// @param[in] idx Index in a blob. Must be valid. /// @param[in] c Value to store. -static inline void tv_blob_set(blob_T *const b, int idx, uint8_t c) +static inline void tv_blob_set(blob_T *const blob, int idx, uint8_t c) { - ((uint8_t *)b->bv_ga.ga_data)[idx] = c; + ((uint8_t *)blob->bv_ga.ga_data)[idx] = c; } /// Initialize VimL object -- cgit From 88b70e7d4650795210222a598cbb233bf7fc98f8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 15:50:35 +0800 Subject: vim-patch:8.2.2782: Vim9: blob operations not fully tested Problem: Vim9: blob operations not fully tested. Solution: Make more blob tests run in Vim9 script. Fix filter(). Make insert() give an error for a null blob, like add(). https://github.com/vim/vim/commit/39211cba723a2cb58a97c7e08826713164b86efc vim-patch:8.2.3284: no error for insert() or remove() changing a locked blob Problem: No error for insert() or remove() changing a locked blob. Solution: Check a blob is not locked before changing it. (Sean Dewar, closes vim/vim#8696) https://github.com/vim/vim/commit/80d7395dcfe96158428da6bb3d28a6eee1244e28 Co-authored-by: Bram Moolenaar Co-authored-by: Sean Dewar --- src/nvim/eval/funcs.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1baf96e281..20e590a30c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3743,7 +3743,6 @@ static void f_inputsecret(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "insert()" function static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - list_T *l; bool error = false; if (argvars[0].v_type == VAR_BLOB) { @@ -3786,8 +3785,12 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_copy(&argvars[0], rettv); } else if (argvars[0].v_type != VAR_LIST) { semsg(_(e_listblobarg), "insert()"); - } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - N_("insert() argument"), TV_TRANSLATE)) { + } else { + list_T *l = argvars[0].vval.v_list; + if (value_check_lock(tv_list_locked(l), N_("insert() argument"), TV_TRANSLATE)) { + return; + } + int64_t before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); -- cgit From bfa0bc7df0ca527fcec49dbd2055f1bac438663e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 19:04:32 +0800 Subject: vim-patch:9.0.0795: readblob() always reads the whole file Problem: readblob() always reads the whole file. Solution: Add arguments to read part of the file. (Ken Takata, closes vim/vim#11402) https://github.com/vim/vim/commit/11df3aeee548b959ccd4b9a4d3c44651eab6b3ce Remove trailing whitespace in test as done in patch 9.0.1257. Move the help for rand() before range(). Co-authored-by: K.Takata --- src/nvim/eval/funcs.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d3bac14754..5da6233e38 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5592,15 +5592,24 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl ptrdiff_t prevlen = 0; // length of data in prev ptrdiff_t prevsize = 0; // size of prev buffer int64_t maxline = MAXLNUM; + off_T offset = 0; + off_T size = -1; if (argvars[1].v_type != VAR_UNKNOWN) { - if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { - binary = true; - } else if (strcmp(tv_get_string(&argvars[1]), "B") == 0) { - blob = true; - } - if (argvars[2].v_type != VAR_UNKNOWN) { - maxline = tv_get_number(&argvars[2]); + if (always_blob) { + offset = (off_T)tv_get_number(&argvars[1]); + if (argvars[2].v_type != VAR_UNKNOWN) { + size = (off_T)tv_get_number(&argvars[2]); + } + } else { + if (strcmp(tv_get_string(&argvars[1]), "b") == 0) { + binary = true; + } else if (strcmp(tv_get_string(&argvars[1]), "B") == 0) { + blob = true; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + maxline = tv_get_number(&argvars[2]); + } } } @@ -5619,11 +5628,8 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl if (blob) { tv_blob_alloc_ret(rettv); - if (!read_blob(fd, rettv->vval.v_blob)) { + if (read_blob(fd, rettv, offset, size) == FAIL) { semsg(_(e_notread), fname); - // An empty blob is returned on error. - tv_blob_free(rettv->vval.v_blob); - rettv->vval.v_blob = NULL; } fclose(fd); return; -- cgit From f6b9791212e86bac3e8128035dec2bfc5016927f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 20:18:52 +0800 Subject: vim-patch:8.2.3438: cannot manipulate blobs Problem: Cannot manipulate blobs. Solution: Add blob2list() and list2blob(). (Yegappan Lakshmanan, closes vim/vim#8868) https://github.com/vim/vim/commit/5dfe467432638fac2e0156a2f9cd0d9eb569fb39 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d56efe30da..6037536548 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -48,10 +48,16 @@ static char e_dict_required_for_argument_nr[] = N_("E1206: Dictionary required for argument %d"); static char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); +static char e_list_required_for_argument_nr[] + = N_("E1211: List required for argument %d"); static char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); static char e_list_or_blob_required_for_argument_nr[] = N_("E1226: List or Blob required for argument %d"); +static char e_blob_required_for_argument_nr[] + = N_("E1238: Blob required for argument %d"); +static char e_invalid_value_for_blob_nr[] + = N_("E1239: Invalid value for blob: %d"); static char e_string_or_function_required_for_argument_nr[] = N_("E1256: String or function required for argument %d"); @@ -2826,6 +2832,51 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } } +/// blob2list() function +void f_blob2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, kListLenMayKnow); + + if (tv_check_for_blob_arg(argvars, 0) == FAIL) { + return; + } + + blob_T *const blob = argvars->vval.v_blob; + list_T *const l = rettv->vval.v_list; + for (int i = 0; i < tv_blob_len(blob); i++) { + tv_list_append_number(l, tv_blob_get(blob, i)); + } +} + +/// list2blob() function +void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_blob_alloc_ret(rettv); + blob_T *const blob = rettv->vval.v_blob; + + if (tv_check_for_list_arg(argvars, 0) == FAIL) { + return; + } + + list_T *const l = argvars->vval.v_list; + if (l == NULL) { + return; + } + + TV_LIST_ITER_CONST(l, li, { + bool error = false; + varnumber_T n = tv_get_number_chk(TV_LIST_ITEM_TV(li), &error); + if (error || n < 0 || n > 255) { + if (!error) { + semsg(_(e_invalid_value_for_blob_nr), n); + } + ga_clear(&blob->bv_ga); + return; + } + ga_append(&blob->bv_ga, (uint8_t)n); + }); +} + //{{{1 Generic typval operations //{{{2 Init/alloc/clear //{{{3 Alloc @@ -3968,6 +4019,28 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a blob. +int tv_check_for_blob_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_BLOB) { + semsg(_(e_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Give an error and return FAIL unless "args[idx]" is a list. +int tv_check_for_list_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_LIST) { + semsg(_(e_list_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Give an error and return FAIL unless "args[idx]" is a dict. int tv_check_for_dict_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE -- cgit From 278aeee3aed753d1084597378e653395bd472c42 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Feb 2023 21:07:56 +0800 Subject: vim-patch:9.0.0430: cannot use repeat() with a blob Problem: Cannot use repeat() with a blob. Solution: Implement blob repeat. (closes vim/vim#11090) https://github.com/vim/vim/commit/375141e1f80dced9be738568a3418f65813f4a2f Co-authored-by: Bakudankun --- src/nvim/eval/funcs.c | 31 +++++++++++++++++++++++++++++++ src/nvim/eval/typval.c | 4 ++-- 2 files changed, 33 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5da6233e38..4208c5ca46 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5976,6 +5976,37 @@ static void f_repeat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) while (n-- > 0) { tv_list_extend(rettv->vval.v_list, argvars[0].vval.v_list, NULL); } + } else if (argvars[0].v_type == VAR_BLOB) { + tv_blob_alloc_ret(rettv); + if (argvars[0].vval.v_blob == NULL || n <= 0) { + return; + } + + const int slen = argvars[0].vval.v_blob->bv_ga.ga_len; + const int len = (int)(slen * n); + if (len <= 0) { + return; + } + + ga_grow(&rettv->vval.v_blob->bv_ga, len); + + rettv->vval.v_blob->bv_ga.ga_len = len; + + int i; + for (i = 0; i < slen; i++) { + if (tv_blob_get(argvars[0].vval.v_blob, i) != 0) { + break; + } + } + + if (i == slen) { + // No need to copy since all bytes are already zero + return; + } + + for (i = 0; i < n; i++) { + tv_blob_set_range(rettv->vval.v_blob, i * slen, (i + 1) * slen - 1, argvars); + } } else { rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6037536548..7d49049b0c 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2743,14 +2743,14 @@ int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. -int tv_blob_set_range(blob_T *dest, long n1, long n2, typval_T *src) +int tv_blob_set_range(blob_T *dest, int n1, int n2, typval_T *src) { if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { emsg(_("E972: Blob value does not have the right number of bytes")); return FAIL; } - for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { + for (int il = n1, ir = 0; il <= n2; il++) { tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); } return OK; -- cgit From c9b6db45417ecbd178f0c6106f4033c760cc75df Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 27 Feb 2023 19:46:39 +0100 Subject: refactor(build): graduate msgpack-c FLOAT32 "feature" since forever --- src/nvim/eval/decode.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index cd1479f150..f57d06c83b 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -987,12 +987,8 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) tv_list_append_number(list, (varnumber_T)(n & 0x7FFFFFFF)); } break; -#ifdef NVIM_MSGPACK_HAS_FLOAT32 case MSGPACK_OBJECT_FLOAT32: case MSGPACK_OBJECT_FLOAT64: -#else - case MSGPACK_OBJECT_FLOAT: -#endif *rettv = (typval_T) { .v_type = VAR_FLOAT, .v_lock = VAR_UNLOCKED, -- cgit From 419819b6245e120aba8897e3ddea711b2cd0246c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 5 Mar 2023 09:18:42 +0800 Subject: vim-patch:9.0.1380: CTRL-X on 2**64 subtracts two (#22530) Problem: CTRL-X on 2**64 subtracts two. (James McCoy) Solution: Correct computation for large number. (closes vim/vim#12103) https://github.com/vim/vim/commit/5fb78c3fa5c996c08a65431d698bd2c251eef5c7 Co-authored-by: Bram Moolenaar --- src/nvim/eval/decode.c | 4 ++-- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index f57d06c83b..6ce9309677 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -439,7 +439,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, t += 4; uvarnumber_T ch; vim_str2nr(ubuf, NULL, NULL, - STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true); + STR2NR_HEX | STR2NR_FORCE, NULL, &ch, 4, true, NULL); if (ch == 0) { hasnul = true; } @@ -608,7 +608,7 @@ parse_json_number_check: // Convert integer varnumber_T nr; int num_len; - vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true); + vim_str2nr(s, NULL, &num_len, 0, &nr, NULL, (int)(p - s), true, NULL); if ((int)exp_num_len != num_len) { semsg(_("E685: internal error: while converting number \"%.*s\" " "to integer vim_str2nr consumed %i bytes in place of %zu"), diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4208c5ca46..3a7da21606 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8033,7 +8033,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) break; } varnumber_T n; - vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false); + vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false, NULL); // Text after the number is silently ignored. if (isneg) { rettv->vval.v_number = -n; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7d49049b0c..d077998dae 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3890,7 +3890,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, false); + vim_str2nr(tv->vval.v_string, NULL, NULL, STR2NR_ALL, &n, NULL, 0, false, NULL); } return n; } -- cgit From 3ad845882413944a8d6ed3bd9da68c6b4cee0afb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 9 Mar 2023 13:47:01 +0800 Subject: vim-patch:8.2.1067: expression "!expr->func()" does not work (#22585) Problem: Expression "!expr->func()" does not work. Solution: Apply plus and minus earlier. (closes vim/vim#6348) https://github.com/vim/vim/commit/0b1cd52ff6bf690388f892be686a91721a082e55 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 3 +-- src/nvim/eval/vars.c | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 3c4cc34464..13779f4173 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3075,8 +3075,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 *)name, (const char **)&name) + if (handle_subscript((const char **)&arg, &rettv, true, true) == FAIL) { failed = true; break; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index d80bdc70f6..ed2453bd59 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -508,7 +508,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) } else { // handle d.key, l[idx], f(expr) const char *const arg_subsc = arg; - if (handle_subscript(&arg, &tv, true, true, name, &name) == FAIL) { + if (handle_subscript(&arg, &tv, true, true) == FAIL) { error = true; } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { @@ -1715,7 +1715,7 @@ bool var_exists(const char *var) n = get_var_tv(name, len, &tv, NULL, false, true) == OK; if (n) { // Handle d.key, l[idx], f(expr). - n = handle_subscript(&var, &tv, true, false, name, &name) == OK; + n = handle_subscript(&var, &tv, true, false) == OK; if (n) { tv_clear(&tv); } -- cgit From 5bad9afed2189f3716865da42c66133d1f6da218 Mon Sep 17 00:00:00 2001 From: ii14 Date: Thu, 16 Mar 2023 18:13:58 +0100 Subject: build: sanitizers for gcc GCC also supports sanitizers. GCC doesn't support -fsanitize-blacklist option though, so replace .asan-blacklist file with no_sanitize_address function attributes instead. --- src/nvim/eval/typval.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 4a2654f03e..84e4067f9d 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -518,13 +518,15 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE - REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE; + REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE + FUNC_ATTR_NO_SANITIZE_ADDRESS; /// Compute the `DictWatcher` address from a QUEUE node. /// /// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer /// arithmetic). static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) + FUNC_ATTR_NO_SANITIZE_ADDRESS { return QUEUE_DATA(q, DictWatcher, node); } -- cgit From 063e93864a7e99ac1c4781bbe4ea63c0adb075a8 Mon Sep 17 00:00:00 2001 From: Lucas Merritt Date: Fri, 24 Mar 2023 22:11:14 -0600 Subject: refactor(PVS/V1048): remove duplicated assignments (#21873) --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3a7da21606..df8004dc73 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7581,7 +7581,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // third argument: action - 'a' for append and 'r' for replace. // default is to replace the stack. if (argvars[2].v_type == VAR_UNKNOWN) { - action = 'r'; + // action = 'r'; } else if (argvars[2].v_type == VAR_STRING) { const char *actstr; actstr = tv_get_string_chk(&argvars[2]); -- cgit From d5f6176e6dc4b4e12fc5061ca6e87f4af533e46a Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Sat, 1 Apr 2023 02:49:51 +0200 Subject: refactor: add const and remove unnecessary casts (#22841) --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index df8004dc73..25d383d8ea 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4670,7 +4670,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } } - regmatch.regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING); + regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING); if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; @@ -7895,7 +7895,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } regmatch_T regmatch = { - .regprog = vim_regcomp((char *)pat, RE_MAGIC + RE_STRING), + .regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING), .startp = { NULL }, .endp = { NULL }, .rm_ic = false, @@ -7906,7 +7906,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (*str == NUL) { match = false; // Empty item at the end. } else { - match = vim_regexec_nl(®match, (char *)str, col); + match = vim_regexec_nl(®match, str, col); } const char *end; if (match) { -- cgit From d510bfbc8e447b1a60d5ec7faaa8f440eb4ef56f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 2 Apr 2023 10:11:42 +0200 Subject: refactor: remove char_u (#22829) Closes https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 25d383d8ea..4286e16eb1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6197,7 +6197,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } # else char *v = os_realpath(fname, NULL); - rettv->vval.v_string = (char_u *)(v == NULL ? xstrdup(fname) : v); + rettv->vval.v_string = v == NULL ? xstrdup(fname) : v; # endif #endif diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 4615198441..80432271b0 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -206,7 +206,7 @@ typedef struct { struct { \ typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ uint8_t di_flags; /* Flags. */ \ - char_u di_key[__VA_ARGS__]; /* Key value. */ /* NOLINT(runtime/arrays)*/ \ + char di_key[__VA_ARGS__]; /* Key value. */ /* NOLINT(runtime/arrays)*/ \ } /// Structure to hold a scope dictionary diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 13779f4173..40bca9acc1 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -90,7 +90,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * bool mustend = false; char *arg = *argp; char *p = arg; - char_u c; + uint8_t c; int i; if (newargs != NULL) { @@ -128,7 +128,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * } if (newargs != NULL) { ga_grow(newargs, 1); - c = (char_u)(*p); + c = (uint8_t)(*p); *p = NUL; arg = xstrdup(arg); @@ -159,7 +159,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * while (p > expr && ascii_iswhite(p[-1])) { p--; } - c = (char_u)(*p); + c = (uint8_t)(*p); *p = NUL; expr = xstrdup(expr); ((char **)(default_args->ga_data))[default_args->ga_len] = expr; -- cgit From 371823d407d7d7519735131bcad4670c62a731a7 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Wed, 5 Apr 2023 21:13:53 +0200 Subject: refactor: make error message definitions const message.c functions now take const char * as a format. Error message definitions can be made const. --- src/nvim/eval/funcs.c | 10 +++++----- src/nvim/eval/typval.c | 22 +++++++++++----------- src/nvim/eval/userfunc.c | 16 ++++++++-------- src/nvim/eval/vars.c | 6 +++--- src/nvim/eval/window.c | 4 ++-- 5 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4286e16eb1..4225e164e4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -145,10 +145,10 @@ PRAGMA_DIAG_POP PRAGMA_DIAG_POP #endif -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"); -static char e_using_number_as_bool_nr[] +static const char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); +static const char *e_invalwindow = N_("E957: Invalid window number"); +static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); +static const char e_using_number_as_bool_nr[] = N_("E1023: Using a Number as a Bool: %d"); /// Dummy va_list for passing to vim_snprintf @@ -7557,7 +7557,7 @@ free_lstval: /// "settagstack()" function static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - static char *e_invact2 = N_("E962: Invalid action: '%s'"); + static const char *e_invact2 = N_("E962: Invalid action: '%s'"); char action = 'r'; rettv->vval.v_number = -1; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d077998dae..8e5db64d6a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -40,25 +40,25 @@ # include "eval/typval.c.generated.h" #endif -static char e_string_required_for_argument_nr[] +static const char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); -static char e_non_empty_string_required_for_argument_nr[] +static const char e_non_empty_string_required_for_argument_nr[] = N_("E1175: Non-empty string required for argument %d"); -static char e_dict_required_for_argument_nr[] +static const char e_dict_required_for_argument_nr[] = N_("E1206: Dictionary required for argument %d"); -static char e_number_required_for_argument_nr[] +static const char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); -static char e_list_required_for_argument_nr[] +static const char e_list_required_for_argument_nr[] = N_("E1211: List required for argument %d"); -static char e_string_or_list_required_for_argument_nr[] +static const char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); -static char e_list_or_blob_required_for_argument_nr[] +static const char e_list_or_blob_required_for_argument_nr[] = N_("E1226: List or Blob required for argument %d"); -static char e_blob_required_for_argument_nr[] +static const char e_blob_required_for_argument_nr[] = N_("E1238: Blob required for argument %d"); -static char e_invalid_value_for_blob_nr[] +static const char e_invalid_value_for_blob_nr[] = N_("E1239: Invalid value for blob: %d"); -static char e_string_or_function_required_for_argument_nr[] +static const char e_string_or_function_required_for_argument_nr[] = N_("E1256: String or function required for argument %d"); bool tv_in_free_unref_items = false; @@ -2868,7 +2868,7 @@ void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) varnumber_T n = tv_get_number_chk(TV_LIST_ITEM_TV(li), &error); if (error || n < 0 || n > 255) { if (!error) { - semsg(_(e_invalid_value_for_blob_nr), n); + semsg(_(e_invalid_value_for_blob_nr), (int)n); } ga_clear(&blob->bv_ga); return; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 40bca9acc1..9f5d964075 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -65,11 +65,11 @@ static funccall_T *current_funccal = NULL; // item in it is still being used. static funccall_T *previous_funccal = NULL; -static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); -static char *e_funcdict = N_("E717: Dictionary entry already exists"); -static char *e_funcref = N_("E718: Funcref required"); -static char *e_nofunc = N_("E130: Unknown function: %s"); -static char e_no_white_space_allowed_before_str_str[] +static const char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); +static const char *e_funcdict = N_("E717: Dictionary entry already exists"); +static const char *e_funcref = N_("E718: Funcref required"); +static const char *e_nofunc = N_("E130: Unknown function: %s"); +static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); void func_init(void) @@ -421,9 +421,9 @@ char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, b /// Give an error message with a function name. Handle things. /// -/// @param ermsg must be passed without translation (use N_() instead of _()). +/// @param errmsg must be passed without translation (use N_() instead of _()). /// @param name function name -void emsg_funcname(char *ermsg, const char *name) +void emsg_funcname(const char *errmsg, const char *name) { char *p; @@ -433,7 +433,7 @@ void emsg_funcname(char *ermsg, const char *name) p = (char *)name; } - semsg(_(ermsg), p); + semsg(_(errmsg), p); if (p != name) { xfree(p); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ed2453bd59..6252adf6a1 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -50,8 +50,8 @@ #define DICT_MAXNEST 100 // maximum nesting of lists and dicts -static char *e_letunexp = N_("E18: Unexpected characters in :let"); -static char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); +static const char *e_letunexp = N_("E18: Unexpected characters in :let"); +static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); /// Get a list of lines from a HERE document. The here document is a list of /// lines surrounded by a marker. @@ -693,7 +693,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo if (!failed) { if (opt_type != gov_string || s != NULL) { - char *err = set_option_value(arg, (long)n, s, scope); + const char *err = set_option_value(arg, (long)n, s, scope); arg_end = p; if (err != NULL) { emsg(_(err)); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index c1d2e5b38f..cf5727fa59 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -36,8 +36,8 @@ # include "eval/window.c.generated.h" #endif -static char *e_invalwindow = N_("E957: Invalid window number"); -static char e_cannot_resize_window_in_another_tab_page[] +static const char *e_invalwindow = N_("E957: Invalid window number"); +static const char e_cannot_resize_window_in_another_tab_page[] = N_("E1308: Cannot resize a window in another tab page"); static int win_getid(typval_T *argvars) -- cgit From 7190dba017e3aac0409c73ff1c954d18858cb3c9 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Thu, 6 Apr 2023 22:39:50 +0200 Subject: refactor: remove use of reserved c++ keywords libnvim couldn't be easily used in C++ due to the use of reserved keywords. Additionally, add explicit casts to *alloc function calls used in inline functions, as C++ doesn't allow implicit casts from void pointers. --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4225e164e4..03df0661c5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3996,7 +3996,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en if (!clear_env) { typval_T temp_env = TV_INITIAL_VALUE; - f_environ(NULL, &temp_env, (EvalFuncData){ .nullptr = NULL }); + f_environ(NULL, &temp_env, (EvalFuncData){ .null = NULL }); tv_dict_extend(env, temp_env.vval.v_dict, "force"); tv_dict_free(temp_env.vval.v_dict); -- cgit From 1d2a29f75ba7d094c8e7444c9b249a4a7211c93c Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Fri, 7 Apr 2023 19:39:04 +0200 Subject: refactor: make char * parameters const in message.c Add const to char * parameters in message.c functions and remove some redundant casts. --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 6252adf6a1..43847cb986 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1206,7 +1206,7 @@ static void list_one_var_a(const char *prefix, const char *name, const ptrdiff_t msg_putchar(' '); } - msg_outtrans((char *)string); + msg_outtrans(string); if (type == VAR_FUNC || type == VAR_PARTIAL) { msg_puts("()"); -- cgit From 9408f2dcf7cade2631688300e9b58eed6bc5219a Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Fri, 7 Apr 2023 19:40:57 +0200 Subject: refactor: remove redundant const char * casts --- src/nvim/eval/buffer.c | 9 +++------ src/nvim/eval/decode.c | 5 ++--- src/nvim/eval/encode.c | 6 +++--- src/nvim/eval/funcs.c | 27 ++++++++++++--------------- src/nvim/eval/typval.c | 39 +++++++++++++++++++-------------------- src/nvim/eval/userfunc.c | 30 +++++++++++++----------------- src/nvim/eval/vars.c | 12 ++++++------ 7 files changed, 58 insertions(+), 70 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 2f37d1ba2e..d9cc18a402 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -487,8 +487,7 @@ static dict_T *get_buffer_info(buf_T *buf) dict_T *const dict = tv_dict_alloc(); tv_dict_add_nr(dict, S_LEN("bufnr"), buf->b_fnum); - tv_dict_add_str(dict, S_LEN("name"), - buf->b_ffname != NULL ? (const char *)buf->b_ffname : ""); + tv_dict_add_str(dict, S_LEN("name"), buf->b_ffname != NULL ? buf->b_ffname : ""); tv_dict_add_nr(dict, S_LEN("lnum"), buf == curbuf ? curwin->w_cursor.lnum : buflist_findlnum(buf)); tv_dict_add_nr(dict, S_LEN("linecount"), buf->b_ml.ml_line_count); @@ -496,8 +495,7 @@ static dict_T *get_buffer_info(buf_T *buf) tv_dict_add_nr(dict, S_LEN("listed"), buf->b_p_bl); tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf)); - tv_dict_add_nr(dict, S_LEN("hidden"), - buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); + tv_dict_add_nr(dict, S_LEN("hidden"), buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); // Get a reference to buffer variables tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); @@ -609,8 +607,7 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli } tv_list_alloc_ret(rettv, end - start + 1); while (start <= end) { - tv_list_append_string(rettv->vval.v_list, - (const char *)ml_get_buf(buf, start++, false), -1); + tv_list_append_string(rettv->vval.v_list, ml_get_buf(buf, start++, false), -1); } } else { rettv->v_type = VAR_STRING; diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 6ce9309677..acef37e0e8 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -148,7 +148,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack assert(!(key.is_special_string || key.val.vval.v_string == NULL || *key.val.vval.v_string == NUL)); - dictitem_T *const obj_di = tv_dict_item_alloc((const char *)key.val.vval.v_string); + dictitem_T *const obj_di = tv_dict_item_alloc(key.val.vval.v_string); tv_clear(&key.val); if (tv_dict_add(last_container.container.vval.v_dict, obj_di) == FAIL) { @@ -179,8 +179,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack && (obj.is_special_string || obj.val.vval.v_string == NULL || *obj.val.vval.v_string == NUL - || tv_dict_find(last_container.container.vval.v_dict, - (const char *)obj.val.vval.v_string, -1))) { + || tv_dict_find(last_container.container.vval.v_dict, obj.val.vval.v_string, -1))) { tv_clear(&obj.val); // Restart diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index c2f1eae8af..b056a1784c 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -298,7 +298,7 @@ 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); \ + const char *const buf_ = (buf); \ if ((buf) == NULL) { \ ga_concat(gap, "''"); \ } else { \ @@ -376,7 +376,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s #define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \ do { \ - const char *const fun_ = (const char *)(fun); \ + const char *const fun_ = (fun); \ if (fun_ == NULL) { \ internal_error("string(): NULL function name"); \ ga_concat(gap, "function(NULL"); \ @@ -712,7 +712,7 @@ static inline int convert_to_json_string(garray_T *const gap, const char *const #undef TYPVAL_ENCODE_CONV_STRING #define TYPVAL_ENCODE_CONV_STRING(tv, buf, len) \ do { \ - if (convert_to_json_string(gap, (const char *)(buf), (len)) != OK) { \ + if (convert_to_json_string(gap, (buf), (len)) != OK) { \ return FAIL; \ } \ } while (0) diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 03df0661c5..b7425b1ef3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -319,7 +319,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) Object result = handler.fn(VIML_INTERNAL_CALL, args, &res_arena, &err); if (ERROR_SET(&err)) { - semsg_multiline((const char *)e_api_error, err.msg); + semsg_multiline(e_api_error, err.msg); goto end; } @@ -1546,7 +1546,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *s = tv_get_string_chk(&argvars[0]); if (s != NULL) { - s = (const char *)skipwhite(s); + s = skipwhite(s); } const char *const expr_start = s; @@ -1779,7 +1779,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (rettv->v_type == VAR_LIST) { tv_list_alloc_ret(rettv, (result != NULL)); if (result != NULL) { - tv_list_append_string(rettv->vval.v_list, (const char *)result, -1); + tv_list_append_string(rettv->vval.v_list, result, -1); } XFREE_CLEAR(result); } else { @@ -1805,8 +1805,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ExpandOne(&xpc, (char *)s, NULL, options, WILD_ALL_KEEP); tv_list_alloc_ret(rettv, xpc.xp_numfiles); for (int i = 0; i < xpc.xp_numfiles; i++) { - tv_list_append_string(rettv->vval.v_list, - (const char *)xpc.xp_files[i], -1); + tv_list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); } ExpandCleanup(&xpc); } @@ -2134,7 +2133,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) first = false; if (fresult != NULL && rettv->v_type == VAR_LIST) { - tv_list_append_string(rettv->vval.v_list, (const char *)fresult, -1); + tv_list_append_string(rettv->vval.v_list, fresult, -1); } } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); } @@ -3008,8 +3007,7 @@ static void f_glob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) WILD_ALL_KEEP); tv_list_alloc_ret(rettv, xpc.xp_numfiles); for (int i = 0; i < xpc.xp_numfiles; i++) { - tv_list_append_string(rettv->vval.v_list, (const char *)xpc.xp_files[i], - -1); + tv_list_append_string(rettv->vval.v_list, xpc.xp_files[i], -1); } ExpandCleanup(&xpc); } @@ -4050,7 +4048,7 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en #ifdef MSWIN TV_DICT_ITER(job_env->di_tv.vval.v_dict, var, { // Always use upper-case keys for Windows so we detect duplicate keys - char *const key = strcase_save((const char *)var->di_key, true); + char *const key = strcase_save(var->di_key, true); size_t len = strlen(key); dictitem_T *dv = tv_dict_find(env, key, len); if (dv) { @@ -4735,8 +4733,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, if (regmatch.endp[i] == NULL) { tv_list_append_string(rettv->vval.v_list, NULL, 0); } else { - tv_list_append_string(rettv->vval.v_list, - (const char *)regmatch.startp[i], + tv_list_append_string(rettv->vval.v_list, regmatch.startp[i], (regmatch.endp[i] - regmatch.startp[i])); } } @@ -4746,7 +4743,7 @@ 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 = xmemdupz((const char *)regmatch.startp[0], + rettv->vval.v_string = xmemdupz(regmatch.startp[0], (size_t)(regmatch.endp[0] - regmatch.startp[0])); } @@ -7910,14 +7907,14 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } const char *end; if (match) { - end = (const char *)regmatch.startp[0]; + end = regmatch.startp[0]; } else { end = str + strlen(str); } if (keepempty || end > str || (tv_list_len(rettv->vval.v_list) > 0 && *str != NUL && match - && end < (const char *)regmatch.endp[0])) { + && end < regmatch.endp[0])) { tv_list_append_string(rettv->vval.v_list, str, end - str); } if (!match) { @@ -7930,7 +7927,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // Don't get stuck at the same match. col = utfc_ptr2len(regmatch.endp[0]); } - str = (const char *)regmatch.endp[0]; + str = regmatch.endp[0]; } vim_regfree(regmatch.regprog); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8e5db64d6a..e027517108 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1091,7 +1091,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) if (partial == NULL) { func_name = sortinfo->item_compare_func; } else { - func_name = (const char *)partial_name(partial); + func_name = partial_name(partial); } // Copy the values. This is needed to be able to set v_lock to VAR_FIXED @@ -1189,7 +1189,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (argvars[1].v_type != VAR_UNKNOWN) { // optional second argument: {func} if (argvars[1].v_type == VAR_FUNC) { - info.item_compare_func = (const char *)argvars[1].vval.v_string; + info.item_compare_func = argvars[1].vval.v_string; } else if (argvars[1].v_type == VAR_PARTIAL) { info.item_compare_partial = argvars[1].vval.v_partial; } else { @@ -1894,7 +1894,7 @@ void tv_dict_item_free(dictitem_T *const item) dictitem_T *tv_dict_item_copy(dictitem_T *const di) FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { - dictitem_T *const new_di = tv_dict_item_alloc((const char *)di->di_key); + dictitem_T *const new_di = tv_dict_item_alloc(di->di_key); tv_copy(&di->di_tv, &new_di->di_tv); return new_di; } @@ -2240,7 +2240,7 @@ int tv_dict_wrong_func_name(dict_T *d, typval_T *tv, const char *name) int tv_dict_add(dict_T *const d, dictitem_T *const item) FUNC_ATTR_NONNULL_ALL { - if (tv_dict_wrong_func_name(d, &item->di_tv, (const char *)item->di_key)) { + if (tv_dict_wrong_func_name(d, &item->di_tv, item->di_key)) { return FAIL; } return hash_add(&d->dv_hashtab, (char *)item->di_key); @@ -2477,9 +2477,9 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action HASHTAB_ITER(&d2->dv_hashtab, hi2, { dictitem_T *const di2 = TV_DICT_HI2DI(hi2); - dictitem_T *const di1 = tv_dict_find(d1, (const char *)di2->di_key, -1); + dictitem_T *const di1 = tv_dict_find(d1, di2->di_key, -1); // Check the key to be valid when adding to any scope. - if (d1->dv_scope != VAR_NO_SCOPE && !valid_varname((const char *)di2->di_key)) { + if (d1->dv_scope != VAR_NO_SCOPE && !valid_varname(di2->di_key)) { break; } if (di1 == NULL) { @@ -2489,14 +2489,14 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action dictitem_T *const new_di = di2; if (tv_dict_add(d1, new_di) == OK) { hash_remove(&d2->dv_hashtab, hi2); - tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, NULL); + tv_dict_watcher_notify(d1, new_di->di_key, &new_di->di_tv, NULL); } } else { dictitem_T *const new_di = tv_dict_item_copy(di2); if (tv_dict_add(d1, new_di) == FAIL) { tv_dict_item_free(new_di); } else if (watched) { - tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, NULL); + tv_dict_watcher_notify(d1, new_di->di_key, &new_di->di_tv, NULL); } } } else if (*action == 'e') { @@ -2510,7 +2510,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action break; } // Disallow replacing a builtin function. - if (tv_dict_wrong_func_name(d1, &di2->di_tv, (const char *)di2->di_key)) { + if (tv_dict_wrong_func_name(d1, &di2->di_tv, di2->di_key)) { break; } @@ -2522,8 +2522,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action tv_copy(&di2->di_tv, &di1->di_tv); if (watched) { - tv_dict_watcher_notify(d1, (const char *)di1->di_key, &di1->di_tv, - &oldtv); + tv_dict_watcher_notify(d1, di1->di_key, &di1->di_tv, &oldtv); tv_clear(&oldtv); } } @@ -2558,7 +2557,7 @@ bool tv_dict_equal(dict_T *const d1, dict_T *const d2, const bool ic, const bool } TV_DICT_ITER(d1, di1, { - dictitem_T *const di2 = tv_dict_find(d2, (const char *)di1->di_key, -1); + dictitem_T *const di2 = tv_dict_find(d2, di1->di_key, -1); if (di2 == NULL) { return false; } @@ -2597,12 +2596,12 @@ dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool } dictitem_T *new_di; if (conv == NULL || conv->vc_type == CONV_NONE) { - new_di = tv_dict_item_alloc((const char *)di->di_key); + new_di = tv_dict_item_alloc(di->di_key); } else { - size_t len = strlen((char *)di->di_key); - char *const key = (char *)string_convert(conv, (char *)di->di_key, &len); + size_t len = strlen(di->di_key); + char *const key = string_convert(conv, di->di_key, &len); if (key == NULL) { - new_di = tv_dict_item_alloc_len((const char *)di->di_key, len); + new_di = tv_dict_item_alloc_len(di->di_key, len); } else { new_di = tv_dict_item_alloc_len(key, len); xfree(key); @@ -2960,7 +2959,7 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi tv_list_append_owned_tv(sub_l, (typval_T) { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrdup((const char *)di->di_key), + .vval.v_string = xstrdup(di->di_key), }); tv_list_append_tv(sub_l, &di->di_tv); @@ -3132,7 +3131,7 @@ static inline int _nothing_conv_func_start(typval_T *const tv, char *const fun) } } else { func_unref(fun); - if ((const char *)fun != tv_empty_string) { + if (fun != tv_empty_string) { xfree(fun); } tv->vval.v_string = NULL; @@ -3805,7 +3804,7 @@ static const char *const str_errors[] = { [VAR_FUNC]= N_(FUNC_ERROR), [VAR_LIST]= N_("E730: using List as a String"), [VAR_DICT]= N_("E731: using Dictionary as a String"), - [VAR_FLOAT]= ((const char *)e_float_as_string), + [VAR_FLOAT]= e_float_as_string, [VAR_BLOB]= N_("E976: using Blob as a String"), [VAR_UNKNOWN]= N_("E908: using an invalid value as a String"), }; @@ -4116,7 +4115,7 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) return buf; case VAR_STRING: if (tv->vval.v_string != NULL) { - return (const char *)tv->vval.v_string; + return tv->vval.v_string; } return ""; case VAR_BOOL: diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9f5d964075..99e8859ae9 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1575,7 +1575,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t XFREE_CLEAR(name); funcname = "v:lua"; } - } else if (fp != NULL || !builtin_function((const char *)rfname, -1)) { + } else if (fp != NULL || !builtin_function(rfname, -1)) { // User defined function. if (fp == NULL) { fp = find_func(rfname); @@ -1589,8 +1589,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t fp = find_func(rfname); } // Try loading a package. - if (fp == NULL && script_autoload((const char *)rfname, strlen(rfname), - true) && !aborting()) { + if (fp == NULL && script_autoload(rfname, strlen(rfname), true) && !aborting()) { // Loaded a package, search for the function again. fp = find_func(rfname); } @@ -1666,7 +1665,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) } msg_puts(force ? "function! " : "function "); if (fp->uf_name_exp != NULL) { - msg_puts((const char *)fp->uf_name_exp); + msg_puts(fp->uf_name_exp); } else { msg_puts(fp->uf_name); } @@ -1676,7 +1675,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) if (j) { msg_puts(", "); } - msg_puts((const char *)FUNCARG(fp, j)); + msg_puts(FUNCARG(fp, j)); if (j >= fp->uf_args.ga_len - fp->uf_def_args.ga_len) { msg_puts(" = "); msg_puts(((char **)(fp->uf_def_args.ga_data)) @@ -1828,7 +1827,7 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part len = (int)strlen(lv.ll_exp_name); name = deref_func_name(lv.ll_exp_name, &len, partial, flags & TFN_NO_AUTOLOAD); - if ((const char *)name == lv.ll_exp_name) { + if (name == lv.ll_exp_name) { name = NULL; } } else if (!(flags & TFN_NO_DEREF)) { @@ -1881,8 +1880,7 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part lead = 0; // do nothing } else if (lead > 0) { lead = 3; - if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) - || eval_fname_sid((const char *)(*pp))) { + if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name)) || eval_fname_sid(*pp)) { // It's "s:" or "". if (current_sctx.sc_sid <= 0) { emsg(_(e_usingsid)); @@ -2209,7 +2207,7 @@ void ex_function(exarg_T *eap) if (KeyTyped && ui_has(kUICmdline)) { show_block = true; - ui_ext_cmdline_block_append(0, (const char *)eap->cmd); + ui_ext_cmdline_block_append(0, eap->cmd); } // find extra arguments "range", "dict", "abort" and "closure" @@ -2308,7 +2306,7 @@ void ex_function(exarg_T *eap) } if (show_block) { assert(indent >= 0); - ui_ext_cmdline_block_append((size_t)indent, (const char *)theline); + ui_ext_cmdline_block_append((size_t)indent, theline); } // Detect line continuation: SOURCING_LNUM increased more than one. @@ -2390,7 +2388,7 @@ void ex_function(exarg_T *eap) if (*p == '!') { p = skipwhite(p + 1); } - p += eval_fname_script((const char *)p); + p += eval_fname_script(p); xfree(trans_function_name(&p, true, 0, NULL, NULL)); if (*skipwhite(p) == '(') { if (nesting == MAX_FUNC_NESTING - 1) { @@ -2501,7 +2499,7 @@ void ex_function(exarg_T *eap) // If there are no errors, add the function if (fudi.fd_dict == NULL) { - v = find_var((const char *)name, strlen(name), &ht, false); + v = find_var(name, strlen(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), name); goto erret; @@ -2548,13 +2546,11 @@ void ex_function(exarg_T *eap) goto erret; } if (fudi.fd_di == NULL) { - if (value_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, - TV_CSTRING)) { + if (value_check_lock(fudi.fd_dict->dv_lock, eap->arg, TV_CSTRING)) { // Can't add a function to a locked dictionary goto erret; } - } else if (value_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, - TV_CSTRING)) { + } else if (value_check_lock(fudi.fd_di->di_tv.v_lock, eap->arg, TV_CSTRING)) { // Can't change an existing function if it is locked goto erret; } @@ -2595,7 +2591,7 @@ void ex_function(exarg_T *eap) if (fudi.fd_dict != NULL) { if (fudi.fd_di == NULL) { // Add new dict entry - fudi.fd_di = tv_dict_item_alloc((const char *)fudi.fd_newkey); + fudi.fd_di = tv_dict_item_alloc(fudi.fd_newkey); if (tv_dict_add(fudi.fd_dict, fudi.fd_di) == FAIL) { xfree(fudi.fd_di); xfree(fp); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 43847cb986..e0f7af5718 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -215,7 +215,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) emsg(_(e_invarg)); } else if (!ends_excmd(*arg)) { // ":let var1 var2" - arg = (char *)list_arg_vars(eap, (const char *)arg, &first); + arg = (char *)list_arg_vars(eap, arg, &first); } else if (!eap->skip) { // ":let" list_glob_vars(&first); @@ -551,7 +551,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) xfree(tofree); } - arg = (const char *)skipwhite(arg); + arg = skipwhite(arg); } return arg; @@ -601,7 +601,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo char *s = vim_getenv(name); if (s != NULL) { tofree = concat_str(s, p); - p = (const char *)tofree; + p = tofree; xfree(s); } } @@ -725,7 +725,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); if (s != NULL) { ptofree = concat_str(s, p); - p = (const char *)ptofree; + p = ptofree; xfree(s); } } @@ -798,7 +798,7 @@ static void ex_unletlock(exarg_T *eap, char *argstart, int deep, ex_unletlock_ca do { if (*arg == '$') { - lv.ll_name = (const char *)arg; + lv.ll_name = arg; lv.ll_tv = NULL; arg++; if (get_env_len((const char **)&arg) == 0) { @@ -1169,7 +1169,7 @@ void delete_var(hashtab_T *ht, hashitem_T *hi) static void list_one_var(dictitem_T *v, const char *prefix, int *first) { char *const s = encode_tv2echo(&v->di_tv, NULL); - list_one_var_a(prefix, (const char *)v->di_key, (ptrdiff_t)strlen((char *)v->di_key), + list_one_var_a(prefix, v->di_key, (ptrdiff_t)strlen((char *)v->di_key), v->di_tv.v_type, (s == NULL ? "" : s), first); xfree(s); } -- cgit From 04933b1ea968f958d2541dd65fd33ebb503caac3 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Fri, 7 Apr 2023 21:08:16 +0200 Subject: refactor: remove redundant casts --- src/nvim/eval/funcs.c | 8 ++++---- src/nvim/eval/typval.c | 2 +- src/nvim/eval/userfunc.c | 6 +++--- src/nvim/eval/vars.c | 24 +++++++++++------------- 4 files changed, 19 insertions(+), 21 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b7425b1ef3..eaa66f6483 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9093,14 +9093,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (dir == 0 || dir == 1) { // Trim leading characters while (*head != NUL) { - c1 = utf_ptr2char((char *)head); + c1 = utf_ptr2char(head); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char((char *)p)) { + if (c1 == utf_ptr2char(p)) { break; } } @@ -9118,14 +9118,14 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) for (; tail > head; tail = prev) { prev = tail; MB_PTR_BACK(head, prev); - c1 = utf_ptr2char((char *)prev); + c1 = utf_ptr2char(prev); if (mask == NULL) { if (c1 > ' ' && c1 != 0xa0) { break; } } else { for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char((char *)p)) { + if (c1 == utf_ptr2char(p)) { break; } } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index e027517108..bfac1ca864 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -898,7 +898,7 @@ void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) TV_LIST_ITER_CONST(l, li, { buf[utf_char2bytes((int)tv_get_number(TV_LIST_ITEM_TV(li)), (char *)buf)] = NUL; - ga_concat(&ga, (char *)buf); + ga_concat(&ga, buf); }); ga_append(&ga, NUL); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 99e8859ae9..9c1e8230a3 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -611,7 +611,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) STRCPY(v->di_key, name); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&dp->dv_hashtab, (char *)v->di_key); + hash_add(&dp->dv_hashtab, v->di_key); v->di_tv.v_type = VAR_NUMBER; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_number = nr; @@ -2612,7 +2612,7 @@ void ex_function(exarg_T *eap) set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); - hi->hi_key = (char *)UF2HIKEY(fp); + hi->hi_key = UF2HIKEY(fp); } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { xfree(fp); goto erret; @@ -2681,7 +2681,7 @@ int eval_fname_script(const char *const p) bool translated_function_exists(const char *name) { if (builtin_function(name, -1)) { - return find_internal_func((char *)name) != NULL; + return find_internal_func(name) != NULL; } return find_func(name) != NULL; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index e0f7af5718..77b40fbf11 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -197,10 +197,10 @@ static void ex_let_const(exarg_T *eap, const bool is_const) int var_count = 0; int semicolon = 0; char op[2]; - char *argend; + const char *argend; int first = true; - argend = (char *)skip_var_list(arg, &var_count, &semicolon); + argend = skip_var_list(arg, &var_count, &semicolon); if (argend == NULL) { return; } @@ -235,8 +235,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) if (!eap->skip) { op[0] = '='; op[1] = NUL; - (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, - is_const, (char *)op); + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); } tv_clear(&rettv); } @@ -267,8 +266,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) } emsg_skip--; } else if (i != FAIL) { - (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, - is_const, (char *)op); + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); tv_clear(&rettv); } } @@ -375,7 +373,7 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon) const char *p = arg; for (;;) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' - s = skip_var_one((char *)p); + s = skip_var_one(p); if (s == p) { semsg(_(e_invarg2), p); return NULL; @@ -398,7 +396,7 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon) } return p + 1; } - return skip_var_one((char *)arg); + return skip_var_one(arg); } /// Skip one (assignable) variable name, including @r, $VAR, &option, d.key, @@ -430,7 +428,7 @@ void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty, int *firs // apply :filter /pat/ to variable name xstrlcpy(buf, prefix, IOSIZE); - xstrlcat(buf, (char *)di->di_key, IOSIZE); + xstrlcat(buf, di->di_key, IOSIZE); if (message_filtered(buf)) { continue; } @@ -915,7 +913,7 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ if (watched) { tv_copy(&di->di_tv, &oldtv); // need to save key because dictitem_remove will free it - key = xstrdup((char *)di->di_key); + key = xstrdup(di->di_key); } tv_dict_item_remove(d, di); @@ -1169,7 +1167,7 @@ void delete_var(hashtab_T *ht, hashitem_T *hi) static void list_one_var(dictitem_T *v, const char *prefix, int *first) { char *const s = encode_tv2echo(&v->di_tv, NULL); - list_one_var_a(prefix, v->di_key, (ptrdiff_t)strlen((char *)v->di_key), + list_one_var_a(prefix, v->di_key, (ptrdiff_t)strlen(v->di_key), v->di_tv.v_type, (s == NULL ? "" : s), first); xfree(s); } @@ -1343,7 +1341,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1); STRCPY(v->di_key, varname); - if (hash_add(ht, (char *)v->di_key) == FAIL) { + if (hash_add(ht, v->di_key) == FAIL) { xfree(v); return; } @@ -1362,7 +1360,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, } if (watched) { - tv_dict_watcher_notify(dict, (char *)v->di_key, &v->di_tv, &oldtv); + tv_dict_watcher_notify(dict, v->di_key, &v->di_tv, &oldtv); tv_clear(&oldtv); } -- cgit From 2d78e656b715119ca11d131a1a932f22f1b4ad36 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Fri, 7 Apr 2023 21:43:00 +0200 Subject: refactor: remove redundant casts --- src/nvim/eval/funcs.c | 24 ++++++++++++------------ src/nvim/eval/typval.c | 12 ++++++------ src/nvim/eval/userfunc.c | 12 ++++++------ src/nvim/eval/vars.c | 4 ++-- src/nvim/eval/window.c | 2 +- 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index eaa66f6483..7f224f371c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -956,7 +956,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const size_t len = strlen(expr); while (*p != NUL) { - if (mb_strnicmp((char *)p, (char *)expr, len) == 0) { + if (mb_strnicmp(p, expr, len) == 0) { n++; p += len; } else { @@ -965,7 +965,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } else { char *next; - while ((next = strstr((char *)p, (char *)expr)) != NULL) { + while ((next = strstr(p, expr)) != NULL) { n++; p = next + strlen(expr); } @@ -1064,17 +1064,17 @@ static void f_ctxpush(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) TV_LIST_ITER(argvars[0].vval.v_list, li, { typval_T *tv_li = TV_LIST_ITEM_TV(li); if (tv_li->v_type == VAR_STRING) { - if (strequal((char *)tv_li->vval.v_string, "regs")) { + if (strequal(tv_li->vval.v_string, "regs")) { types |= kCtxRegs; - } else if (strequal((char *)tv_li->vval.v_string, "jumps")) { + } else if (strequal(tv_li->vval.v_string, "jumps")) { types |= kCtxJumps; - } else if (strequal((char *)tv_li->vval.v_string, "bufs")) { + } else if (strequal(tv_li->vval.v_string, "bufs")) { types |= kCtxBufs; - } else if (strequal((char *)tv_li->vval.v_string, "gvars")) { + } else if (strequal(tv_li->vval.v_string, "gvars")) { types |= kCtxGVars; - } else if (strequal((char *)tv_li->vval.v_string, "sfuncs")) { + } else if (strequal(tv_li->vval.v_string, "sfuncs")) { types |= kCtxSFuncs; - } else if (strequal((char *)tv_li->vval.v_string, "funcs")) { + } else if (strequal(tv_li->vval.v_string, "funcs")) { types |= kCtxFuncs; } } @@ -4953,7 +4953,7 @@ static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char msgbuf[sizeof("msgpackdump() argument, index ") * 4 + NUMBUFLEN]; int idx = 0; TV_LIST_ITER(list, li, { - vim_snprintf(msgbuf, sizeof(msgbuf), (char *)msg, idx); + vim_snprintf(msgbuf, sizeof(msgbuf), msg, idx); idx++; if (encode_vim_to_msgpack(packer, TV_LIST_ITEM_TV(li), msgbuf) == FAIL) { break; @@ -6282,7 +6282,7 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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); + const int r = call_func(func_name, -1, rettv, 2, argv, &funcexe); tv_clear(&argv[0]); if (r == FAIL || called_emsg != called_emsg_start) { break; @@ -6315,7 +6315,7 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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) { + if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL) { return; } } @@ -8584,7 +8584,7 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } rettv->v_type = VAR_STRING; - rettv->vval.v_string = (char *)(p == NULL ? p : xstrdup(p)); + rettv->vval.v_string = p == NULL ? NULL : xstrdup(p); } /// "synIDtrans(id)" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index bfac1ca864..3e67571053 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -897,7 +897,7 @@ void f_list2str(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char buf[MB_MAXBYTES + 1]; TV_LIST_ITER_CONST(l, li, { - buf[utf_char2bytes((int)tv_get_number(TV_LIST_ITEM_TV(li)), (char *)buf)] = NUL; + buf[utf_char2bytes((int)tv_get_number(TV_LIST_ITEM_TV(li)), buf)] = NUL; ga_concat(&ga, buf); }); ga_append(&ga, NUL); @@ -1906,7 +1906,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, (char *)item->di_key); + hashitem_T *const hi = hash_find(&dict->dv_hashtab, item->di_key); if (HASHITEM_EMPTY(hi)) { semsg(_(e_intern2), "tv_dict_item_remove()"); } else { @@ -2111,9 +2111,9 @@ char **tv_dict_to_env(dict_T *denv) TV_DICT_ITER(denv, var, { const char *str = tv_get_string(&var->di_tv); assert(str); - size_t len = strlen((char *)var->di_key) + strlen(str) + strlen("=") + 1; + size_t len = strlen(var->di_key) + strlen(str) + strlen("=") + 1; env[i] = xmalloc(len); - snprintf(env[i], len, "%s=%s", (char *)var->di_key, str); + snprintf(env[i], len, "%s=%s", var->di_key, str); i++; }); @@ -2243,7 +2243,7 @@ int tv_dict_add(dict_T *const d, dictitem_T *const item) if (tv_dict_wrong_func_name(d, &item->di_tv, item->di_key)) { return FAIL; } - return hash_add(&d->dv_hashtab, (char *)item->di_key); + return hash_add(&d->dv_hashtab, item->di_key); } /// Add a list entry to dictionary @@ -2944,7 +2944,7 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi switch (what) { case kDictListKeys: tv_item.v_type = VAR_STRING; - tv_item.vval.v_string = xstrdup((char *)di->di_key); + tv_item.vval.v_string = xstrdup(di->di_key); break; case kDictListValues: tv_copy(&di->di_tv, &tv_item); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9c1e8230a3..f09da6b79b 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -758,7 +758,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, (char *)UF2HIKEY(fp)); + hashitem_T *hi = hash_find(&func_hashtab, UF2HIKEY(fp)); if (HASHITEM_EMPTY(hi)) { return false; } @@ -905,7 +905,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_vars.dv_hashtab, (char *)v->di_key); + hash_add(&fc->l_vars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = VAR_UNLOCKED; v->di_tv.vval.v_dict = selfdict; @@ -931,7 +931,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_avars.dv_hashtab, (char *)v->di_key); + hash_add(&fc->l_avars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_list = &fc->l_varlist; @@ -1009,9 +1009,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Named arguments can be accessed without the "a:" prefix in lambda // expressions. Add to the l: dict. tv_copy(&v->di_tv, &v->di_tv); - hash_add(&fc->l_vars.dv_hashtab, (char *)v->di_key); + hash_add(&fc->l_vars.dv_hashtab, v->di_key); } else { - hash_add(&fc->l_avars.dv_hashtab, (char *)v->di_key); + hash_add(&fc->l_avars.dv_hashtab, v->di_key); } if (ai >= 0 && ai < MAX_FUNC_ARGS) { @@ -1770,7 +1770,7 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part semsg(_(e_invarg2), start); } } else { - *pp = (char *)find_name_end((char *)start, NULL, NULL, FNE_INCL_BR); + *pp = (char *)find_name_end(start, NULL, NULL, FNE_INCL_BR); } goto theend; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 77b40fbf11..701f190a06 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -406,8 +406,8 @@ static const char *skip_var_one(const char *arg) if (*arg == '@' && arg[1] != NUL) { return arg + 2; } - return (char *)find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg, - NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); + return find_name_end(*arg == '$' || *arg == '&' ? arg + 1 : arg, + NULL, NULL, FNE_INCL_BR | FNE_CHECK_START); } /// List variables for hashtab "ht" with prefix "prefix". diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index cf5727fa59..25de236d90 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -265,7 +265,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } else { // Extract the window count (if specified). e.g. winnr('3j') char *endp; - long count = strtol((char *)arg, &endp, 10); + long count = strtol(arg, &endp, 10); if (count <= 0) { // if count is not specified, default to 1 count = 1; -- cgit From 0e4086b74189c2b31ce63c6c5e85124edaf20d08 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 10 Apr 2023 18:06:59 +0800 Subject: fix(eval): prevent double-free in garbage collection (#22990) --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 701f190a06..9120cc4471 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1149,7 +1149,7 @@ void vars_clear_ext(hashtab_T *ht, int free_val) } } hash_clear(ht); - ht->ht_used = 0; + hash_init(ht); } /// Delete a variable from hashtab "ht" at item "hi". -- cgit From 8f69c5ed450337b9f77c50f9ee0d3eb32f649ca6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 07:11:59 +0800 Subject: vim-patch:8.2.{0695,0725,0734,0753,0818,0819,0822} (#23075) vim-patch:8.2.0695: Vim9: cannot define a function inside a function Problem: Vim9: cannot define a function inside a function. Solution: Initial support for :def inside :def. https://github.com/vim/vim/commit/04b12697838b232b8b17c553ccc74cf1f1bdb81c vim-patch:8.2.0725: Vim9: cannot call a function declared later in Vim9 script Problem: Vim9: cannot call a function declared later in Vim9 script. Solution: Make two passes through the script file. https://github.com/vim/vim/commit/09689a02840be40fa7bb10b1921fb5bc5b2908f1 vim-patch:8.2.0734: Vim9: leaking memory when using :finish Problem: Vim9: leaking memory when using :finish. Solution: Do not check for next line in third pass. https://github.com/vim/vim/commit/04816717dfea6e2469ff4c9d40f68b59aaf03724 vim-patch:8.2.0753: Vim9: expressions are evaluated in the discovery phase Problem: Vim9: expressions are evaluated in the discovery phase. Solution: Bail out if an expression is not a constant. Require a type for declared constants. https://github.com/vim/vim/commit/32e351179eacfc84f64cd5029e221582d400bb38 vim-patch:8.2.0818: Vim9: using a discovery phase doesn't work well Problem: Vim9: using a discovery phase doesn't work well. Solution: Remove the discovery phase, instead compile a function only when it is used. Add :defcompile to compile def functions earlier. https://github.com/vim/vim/commit/822ba24743af9ee1b5e7f656a7a61a38f3638bca vim-patch:8.2.0819: compiler warning for unused variable Problem: Compiler warning for unused variable. Solution: Remove the variable. https://github.com/vim/vim/commit/f40e51a880a95f94dbbbecc9476559506c2cc345 vim-patch:8.2.0822: Vim9: code left over from discovery phase Problem: Vim9: code left over from discovery phase. Solution: Remove the dead code. https://github.com/vim/vim/commit/2eec37926db6d31beb36f162ac00357a30c093c8 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/userfunc.c | 15 ++++++++------- src/nvim/eval/vars.c | 29 +++++++++++++---------------- 3 files changed, 22 insertions(+), 24 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7f224f371c..52e38b73ba 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1550,7 +1550,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } const char *const expr_start = s; - if (s == NULL || eval1((char **)&s, rettv, true) == FAIL) { + if (s == NULL || eval1((char **)&s, rettv, EVAL_EVALUATE) == FAIL) { if (expr_start != NULL && !aborting()) { semsg(_(e_invexpr2), expr_start); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f09da6b79b..f82ab08d2d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -152,7 +152,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * p = skipwhite(p) + 1; p = skipwhite(p); char *expr = p; - if (eval1(&p, &rettv, false) != FAIL) { + if (eval1(&p, &rettv, 0) != FAIL) { ga_grow(default_args, 1); // trim trailing whitespace @@ -463,7 +463,8 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_ if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], funcexe->fe_evaluate) == FAIL) { + if (eval1(&argp, &argvars[argcount], + funcexe->fe_evaluate ? EVAL_EVALUATE : 0) == FAIL) { ret = FAIL; break; } @@ -972,7 +973,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett default_expr = ((char **)(fp->uf_def_args.ga_data)) [ai + fp->uf_def_args.ga_len]; - if (eval1(&default_expr, &def_rettv, true) == FAIL) { + if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL) { default_arg_err = true; break; } @@ -1109,7 +1110,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(&p, rettv, EVAL_EVALUATE); ex_nesting_level--; } else { // call do_cmdline() to execute the lines @@ -2953,7 +2954,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(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -3004,7 +3005,7 @@ void ex_call(exarg_T *eap) // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. emsg_skip++; - if (eval0(eap->arg, &rettv, &eap->nextcmd, false) != FAIL) { + if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL) { tv_clear(&rettv); } emsg_skip--; @@ -3071,7 +3072,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) + if (handle_subscript((const char **)&arg, &rettv, EVAL_EVALUATE, true) == FAIL) { failed = true; break; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9120cc4471..a3dc0cfc04 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -175,21 +175,13 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) /// ":let var ..= expr" assignment command. /// ":let [var1, var2] = expr" unpack list. /// ":let [name, ..., ; lastname] = expr" unpack list. -void ex_let(exarg_T *eap) -{ - ex_let_const(eap, false); -} - +/// /// ":cons[t] var = expr1" define constant /// ":cons[t] [name1, name2, ...] = expr1" define constants unpacking list /// ":cons[t] [name, ..., ; lastname] = expr" define constants unpacking list -void ex_const(exarg_T *eap) -{ - ex_let_const(eap, true); -} - -static void ex_let_const(exarg_T *eap, const bool is_const) +void ex_let(exarg_T *eap) { + const bool is_const = eap->cmdidx == CMD_const; char *arg = eap->arg; char *expr = NULL; typval_T rettv; @@ -208,8 +200,10 @@ static void ex_let_const(exarg_T *eap, const bool is_const) argend--; } expr = skipwhite(argend); - if (*expr != '=' && !((vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL - && expr[1] == '=') || strncmp(expr, "..=", 3) == 0)) { + bool concat = strncmp(expr, "..=", 3) == 0; + bool has_assign = *expr == '=' || (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL + && expr[1] == '='); + if (!has_assign && !concat) { // ":let" without "=": list variables if (*arg == '[') { emsg(_(e_invarg)); @@ -240,6 +234,8 @@ static void ex_let_const(exarg_T *eap, const bool is_const) tv_clear(&rettv); } } else { + rettv.v_type = VAR_UNKNOWN; + op[0] = '='; op[1] = NUL; if (*expr != '=') { @@ -259,7 +255,8 @@ static void ex_let_const(exarg_T *eap, const bool is_const) if (eap->skip) { emsg_skip++; } - i = eval0(expr, &rettv, &eap->nextcmd, !eap->skip); + int eval_flags = eap->skip ? 0 : EVAL_EVALUATE; + i = eval0(expr, &rettv, &eap->nextcmd, eval_flags); if (eap->skip) { if (i != FAIL) { tv_clear(&rettv); @@ -506,7 +503,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) } else { // handle d.key, l[idx], f(expr) const char *const arg_subsc = arg; - if (handle_subscript(&arg, &tv, true, true) == FAIL) { + if (handle_subscript(&arg, &tv, EVAL_EVALUATE, true) == FAIL) { error = true; } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { @@ -1713,7 +1710,7 @@ bool var_exists(const char *var) n = get_var_tv(name, len, &tv, NULL, false, true) == OK; if (n) { // Handle d.key, l[idx], f(expr). - n = handle_subscript(&var, &tv, true, false) == OK; + n = handle_subscript(&var, &tv, EVAL_EVALUATE, false) == OK; if (n) { tv_clear(&tv); } -- cgit From bd83b587b18bb6f2ac555a992fa5b7d907de7e79 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 07:22:01 +0800 Subject: vim-patch:8.2.1047: Vim9: script cannot use line continuation like :def function Problem: Vim9: script cannot use line continuation like in a :def function. Solution: Pass the getline function pointer to the eval() functions. Use it for addition and multiplication operators. https://github.com/vim/vim/commit/5409f5d8c95007216ae1190565a7a8ee9ebd7100 Omit source_nextline() and eval_next_non_blank(): Vim9 script only. N/A patches for version.c: vim-patch:8.2.1048: build failure without the eval feature Problem: Build failure without the eval feature. Solution: Add dummy typedef. https://github.com/vim/vim/commit/9d40c63c7dc8c3eb3886c58dcd334bc7f37eceba vim-patch:8.2.1052: build failure with older compilers Problem: Build failure with older compilers. Solution: Move declaration to start of block. https://github.com/vim/vim/commit/7acde51832f383f9a6d2e740cd0420b433ea841a Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/userfunc.c | 17 ++++++++++------- src/nvim/eval/vars.c | 11 ++++++++--- 3 files changed, 19 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 52e38b73ba..887a4857f6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1550,7 +1550,7 @@ static void f_eval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } const char *const expr_start = s; - if (s == NULL || eval1((char **)&s, rettv, EVAL_EVALUATE) == FAIL) { + if (s == NULL || eval1((char **)&s, rettv, &EVALARG_EVALUATE) == FAIL) { if (expr_start != NULL && !aborting()) { semsg(_(e_invexpr2), expr_start); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f82ab08d2d..d994a31039 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -152,7 +152,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int * p = skipwhite(p) + 1; p = skipwhite(p); char *expr = p; - if (eval1(&p, &rettv, 0) != FAIL) { + if (eval1(&p, &rettv, NULL) != FAIL) { ga_grow(default_args, 1); // trim trailing whitespace @@ -455,6 +455,8 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_ typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments int argcount = 0; // number of arguments found + evalarg_T evalarg = { .eval_flags = funcexe->fe_evaluate ? EVAL_EVALUATE : 0 }; + // Get the arguments. argp = *arg; while (argcount < MAX_FUNC_ARGS @@ -463,8 +465,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_ if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], - funcexe->fe_evaluate ? EVAL_EVALUATE : 0) == FAIL) { + if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL) { ret = FAIL; break; } @@ -973,7 +974,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett default_expr = ((char **)(fp->uf_def_args.ga_data)) [ai + fp->uf_def_args.ga_len]; - if (eval1(&default_expr, &def_rettv, EVAL_EVALUATE) == FAIL) { + if (eval1(&default_expr, &def_rettv, &EVALARG_EVALUATE) == FAIL) { default_arg_err = true; break; } @@ -1110,7 +1111,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, EVAL_EVALUATE); + (void)eval1(&p, rettv, &EVALARG_EVALUATE); ex_nesting_level--; } else { // call do_cmdline() to execute the lines @@ -2948,13 +2949,15 @@ void ex_return(exarg_T *eap) return; } + evalarg_T evalarg = { .eval_flags = eap->skip ? 0 : EVAL_EVALUATE }; + if (eap->skip) { emsg_skip++; } eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') - && eval0(arg, &rettv, &eap->nextcmd, eap->skip ? 0 : EVAL_EVALUATE) != FAIL) { + && eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -3005,7 +3008,7 @@ void ex_call(exarg_T *eap) // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. emsg_skip++; - if (eval0(eap->arg, &rettv, &eap->nextcmd, 0) != FAIL) { + if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL) { tv_clear(&rettv); } emsg_skip--; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index a3dc0cfc04..02e526d7b6 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -255,13 +255,18 @@ void ex_let(exarg_T *eap) if (eap->skip) { emsg_skip++; } - int eval_flags = eap->skip ? 0 : EVAL_EVALUATE; - i = eval0(expr, &rettv, &eap->nextcmd, eval_flags); + evalarg_T evalarg = { + .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, + .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, + }; + i = eval0(expr, &rettv, &eap->nextcmd, &evalarg); + if (eap->skip) { + emsg_skip--; + } if (eap->skip) { if (i != FAIL) { tv_clear(&rettv); } - emsg_skip--; } else if (i != FAIL) { (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); tv_clear(&rettv); -- cgit From 8e2903d2fe810cfa3be41fc1e7a4d8394c84cf11 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 09:11:37 +0800 Subject: vim-patch:8.2.1049: Vim9: leaking memory when using continuation line Problem: Vim9: leaking memory when using continuation line. Solution: Keep a pointer to the continuation line in evalarg_T. Centralize checking for a next command. https://github.com/vim/vim/commit/b171fb179053fa631fec74911b5fb9374cb6a8a1 Omit eval_next_line(): Vim9 script only. vim-patch:8.2.1050: missing change in struct Problem: Missing change in struct. Solution: Add missing change. https://github.com/vim/vim/commit/65a8ed37f7bc61fbe5c612a7b0eb0dfc16ad3e11 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 4 ++-- src/nvim/eval/vars.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index d994a31039..fe0249ea3a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2957,7 +2957,7 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') - && eval0(arg, &rettv, &eap->nextcmd, &evalarg) != FAIL) { + && eval0(arg, &rettv, eap, &evalarg) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -3008,7 +3008,7 @@ void ex_call(exarg_T *eap) // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. emsg_skip++; - if (eval0(eap->arg, &rettv, &eap->nextcmd, NULL) != FAIL) { + if (eval0(eap->arg, &rettv, eap, NULL) != FAIL) { tv_clear(&rettv); } emsg_skip--; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 02e526d7b6..bad676500b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -259,7 +259,7 @@ void ex_let(exarg_T *eap) .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, }; - i = eval0(expr, &rettv, &eap->nextcmd, &evalarg); + i = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) { emsg_skip--; } -- cgit From e8c25aac8d864e7033bcfe4640ee44054035f61d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 09:50:51 +0800 Subject: vim-patch:9.0.1447: condition is always true Problem: Condition is always true. Solution: Remove the useless condition. (closes vim/vim#12253) https://github.com/vim/vim/commit/474891bc89e657100bd37c29129451a0e601879d --- src/nvim/eval/vars.c | 74 +++++++++++++++++++++++++++------------------------- 1 file changed, 38 insertions(+), 36 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index bad676500b..79414acac9 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -185,7 +185,6 @@ void ex_let(exarg_T *eap) char *arg = eap->arg; char *expr = NULL; typval_T rettv; - int i; int var_count = 0; int semicolon = 0; char op[2]; @@ -221,7 +220,10 @@ void ex_let(exarg_T *eap) list_vim_vars(&first); } eap->nextcmd = check_nextcmd(arg); - } else if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { + return; + } + + if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { // HERE document list_T *l = heredoc_get(eap, expr + 3); if (l != NULL) { @@ -233,44 +235,44 @@ void ex_let(exarg_T *eap) } tv_clear(&rettv); } - } else { - rettv.v_type = VAR_UNKNOWN; - - op[0] = '='; - op[1] = NUL; - if (*expr != '=') { - if (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL) { - op[0] = *expr; // +=, -=, *=, /=, %= or .= - if (expr[0] == '.' && expr[1] == '.') { // ..= - expr++; - } - } - expr += 2; - } else { - expr += 1; - } + return; + } - expr = skipwhite(expr); + rettv.v_type = VAR_UNKNOWN; - if (eap->skip) { - emsg_skip++; - } - evalarg_T evalarg = { - .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, - .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, - }; - i = eval0(expr, &rettv, eap, &evalarg); - if (eap->skip) { - emsg_skip--; - } - if (eap->skip) { - if (i != FAIL) { - tv_clear(&rettv); + op[0] = '='; + op[1] = NUL; + if (*expr != '=') { + if (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL) { + op[0] = *expr; // +=, -=, *=, /=, %= or .= + if (expr[0] == '.' && expr[1] == '.') { // ..= + expr++; } - } else if (i != FAIL) { - (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); - tv_clear(&rettv); } + expr += 2; + } else { + expr += 1; + } + + expr = skipwhite(expr); + + if (eap->skip) { + emsg_skip++; + } + evalarg_T evalarg = { + .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, + .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, + }; + int eval_res = eval0(expr, &rettv, eap, &evalarg); + if (eap->skip) { + emsg_skip--; + } + + if (!eap->skip && eval_res != FAIL) { + (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); + } + if (eval_res != FAIL) { + tv_clear(&rettv); } } -- cgit From d927128fccad1c234e4b87321ff0d6392b9d69d5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 13:03:04 +0800 Subject: vim-patch:8.2.1071: Vim9: no line break allowed inside a lambda Problem: Vim9: no line break allowed inside a lambda. Solution: Handle line break inside a lambda in Vim9 script. https://github.com/vim/vim/commit/e40fbc2ca9fda07332a4da5af1fcaba91bed865b Omit skip_expr_concatenate(). Apply the change to skip_expr() instead. Omit eval_ga: Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 17 +++++++++++++---- src/nvim/eval/userfunc.h | 1 + src/nvim/eval/vars.c | 5 +++-- 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index fe0249ea3a..b1cb53fec2 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -252,8 +252,9 @@ static void set_ufunc_name(ufunc_T *fp, char *name) /// Parse a lambda expression and get a Funcref from "*arg". /// /// @return OK or FAIL. Returns NOTDONE for dict or {expr}. -int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) +int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) { + const bool evaluate = evalarg != NULL && (evalarg->eval_flags & EVAL_EVALUATE); garray_T newargs = GA_EMPTY_INIT_VALUE; garray_T *pnewargs; ufunc_T *fp = NULL; @@ -264,6 +265,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) char *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; + char *tofree = NULL; // First, check if this is a lambda expression. "->" must exists. ret = get_function_args(&start, '-', NULL, NULL, NULL, true); @@ -291,10 +293,16 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) // Get the start and the end of the expression. *arg = skipwhite((*arg) + 1); s = *arg; - ret = skip_expr(arg); + ret = skip_expr(arg, evalarg); if (ret == FAIL) { goto errret; } + if (evalarg != NULL) { + // avoid that the expression gets freed when another line break follows + tofree = evalarg->eval_tofree; + evalarg->eval_tofree = NULL; + } + e = *arg; *arg = skipwhite(*arg); if (**arg != '}') { @@ -359,12 +367,14 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) } eval_lavars_used = old_eval_lavars; + xfree(tofree); return OK; errret: ga_clear_strings(&newargs); xfree(fp); xfree(pt); + xfree(tofree); eval_lavars_used = old_eval_lavars; return FAIL; } @@ -3075,8 +3085,7 @@ void ex_call(exarg_T *eap) } // Handle a function returning a Funcref, Dictionary or List. - if (handle_subscript((const char **)&arg, &rettv, EVAL_EVALUATE, true) - == FAIL) { + if (handle_subscript((const char **)&arg, &rettv, &EVALARG_EVALUATE, true) == FAIL) { failed = true; break; } diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index c8583f232c..f0e1f5dca0 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -4,6 +4,7 @@ #include #include +#include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 79414acac9..c566129202 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -267,6 +267,7 @@ void ex_let(exarg_T *eap) if (eap->skip) { emsg_skip--; } + xfree(evalarg.eval_tofree); if (!eap->skip && eval_res != FAIL) { (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); @@ -510,7 +511,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) } else { // handle d.key, l[idx], f(expr) const char *const arg_subsc = arg; - if (handle_subscript(&arg, &tv, EVAL_EVALUATE, true) == FAIL) { + if (handle_subscript(&arg, &tv, &EVALARG_EVALUATE, true) == FAIL) { error = true; } else { if (arg == arg_subsc && len == 2 && name[1] == ':') { @@ -1717,7 +1718,7 @@ bool var_exists(const char *var) n = get_var_tv(name, len, &tv, NULL, false, true) == OK; if (n) { // Handle d.key, l[idx], f(expr). - n = handle_subscript(&var, &tv, EVAL_EVALUATE, false) == OK; + n = handle_subscript(&var, &tv, &EVALARG_EVALUATE, false) == OK; if (n) { tv_clear(&tv); } -- cgit From e99f28e57d69cfa1bd38ab531a0954f4f875ca47 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 13:32:47 +0800 Subject: vim-patch:8.2.1076: Vim9: no line break allowed in :if expression Problem: Vim9: no line break allowed in :if expression. Solution: Skip linebreak. https://github.com/vim/vim/commit/faf8626b79e380fe81e7ae2439a535ed7619d27b Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index c566129202..868d03a115 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -267,7 +267,7 @@ void ex_let(exarg_T *eap) if (eap->skip) { emsg_skip--; } - xfree(evalarg.eval_tofree); + clear_evalarg(&evalarg, eap); if (!eap->skip && eval_res != FAIL) { (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op); -- cgit From 4b84b2e2aa3d7ab6a4e346c7439826700682f5f1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 13:38:14 +0800 Subject: vim-patch:8.2.1079: Vim9: no line break allowed in a while loop Problem: Vim9: no line break allowed in a while loop. Solution: Update stored loop lines when finding line breaks. https://github.com/vim/vim/commit/d5053d015a957b343ad9c9e45e0abd2978f10cf0 Omit getline_peek(): Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 868d03a115..4bce555d75 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -261,8 +261,11 @@ void ex_let(exarg_T *eap) } evalarg_T evalarg = { .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, - .eval_cookie = eap->getline == getsourceline ? eap->cookie : NULL, }; + if (getline_equal(eap->getline, eap->cookie, getsourceline)) { + evalarg.eval_getline = eap->getline; + evalarg.eval_cookie = eap->cookie; + } int eval_res = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) { emsg_skip--; -- cgit From 8729c41f44de3b164ad8d01bb3558c6400e27952 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 13:49:28 +0800 Subject: vim-patch:8.2.1080: Vim9: no line break allowed in a for loop Problem: Vim9: no line break allowed in a for loop. Solution: Skip line breaks in for command. https://github.com/vim/vim/commit/b7a78f7a6713f07d2fcad0b27dea22925c7b1cdf Omit *_break_count and skip_for_lines(): Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index b1cb53fec2..1f25b7fb36 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2996,6 +2996,7 @@ void ex_return(exarg_T *eap) if (eap->skip) { emsg_skip--; } + clear_evalarg(&evalarg, eap); } /// ":1,25call func(arg1, arg2)" function call. -- cgit From cf37630d1b1443427c13e0a35e0a12b39e1415db Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 14:24:50 +0800 Subject: vim-patch:8.2.1110: Vim9: line continuation does not work in function arguments Problem: Vim9: line continuation does not work in function arguments. Solution: Pass "evalarg" to get_func_tv(). Fix seeing double quoted string as comment. https://github.com/vim/vim/commit/e6b5324e3a3d354363f3c48e784c42ce3e77453f Omit skipwhite_and_linebreak_keep_string(): Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1f25b7fb36..3fc34471bf 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -458,15 +458,14 @@ void emsg_funcname(const char *errmsg, const char *name) /// @param funcexe various values /// /// @return OK or FAIL. -int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_T *funcexe) +int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_T *const evalarg, + funcexe_T *funcexe) { char *argp; int ret = OK; typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments int argcount = 0; // number of arguments found - evalarg_T evalarg = { .eval_flags = funcexe->fe_evaluate ? EVAL_EVALUATE : 0 }; - // Get the arguments. argp = *arg; while (argcount < MAX_FUNC_ARGS @@ -475,7 +474,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_ if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], &evalarg) == FAIL) { + if (eval1(&argp, &argvars[argcount], evalarg) == FAIL) { ret = FAIL; break; } @@ -3013,16 +3012,19 @@ void ex_call(exarg_T *eap) bool failed = false; funcdict_T fudi; partial_T *partial = NULL; + evalarg_T evalarg; + fill_evalarg_from_eap(&evalarg, eap, eap->skip); if (eap->skip) { // trans_function_name() doesn't work well when skipping, use eval0() // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. emsg_skip++; - if (eval0(eap->arg, &rettv, eap, NULL) != FAIL) { + if (eval0(eap->arg, &rettv, eap, &evalarg) != FAIL) { tv_clear(&rettv); } emsg_skip--; + clear_evalarg(&evalarg, eap); return; } @@ -3080,7 +3082,7 @@ void ex_call(exarg_T *eap) funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; - if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL) { + if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL) { failed = true; break; } @@ -3118,6 +3120,7 @@ void ex_call(exarg_T *eap) eap->nextcmd = check_nextcmd(arg); } } + clear_evalarg(&evalarg, eap); end: tv_dict_unref(fudi.fd_dict); -- cgit From cc7a50a9ae9384167bd0fc2ee2eb7f1b31842f27 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 15:05:12 +0800 Subject: vim-patch:8.2.1161: Vim9: using freed memory Problem: Vim9: using freed memory. Solution: Put pointer back in evalarg instead of freeing it. https://github.com/vim/vim/commit/8e2730a315b8b06192f5fc822dc218dbb3cff7ae Omit eval_tofree_lambda: Vim9 script only. N/A patches for version.c: vim-patch:8.2.1163: build error Problem: Build error. Solution: Add missing change to globals. https://github.com/vim/vim/commit/6e13530ca03dd9cad245221177dd65f712211448 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 3fc34471bf..9440ceb36e 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -261,15 +261,14 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) partial_T *pt = NULL; int varargs; int ret; - char *start = skipwhite(*arg + 1); - char *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; char *tofree = NULL; // First, check if this is a lambda expression. "->" must exists. - ret = get_function_args(&start, '-', NULL, NULL, NULL, true); - if (ret == FAIL || *start != '>') { + char *s = skipwhite(*arg + 1); + ret = get_function_args(&s, '-', NULL, NULL, NULL, true); + if (ret == FAIL || *s != '>') { return NOTDONE; } @@ -292,8 +291,9 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) // Get the start and the end of the expression. *arg = skipwhite((*arg) + 1); - s = *arg; + char *start = *arg; ret = skip_expr(arg, evalarg); + char *end = *arg; if (ret == FAIL) { goto errret; } @@ -303,7 +303,6 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) evalarg->eval_tofree = NULL; } - e = *arg; *arg = skipwhite(*arg); if (**arg != '}') { semsg(_("E451: Expected }: %s"), *arg); @@ -325,11 +324,11 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) ga_grow(&newlines, 1); // Add "return " before the expression. - size_t len = (size_t)(7 + e - s + 1); + size_t len = (size_t)(7 + end - start + 1); p = xmalloc(len); ((char **)(newlines.ga_data))[newlines.ga_len++] = p; STRCPY(p, "return "); - xstrlcpy(p + 7, s, (size_t)(e - s) + 1); + xstrlcpy(p + 7, start, (size_t)(end - start) + 1); if (strstr(p + 7, "a:") == NULL) { // No a: variables are used for sure. flags |= FC_NOARGS; @@ -367,14 +366,22 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) } eval_lavars_used = old_eval_lavars; - xfree(tofree); + if (evalarg->eval_tofree == NULL) { + evalarg->eval_tofree = tofree; + } else { + xfree(tofree); + } return OK; errret: ga_clear_strings(&newargs); xfree(fp); xfree(pt); - xfree(tofree); + if (evalarg->eval_tofree == NULL) { + evalarg->eval_tofree = tofree; + } else { + xfree(tofree); + } eval_lavars_used = old_eval_lavars; return FAIL; } -- cgit From c804c7df0cf3259b4ee3e286293b43529c9e42d6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 15:24:57 +0800 Subject: vim-patch:8.2.1162: crash when using a lambda Problem: Crash when using a lambda. Solution: Check for evalarg to be NULL. https://github.com/vim/vim/commit/efaaaa683b7b0cebc128be5c0c257b9d6578ac96 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9440ceb36e..f73d22243d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -366,7 +366,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) } eval_lavars_used = old_eval_lavars; - if (evalarg->eval_tofree == NULL) { + if (evalarg != NULL && evalarg->eval_tofree == NULL) { evalarg->eval_tofree = tofree; } else { xfree(tofree); @@ -377,7 +377,7 @@ errret: ga_clear_strings(&newargs); xfree(fp); xfree(pt); - if (evalarg->eval_tofree == NULL) { + if (evalarg != NULL && evalarg->eval_tofree == NULL) { evalarg->eval_tofree = tofree; } else { xfree(tofree); -- cgit From 9c66b48316d85d24ee92d917765700713862aa2d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 14:57:22 +0800 Subject: vim-patch:8.2.3216: Vim9: crash when using variable in a loop at script level Problem: Vim9: crash when using variable in a loop at script level. Solution: Do not clear the variable if a function was defined. Do not create a new entry in sn_var_vals every time. (closes vim/vim#8628) https://github.com/vim/vim/commit/2eb6fc3b52148f961e804ec2be361d531ff770d8 Omit eval_cstack: Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 4bce555d75..c4a9823c0a 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -259,13 +259,8 @@ void ex_let(exarg_T *eap) if (eap->skip) { emsg_skip++; } - evalarg_T evalarg = { - .eval_flags = eap->skip ? 0 : EVAL_EVALUATE, - }; - if (getline_equal(eap->getline, eap->cookie, getsourceline)) { - evalarg.eval_getline = eap->getline; - evalarg.eval_cookie = eap->cookie; - } + evalarg_T evalarg; + fill_evalarg_from_eap(&evalarg, eap, eap->skip); int eval_res = eval0(expr, &rettv, eap, &evalarg); if (eap->skip) { emsg_skip--; -- cgit From d6e2804ab4f8810293dbcd748bfb938d9e0c3d52 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 11:00:17 +0800 Subject: vim-patch:8.2.1794: no falsy Coalescing operator Problem: No falsy Coalescing operator. Solution: Add the "??" operator. Fix mistake with function argument count. https://github.com/vim/vim/commit/92f26c256e06277ff2ec4ce7adea1eb58c85abe0 Cherry-pick tv2bool() into eval/typval.c. Cherry-pick *??* tag from Vim runtime. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 3e67571053..91be41751e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -4201,3 +4201,34 @@ const char *tv_get_string_buf(const typval_T *const tv, char *const buf) return res != NULL ? res : ""; } + +/// Return true when "tv" is not falsy: non-zero, non-empty string, non-empty +/// list, etc. Mostly like what JavaScript does, except that empty list and +/// empty dictionary are false. +bool tv2bool(const typval_T *const tv) +{ + switch (tv->v_type) { + case VAR_NUMBER: + return tv->vval.v_number != 0; + case VAR_FLOAT: + return tv->vval.v_float != 0.0; + case VAR_PARTIAL: + return tv->vval.v_partial != NULL; + case VAR_FUNC: + case VAR_STRING: + return tv->vval.v_string != NULL && *tv->vval.v_string != NUL; + case VAR_LIST: + return tv->vval.v_list != NULL && tv->vval.v_list->lv_len > 0; + case VAR_DICT: + return tv->vval.v_dict != NULL && tv->vval.v_dict->dv_hashtab.ht_used > 0; + case VAR_BOOL: + return tv->vval.v_bool == kBoolVarTrue; + case VAR_SPECIAL: + return tv->vval.v_special == kSpecialVarNull; + case VAR_BLOB: + return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; + case VAR_UNKNOWN: + break; + } + return false; +} -- cgit From 90efe85a99c7986acccc8af370cfb179ae18aeff Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 19:28:39 +0800 Subject: vim-patch:8.2.1111: inconsistent naming of get_list_tv() and eval_dict() (#23086) Problem: Inconsistent naming of get_list_tv() and eval_dict(). Solution: Rename get_list_tv() to eval_list(). Similarly for eval_number(), eval_string(), eval_lit_string() and a few others. https://github.com/vim/vim/commit/9a78e6df17033223ebdf499f2b02b2538601c52d Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 887a4857f6..23d0242ce4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1722,7 +1722,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(exp); } } else if (*p == '&' || *p == '+') { // Option. - n = (get_option_tv(&p, NULL, true) == OK); + n = (eval_option(&p, NULL, true) == OK); if (*skipwhite(p) != NUL) { n = false; // Trailing garbage. } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index c4a9823c0a..b8a8f39437 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -503,8 +503,7 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) if (tofree != NULL) { name = tofree; } - if (get_var_tv(name, len, &tv, NULL, true, false) - == FAIL) { + if (eval_variable(name, len, &tv, NULL, true, false) == FAIL) { error = true; } else { // handle d.key, l[idx], f(expr) @@ -1076,8 +1075,8 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap /// @param dip non-NULL when typval's dict item is needed /// @param verbose may give error message /// @param no_autoload do not use script autoloading -int get_var_tv(const char *name, int len, typval_T *rettv, dictitem_T **dip, bool verbose, - bool no_autoload) +int eval_variable(const char *name, int len, typval_T *rettv, dictitem_T **dip, bool verbose, + bool no_autoload) { int ret = OK; typval_T *tv = NULL; @@ -1564,7 +1563,7 @@ static void get_var_from(const char *varname, typval_T *rettv, typval_T *deftv, tv_dict_set_ret(rettv, opts); done = true; } - } else if (get_option_tv(&varname, rettv, true) == OK) { + } else if (eval_option(&varname, rettv, true) == OK) { // Local option done = true; } @@ -1713,7 +1712,7 @@ bool var_exists(const char *var) if (tofree != NULL) { name = tofree; } - n = get_var_tv(name, len, &tv, NULL, false, true) == OK; + n = eval_variable(name, len, &tv, NULL, false, true) == OK; if (n) { // Handle d.key, l[idx], f(expr). n = handle_subscript(&var, &tv, &EVALARG_EVALUATE, false) == OK; -- cgit From e36806666fe3c5792c39f0f9127e6637a6ceb7f2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 20:35:46 +0800 Subject: vim-patch:8.2.2138: Vim9: "exit_cb" causes Vim to exit (#23087) Problem: Vim9: "exit_cb" causes Vim to exit. Solution: Require white space after a command in Vim9 script. (closes vim/vim#7467) Also fix that Vim9 style heredoc was not always recognized. https://github.com/vim/vim/commit/b5b9480ee936ef4cd0e350c468ef8c5f42fa398b Omit EX_NONWHITE_OK, E1143, E1144: Vim9 script only. Cherry-pick test_vimscript.vim changes from patch 8.2.2141. Cherry-pick E1145 tag from Vim runtime. N/A patches for version.c: vim-patch:8.2.2140: build failure with tiny features Problem: Build failure with tiny features. Solution: Add #ifdef. https://github.com/vim/vim/commit/2a3cd3af455973d678f70303ebdd486f3478bc0d Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f73d22243d..178f9fd6b6 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -71,6 +71,8 @@ static const char *e_funcref = N_("E718: Funcref required"); static const char *e_nofunc = N_("E130: Unknown function: %s"); static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); +static const char e_missing_heredoc_end_marker_str[] + = N_("E1145: Missing heredoc end marker: %s"); void func_init(void) { @@ -2319,7 +2321,11 @@ void ex_function(exarg_T *eap) lines_left = Rows - 1; } if (theline == NULL) { - emsg(_("E126: Missing :endfunction")); + if (skip_until != NULL) { + semsg(_(e_missing_heredoc_end_marker_str), skip_until); + } else { + emsg(_("E126: Missing :endfunction")); + } goto erret; } if (show_block) { -- cgit From ae9654dd7336e263e18ca7da4a40a25ec684002d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 21:56:13 +0800 Subject: vim-patch:8.2.4055: Vim9: line break in expression causes v:errmsg to be fillec (#23090) Problem: Vim9: line break in expression causes v:errmsg to be filled. (Yegappan Lakshmanan) Solution: Do not give an error when skipping over an expression. https://github.com/vim/vim/commit/5e6b9882fe0218ae4878f6ad0561c8654a2277d8 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 178f9fd6b6..67c73924c8 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -474,6 +474,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_ int ret = OK; typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments int argcount = 0; // number of arguments found + const bool evaluate = evalarg == NULL ? false : (evalarg->eval_flags & EVAL_EVALUATE); // Get the arguments. argp = *arg; @@ -515,7 +516,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_ ret = call_func(name, len, rettv, argcount, argvars, funcexe); funcargs.ga_len -= i; - } else if (!aborting()) { + } else if (!aborting() && evaluate) { if (argcount == MAX_FUNC_ARGS) { emsg_funcname(N_("E740: Too many arguments for function %s"), name); } else { -- cgit From 4c276bbd1887c09350fca4bdb355a2afde3ef471 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 15 Apr 2023 13:10:36 +0800 Subject: vim-patch:8.2.0103: using null object with execute() has strange effects Problem: Using null object with execute() has strange effects. Solution: Give an error message ofr Job and Channel. https://github.com/vim/vim/commit/e2a8f0773e91685843c062b1e48259712d5f2213 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 91be41751e..7c982de61e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3806,7 +3806,7 @@ static const char *const str_errors[] = { [VAR_DICT]= N_("E731: using Dictionary as a String"), [VAR_FLOAT]= e_float_as_string, [VAR_BLOB]= N_("E976: using Blob as a String"), - [VAR_UNKNOWN]= N_("E908: using an invalid value as a String"), + [VAR_UNKNOWN]= e_inval_string, }; #undef FUNC_ERROR -- cgit From 3ad8c08acc506555667a070cf83c410ac9334f1e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 19:45:54 +0800 Subject: vim-patch:8.2.4770: cannot easily mix expression and heredoc Problem: Cannot easily mix expression and heredoc. Solution: Support in heredoc. (Yegappan Lakshmanan, closes vim/vim#10138) https://github.com/vim/vim/commit/efbfa867a146fcd93fdec2435597aa4ae7f1325c Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 17 +++++-- src/nvim/eval/vars.c | 119 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 117 insertions(+), 19 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 67c73924c8..67b1e53a35 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2483,10 +2483,19 @@ void ex_function(exarg_T *eap) && (!ASCII_ISALNUM(p[2]) || (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) { p = skipwhite(arg + 3); - if (strncmp(p, "trim", 4) == 0) { - // Ignore leading white space. - p = skipwhite(p + 4); - heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); + while (true) { + if (strncmp(p, "trim", 4) == 0) { + // Ignore leading white space. + p = skipwhite(p + 4); + heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); + continue; + } + if (strncmp(p, "eval", 4) == 0) { + // Ignore leading white space. + p = skipwhite(p + 4); + continue; + } + break; } skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p)); do_concat = false; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index b8a8f39437..3905cf82a6 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -53,6 +53,56 @@ static const char *e_letunexp = N_("E18: Unexpected characters in :let"); static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); +/// Evaluate all the Vim expressions (`=expr`) in string "str" and return the +/// resulting string. The caller must free the returned string. +static char *eval_all_expr_in_str(char *str) +{ + garray_T ga; + ga_init(&ga, 1, 80); + char *p = str; + + // Look for `=expr`, evaluate the expression and replace `=expr` with the + // result. + while (*p != NUL) { + char *s = p; + while (*p != NUL && (*p != '`' || p[1] != '=')) { + p++; + } + ga_concat_len(&ga, s, (size_t)(p - s)); + if (*p == NUL) { + break; // no backtick expression found + } + s = p; + p += 2; // skip `= + + int status = *p == NUL ? OK : skip_expr(&p, NULL); + if (status == FAIL || *p != '`') { + // invalid expression or missing ending backtick + if (status != FAIL) { + emsg(_("E1083: Missing backtick")); + } + xfree(ga.ga_data); + return NULL; + } + s += 2; // skip `= + char save_c = *p; + *p = NUL; + char *exprval = eval_to_string(s, true); + *p = save_c; + p++; + if (exprval == NULL) { + // expression evaluation failed + xfree(ga.ga_data); + return NULL; + } + ga_concat(&ga, exprval); + xfree(exprval); + } + ga_append(&ga, NUL); + + return ga.ga_data; +} + /// Get a list of lines from a HERE document. The here document is a list of /// lines surrounded by a marker. /// cmd << {marker} @@ -65,7 +115,7 @@ static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s") /// marker, then the leading indentation before the lines (matching the /// indentation in the 'cmd' line) is stripped. /// -/// @return a List with {lines} or NULL. +/// @return a List with {lines} or NULL on failure. static list_T *heredoc_get(exarg_T *eap, char *cmd) { char *marker; @@ -81,20 +131,33 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) // Check for the optional 'trim' word before the marker cmd = skipwhite(cmd); - if (strncmp(cmd, "trim", 4) == 0 - && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { - cmd = skipwhite(cmd + 4); - - // Trim the indentation from all the lines in the here document. - // The amount of indentation trimmed is the same as the indentation of - // the first line after the :let command line. To find the end marker - // the indent of the :let command line is trimmed. - p = *eap->cmdlinep; - while (ascii_iswhite(*p)) { - p++; - marker_indent_len++; + bool evalstr = false; + bool eval_failed = false; + while (true) { + if (strncmp(cmd, "trim", 4) == 0 + && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { + cmd = skipwhite(cmd + 4); + + // Trim the indentation from all the lines in the here document. + // The amount of indentation trimmed is the same as the indentation + // of the first line after the :let command line. To find the end + // marker the indent of the :let command line is trimmed. + p = *eap->cmdlinep; + while (ascii_iswhite(*p)) { + p++; + marker_indent_len++; + } + text_indent_len = -1; + + continue; + } + if (strncmp(cmd, "eval", 4) == 0 + && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { + cmd = skipwhite(cmd + 4); + evalstr = true; + continue; } - text_indent_len = -1; + break; } // The marker is the next word. @@ -136,6 +199,14 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) xfree(theline); break; } + + // If expression evaluation failed in the heredoc, then skip till the + // end marker. + if (eval_failed) { + xfree(theline); + continue; + } + if (text_indent_len == -1 && *theline != NUL) { // set the text indent from the first line. p = theline; @@ -155,11 +226,29 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) } } - tv_list_append_string(l, theline + ti, -1); + char *str = theline + ti; + if (evalstr) { + str = eval_all_expr_in_str(str); + if (str == NULL) { + // expression evaluation failed + xfree(theline); + eval_failed = true; + continue; + } + xfree(theline); + theline = str; + } + + tv_list_append_string(l, str, -1); xfree(theline); } xfree(text_indent); + if (eval_failed) { + // expression evaluation in the heredoc failed + tv_list_free(l); + return NULL; + } return l; } -- cgit From 3c16e75ae194f728c703032084a8f6dd0833a563 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 21:00:08 +0800 Subject: vim-patch:8.2.4783: Coverity warns for leaking memory Problem: Coverity warns for leaking memory. Solution: Use another strategy freeing "theline". https://github.com/vim/vim/commit/42ccb8d74700506936567b0eb6d11def5e25e1dd Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3905cf82a6..048b5ee2aa 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -178,12 +178,14 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) return NULL; } + char *theline = NULL; list_T *l = tv_list_alloc(0); for (;;) { int mi = 0; int ti = 0; - char *theline = eap->getline(NUL, eap->cookie, 0, false); + xfree(theline); + theline = eap->getline(NUL, eap->cookie, 0, false); if (theline == NULL) { semsg(_("E990: Missing end marker '%s'"), marker); break; @@ -196,14 +198,12 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) mi = marker_indent_len; } if (strcmp(marker, theline + mi) == 0) { - xfree(theline); break; } // If expression evaluation failed in the heredoc, then skip till the // end marker. if (eval_failed) { - xfree(theline); continue; } @@ -231,7 +231,6 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) str = eval_all_expr_in_str(str); if (str == NULL) { // expression evaluation failed - xfree(theline); eval_failed = true; continue; } @@ -240,8 +239,8 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) } tv_list_append_string(l, str, -1); - xfree(theline); } + xfree(theline); xfree(text_indent); if (eval_failed) { -- cgit From 2cf8f01e7d0469b592bacecd5f224b4fe3149a62 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 21:06:15 +0800 Subject: vim-patch:8.2.4840: heredoc expression evaluated even when skipping Problem: Heredoc expression evaluated even when skipping. Solution: Don't evaluate when "skip" is set. (closes vim/vim#10306) https://github.com/vim/vim/commit/05c7f5d3d03440da6f69604f8c06c4e3d90d2a26 Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 048b5ee2aa..a8d1e01152 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -227,7 +227,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) } char *str = theline + ti; - if (evalstr) { + if (evalstr && !eap->skip) { str = eval_all_expr_in_str(str); if (str == NULL) { // expression evaluation failed -- cgit From bacb5021d4eff33c67eb659fb01125b2abcacd79 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 14 Apr 2023 21:08:00 +0800 Subject: vim-patch:8.2.4883: string interpolation only works in heredoc Problem: String interpolation only works in heredoc. Solution: Support interpolated strings. Use syntax for heredoc consistent with strings, similar to C#. (closes vim/vim#10327) https://github.com/vim/vim/commit/2eaef106e4a7fc9dc74a7e672b5f550ec1f9786e Cherry-pick Test_Debugger_breakadd_expr() from Vim. Co-authored-by: LemonBoy --- src/nvim/eval/vars.c | 81 +++++++++++++++++++++++++++++++++------------------- 1 file changed, 52 insertions(+), 29 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index a8d1e01152..b86c49fd98 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -53,50 +53,73 @@ static const char *e_letunexp = N_("E18: Unexpected characters in :let"); static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); -/// Evaluate all the Vim expressions (`=expr`) in string "str" and return the +/// Evaluate all the Vim expressions ({expr}) in string "str" and return the /// resulting string. The caller must free the returned string. -static char *eval_all_expr_in_str(char *str) +char *eval_all_expr_in_str(char *str) { garray_T ga; ga_init(&ga, 1, 80); char *p = str; - // Look for `=expr`, evaluate the expression and replace `=expr` with the - // result. while (*p != NUL) { - char *s = p; - while (*p != NUL && (*p != '`' || p[1] != '=')) { - p++; + bool escaped_brace = false; + + // Look for a block start. + char *lit_start = p; + while (*p != '{' && *p != '}' && *p != NUL) { + ++p; + } + + if (*p != NUL && *p == p[1]) { + // Escaped brace, unescape and continue. + // Include the brace in the literal string. + ++p; + escaped_brace = true; + } else if (*p == '}') { + semsg(_(e_stray_closing_curly_str), str); + ga_clear(&ga); + return NULL; } - ga_concat_len(&ga, s, (size_t)(p - s)); + + // Append the literal part. + ga_concat_len(&ga, lit_start, (size_t)(p - lit_start)); + if (*p == NUL) { - break; // no backtick expression found + break; } - s = p; - p += 2; // skip `= - int status = *p == NUL ? OK : skip_expr(&p, NULL); - if (status == FAIL || *p != '`') { - // invalid expression or missing ending backtick - if (status != FAIL) { - emsg(_("E1083: Missing backtick")); - } - xfree(ga.ga_data); + if (escaped_brace) { + // Skip the second brace. + ++p; + continue; + } + + // Skip the opening {. + char *block_start = ++p; + char *block_end = block_start; + if (*block_start != NUL && skip_expr(&block_end, NULL) == FAIL) { + ga_clear(&ga); return NULL; } - s += 2; // skip `= - char save_c = *p; - *p = NUL; - char *exprval = eval_to_string(s, true); - *p = save_c; - p++; - if (exprval == NULL) { - // expression evaluation failed - xfree(ga.ga_data); + block_end = skipwhite(block_end); + // The block must be closed by a }. + if (*block_end != '}') { + semsg(_(e_missing_close_curly_str), str); + ga_clear(&ga); return NULL; } - ga_concat(&ga, exprval); - xfree(exprval); + char save_c = *block_end; + *block_end = NUL; + char *expr_val = eval_to_string(block_start, true); + *block_end = save_c; + if (expr_val == NULL) { + ga_clear(&ga); + return NULL; + } + ga_concat(&ga, expr_val); + xfree(expr_val); + + p = block_end + 1; } ga_append(&ga, NUL); -- cgit From ef9af89da753235c64cbd8b7d700c686bc94dad7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 15 Apr 2023 17:51:39 +0800 Subject: vim-patch:8.2.4930: interpolated string expression requires escaping Problem: Interpolated string expression requires escaping. Solution: Do not require escaping in the expression. https://github.com/vim/vim/commit/0abc2871c105882ed1c1effb9a7757fad8a395bd Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 70 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 42 insertions(+), 28 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index b86c49fd98..7ae7b5a57a 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -53,8 +53,42 @@ static const char *e_letunexp = N_("E18: Unexpected characters in :let"); static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); -/// Evaluate all the Vim expressions ({expr}) in string "str" and return the -/// resulting string. The caller must free the returned string. +/// Evaluate one Vim expression {expr} in string "p" and append the +/// resulting string to "gap". "p" points to the opening "{". +/// Return a pointer to the character after "}", NULL for an error. +char *eval_one_expr_in_str(char *p, garray_T *gap) +{ + char *block_start = skipwhite(p + 1); // skip the opening { + char *block_end = block_start; + + if (*block_start == NUL) { + semsg(_(e_missing_close_curly_str), p); + return NULL; + } + if (skip_expr(&block_end, NULL) == FAIL) { + return NULL; + } + block_end = skipwhite(block_end); + if (*block_end != '}') { + semsg(_(e_missing_close_curly_str), p); + return NULL; + } + *block_end = NUL; + char *expr_val = eval_to_string(block_start, true); + *block_end = '}'; + if (expr_val == NULL) { + return NULL; + } + ga_concat(gap, expr_val); + xfree(expr_val); + + return block_end + 1; +} + +/// Evaluate all the Vim expressions {expr} in "str" and return the resulting +/// string in allocated memory. "{{" is reduced to "{" and "}}" to "}". +/// Used for a heredoc assignment. +/// Returns NULL for an error. char *eval_all_expr_in_str(char *str) { garray_T ga; @@ -67,13 +101,13 @@ char *eval_all_expr_in_str(char *str) // Look for a block start. char *lit_start = p; while (*p != '{' && *p != '}' && *p != NUL) { - ++p; + p++; } if (*p != NUL && *p == p[1]) { // Escaped brace, unescape and continue. // Include the brace in the literal string. - ++p; + p++; escaped_brace = true; } else if (*p == '}') { semsg(_(e_stray_closing_curly_str), str); @@ -90,36 +124,16 @@ char *eval_all_expr_in_str(char *str) if (escaped_brace) { // Skip the second brace. - ++p; + p++; continue; } - // Skip the opening {. - char *block_start = ++p; - char *block_end = block_start; - if (*block_start != NUL && skip_expr(&block_end, NULL) == FAIL) { - ga_clear(&ga); - return NULL; - } - block_end = skipwhite(block_end); - // The block must be closed by a }. - if (*block_end != '}') { - semsg(_(e_missing_close_curly_str), str); + // Evaluate the expression and append the result. + p = eval_one_expr_in_str(p, &ga); + if (p == NULL) { ga_clear(&ga); return NULL; } - char save_c = *block_end; - *block_end = NUL; - char *expr_val = eval_to_string(block_start, true); - *block_end = save_c; - if (expr_val == NULL) { - ga_clear(&ga); - return NULL; - } - ga_concat(&ga, expr_val); - xfree(expr_val); - - p = block_end + 1; } ga_append(&ga, NUL); -- cgit From 29efd54e0284727a7dde5608e5eedaef9c00c65f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 15 Apr 2023 18:19:47 +0800 Subject: vim-patch:8.2.4934: string interpolation fails when not evaluating Problem: String interpolation fails when not evaluating. Solution: Skip the expression when not evaluating. (closes vim/vim#10398) https://github.com/vim/vim/commit/70c41241c2701f26a99085e433925a206ca265a3 Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 7ae7b5a57a..d3ca2624eb 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -55,8 +55,9 @@ static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s") /// Evaluate one Vim expression {expr} in string "p" and append the /// resulting string to "gap". "p" points to the opening "{". +/// When "evaluate" is false only skip over the expression. /// Return a pointer to the character after "}", NULL for an error. -char *eval_one_expr_in_str(char *p, garray_T *gap) +char *eval_one_expr_in_str(char *p, garray_T *gap, bool evaluate) { char *block_start = skipwhite(p + 1); // skip the opening { char *block_end = block_start; @@ -73,14 +74,16 @@ char *eval_one_expr_in_str(char *p, garray_T *gap) semsg(_(e_missing_close_curly_str), p); return NULL; } - *block_end = NUL; - char *expr_val = eval_to_string(block_start, true); - *block_end = '}'; - if (expr_val == NULL) { - return NULL; + if (evaluate) { + *block_end = NUL; + char *expr_val = eval_to_string(block_start, true); + *block_end = '}'; + if (expr_val == NULL) { + return NULL; + } + ga_concat(gap, expr_val); + xfree(expr_val); } - ga_concat(gap, expr_val); - xfree(expr_val); return block_end + 1; } @@ -129,7 +132,7 @@ char *eval_all_expr_in_str(char *str) } // Evaluate the expression and append the result. - p = eval_one_expr_in_str(p, &ga); + p = eval_one_expr_in_str(p, &ga, true); if (p == NULL) { ga_clear(&ga); return NULL; -- cgit From 9770dcf96d77d734e2b88fc693c0f4fa0a17ef74 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 15 Apr 2023 21:05:55 +0800 Subject: refactor: remove FC_DEAD It's for Vim9 script only. --- src/nvim/eval/userfunc.c | 11 +++++------ src/nvim/eval/userfunc.h | 6 +++--- 2 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 67b1e53a35..9705bc93db 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2015,12 +2015,11 @@ static void list_functions(regmatch_T *regmatch) if (!HASHITEM_EMPTY(hi)) { ufunc_T *fp = HI2UF(hi); todo--; - if ((fp->uf_flags & FC_DEAD) == 0 - && (regmatch == NULL - ? (!message_filtered(fp->uf_name) - && !func_name_refcount(fp->uf_name)) - : (!isdigit((uint8_t)(*fp->uf_name)) - && vim_regexec(regmatch, fp->uf_name, 0)))) { + if (regmatch == NULL + ? (!message_filtered(fp->uf_name) + && !func_name_refcount(fp->uf_name)) + : (!isdigit((uint8_t)(*fp->uf_name)) + && vim_regexec(regmatch, fp->uf_name, 0))) { list_func_head(fp, false, false); if (changed != func_hashtab.ht_changed) { emsg(_("E454: function list was modified")); diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index f0e1f5dca0..d0ad53c43d 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -28,10 +28,10 @@ struct funccal_entry; #define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0 #define FC_REMOVED 0x20 // function redefined while uf_refcount > 0 #define FC_SANDBOX 0x40 // function defined in the sandbox -#define FC_DEAD 0x80 // function kept only for reference to dfunc -#define FC_EXPORT 0x100 // "export def Func()" +// #define FC_DEAD 0x80 // function kept only for reference to dfunc +// #define FC_EXPORT 0x100 // "export def Func()" #define FC_NOARGS 0x200 // no a: variables in lambda -#define FC_VIM9 0x400 // defined in vim9 script file +// #define FC_VIM9 0x400 // defined in vim9 script file #define FC_LUAREF 0x800 // luaref callback /// Structure used by trans_function_name() -- cgit From d13222649a2145272f14675d9bbf64bb72c43f64 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 08:58:37 +0800 Subject: vim-patch:8.2.1945: crash when passing NULL function to reduce() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Crash when passing NULL function to reduce(). Solution: Check for NULL pointer and give an error. (Dominique Pellé, closes vim/vim#7243) https://github.com/vim/vim/commit/0d90e728fe089ff1bb34d6a17f5591a96b57f734 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 23d0242ce4..f94725e1cc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -150,6 +150,8 @@ static const char *e_invalwindow = N_("E957: Invalid window number"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); static const char e_using_number_as_bool_nr[] = N_("E1023: Using a Number as a Bool: %d"); +static const char e_missing_function_argument[] + = N_("E1132: Missing function argument"); /// Dummy va_list for passing to vim_snprintf /// @@ -6244,8 +6246,9 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else { func_name = tv_get_string(&argvars[1]); } - if (*func_name == NUL) { - return; // type error or empty name + if (func_name == NULL || *func_name == NUL) { + emsg(_(e_missing_function_argument)); + return; } funcexe_T funcexe = FUNCEXE_INIT; -- cgit From 08121ef69f47f8ad8f8903a732920412e24d30c1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 08:55:42 +0800 Subject: vim-patch:8.2.2848: crash whn calling partial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Crash whn calling partial. Solution: Check for NULL pointer. (Dominique Pellé, closes vim/vim#8202) https://github.com/vim/vim/commit/fe8ebdbe5c4e116311c0c0d5937b89ded5c92d01 Co-authored-by: Dominique Pelle --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f94725e1cc..99e511a7a4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -565,8 +565,8 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) func = (char *)tv_get_string(&argvars[0]); } - if (*func == NUL) { - return; // type error or empty name + if (func == NULL || *func == NUL) { + return; // type error, empty name or null function } dict_T *selfdict = NULL; @@ -1136,7 +1136,7 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// Set the cursor position. -/// If 'charcol' is true, then use the column number as a character offset. +/// 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) { -- cgit From 68ca16c376bd8786ffc0c7ce7619b9a0ce5657e8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 08:54:07 +0800 Subject: vim-patch:8.2.3783: confusing error for using a variable as a function Problem: Confusing error for using a variable as a function. Solution: If a function is not found but there is a variable, give a more useful error. (issue vim/vim#9310) https://github.com/vim/vim/commit/2ef9156b4284e4a52613c36e3d4667245273a28d Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 45 ++++++++++++++++++++++++++++++--------------- src/nvim/eval/userfunc.h | 3 +++ 2 files changed, 33 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9705bc93db..a348588106 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -65,6 +65,7 @@ static funccall_T *current_funccal = NULL; // item in it is still being used. static funccall_T *previous_funccal = NULL; +static const char *e_unknownfunc = N_("E117: Unknown function: %s"); static const char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); static const char *e_funcdict = N_("E717: Dictionary entry already exists"); static const char *e_funcref = N_("E718: Funcref required"); @@ -401,9 +402,11 @@ errret: /// is not needed. /// @param[in] no_autoload If true, do not source autoload scripts if function /// was not found. +/// @param[out] found_var If not NULL and a variable was found set it to true. /// /// @return name of the function. -char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload) +char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload, + bool *found_var) FUNC_ATTR_NONNULL_ARG(1, 2) { if (partialp != NULL) { @@ -411,18 +414,25 @@ char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, b } dictitem_T *const v = find_var(name, (size_t)(*lenp), NULL, no_autoload); - if (v != NULL && v->di_tv.v_type == VAR_FUNC) { - if (v->di_tv.vval.v_string == NULL) { // just in case + if (v == NULL) { + return (char *)name; + } + typval_T *const tv = &v->di_tv; + if (found_var != NULL) { + *found_var = true; + } + + if (tv->v_type == VAR_FUNC) { + if (tv->vval.v_string == NULL) { // just in case *lenp = 0; return ""; } - *lenp = (int)strlen(v->di_tv.vval.v_string); - return v->di_tv.vval.v_string; + *lenp = (int)strlen(tv->vval.v_string); + return tv->vval.v_string; } - if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) { - partial_T *const pt = v->di_tv.vval.v_partial; - + if (tv->v_type == VAR_PARTIAL) { + partial_T *const pt = tv->vval.v_partial; if (pt == NULL) { // just in case *lenp = 0; return ""; @@ -1454,12 +1464,16 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv /// 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 *name) +static void user_func_error(int error, const char *name, funcexe_T *funcexe) FUNC_ATTR_NONNULL_ALL { switch (error) { case FCERR_UNKNOWN: - emsg_funcname(N_("E117: Unknown function: %s"), name); + if (funcexe->fe_found_var) { + semsg(_(e_not_callable_type_str), name); + } else { + emsg_funcname(e_unknownfunc, name); + } break; case FCERR_NOTMETHOD: emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); @@ -1654,7 +1668,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 : funcname, funcexe); } // clear the copies made from the partial @@ -1846,14 +1860,13 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part // Check if the name is a Funcref. If so, use the value. if (lv.ll_exp_name != NULL) { len = (int)strlen(lv.ll_exp_name); - name = deref_func_name(lv.ll_exp_name, &len, partial, - flags & TFN_NO_AUTOLOAD); + name = deref_func_name(lv.ll_exp_name, &len, partial, flags & TFN_NO_AUTOLOAD, NULL); if (name == lv.ll_exp_name) { name = NULL; } } else if (!(flags & TFN_NO_DEREF)) { len = (int)(end - *pp); - name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); + name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD, NULL); if (name == *pp) { name = NULL; } @@ -3070,7 +3083,8 @@ void ex_call(exarg_T *eap) // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). len = (int)strlen(tofree); - name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); + bool found_var = false; + name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false, &found_var); // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. @@ -3104,6 +3118,7 @@ void ex_call(exarg_T *eap) funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; + funcexe.fe_found_var = found_var; if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL) { failed = true; break; diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index d0ad53c43d..4a98afb00e 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -75,6 +75,8 @@ typedef struct { partial_T *fe_partial; ///< for extra arguments dict_T *fe_selfdict; ///< Dictionary for "self" typval_T *fe_basetv; ///< base for base->method() + bool fe_found_var; ///< if the function is not found then give an + ///< error that a variable is not callable. } funcexe_T; #define FUNCEXE_INIT (funcexe_T) { \ @@ -86,6 +88,7 @@ typedef struct { .fe_partial = NULL, \ .fe_selfdict = NULL, \ .fe_basetv = NULL, \ + .fe_found_var = false, \ } #define FUNCARG(fp, j) ((char **)(fp->uf_args.ga_data))[j] -- cgit From b75634e55ee4cdfee7917b29f39e3ca1307cb059 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 07:50:18 +0800 Subject: vim-patch:9.0.0370: cleaning up afterwards can make a function messy Problem: Cleaning up afterwards can make a function messy. Solution: Add the :defer command. https://github.com/vim/vim/commit/1d84f7608f1e41dad03b8cc7925895437775f7c0 Omit EX_EXPR_ARG: Vim9 script only. Make :def throw E319 to avoid confusing behavior. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval_defs.h | 1 + src/nvim/eval/userfunc.c | 228 +++++++++++++++++++++++++++++++------------- 2 files changed, 164 insertions(+), 65 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 80432271b0..517e59f3c2 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -299,6 +299,7 @@ struct funccall_S { linenr_T breakpoint; ///< Next line with breakpoint or zero. int dbg_tick; ///< debug_tick when breakpoint was set. int level; ///< Top nesting level of executed function. + garray_T fc_defer; ///< Functions to be called on return. proftime_T prof_child; ///< Time spent in a child. funccall_T *caller; ///< Calling function or NULL; or next funccal in ///< list pointed to by previous_funccal. diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a348588106..9853622ee0 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -53,6 +53,13 @@ # include "eval/userfunc.c.generated.h" #endif +/// structure used as item in "fc_defer" +typedef struct { + char *dr_name; ///< function name, allocated + typval_T dr_argvars[MAX_FUNC_ARGS + 1]; + int dr_argcount; +} defer_T; + static hashtab_T func_hashtab; // Used by get_func_tv() @@ -469,45 +476,62 @@ void emsg_funcname(const char *errmsg, const char *name) } } -/// Allocate a variable for the result of a function. -/// -/// @param name name of the function -/// @param len length of "name" or -1 to use strlen() -/// @param arg argument, pointing to the '(' -/// @param funcexe various values -/// -/// @return OK or FAIL. -int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_T *const evalarg, - funcexe_T *funcexe) +/// Get function arguments at "*arg" and advance it. +/// Return them in "*argvars[MAX_FUNC_ARGS + 1]" and the count in "argcount". +static int get_func_arguments(char **arg, evalarg_T *const evalarg, int partial_argc, + typval_T *argvars, int *argcount) { - char *argp; + char *argp = *arg; int ret = OK; - typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments - int argcount = 0; // number of arguments found - const bool evaluate = evalarg == NULL ? false : (evalarg->eval_flags & EVAL_EVALUATE); // Get the arguments. - argp = *arg; - while (argcount < MAX_FUNC_ARGS - - (funcexe->fe_partial == NULL ? 0 : funcexe->fe_partial->pt_argc)) { + while (*argcount < MAX_FUNC_ARGS - partial_argc) { argp = skipwhite(argp + 1); // skip the '(' or ',' + if (*argp == ')' || *argp == ',' || *argp == NUL) { break; } - if (eval1(&argp, &argvars[argcount], evalarg) == FAIL) { + if (eval1(&argp, &argvars[*argcount], evalarg) == FAIL) { ret = FAIL; break; } - argcount++; + (*argcount)++; if (*argp != ',') { break; } } + + argp = skipwhite(argp); if (*argp == ')') { argp++; } else { ret = FAIL; } + *arg = argp; + return ret; +} + +/// Call a function and put the result in "rettv". +/// +/// @param name name of the function +/// @param len length of "name" or -1 to use strlen() +/// @param arg argument, pointing to the '(' +/// @param funcexe various values +/// +/// @return OK or FAIL. +int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_T *const evalarg, + funcexe_T *funcexe) +{ + typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments + int argcount = 0; // number of arguments found + const bool evaluate = evalarg == NULL ? false : (evalarg->eval_flags & EVAL_EVALUATE); + + char *argp = *arg; + int ret = get_func_arguments(&argp, evalarg, + (funcexe->fe_partial == NULL + ? 0 + : funcexe->fe_partial->pt_argc), + argvars, &argcount); if (ret == OK) { int i = 0; @@ -1148,6 +1172,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett DOCMD_NOWAIT|DOCMD_VERBOSE|DOCMD_REPEAT); } + // Invoke functions added with ":defer". + handle_defer(); + RedrawingDisabled--; // when the function was aborted because of an error, return -1 @@ -1544,7 +1571,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t int argv_base = 0; partial_T *partial = funcexe->fe_partial; - // Initialize rettv so that it is safe for caller to invoke clear_tv(rettv) + // Initialize rettv so that it is safe for caller to invoke tv_clear(rettv) // even when call_func() returns FAIL. rettv->v_type = VAR_UNKNOWN; @@ -3033,7 +3060,115 @@ void ex_return(exarg_T *eap) clear_evalarg(&evalarg, eap); } +static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg, + funcexe_T *funcexe_init, evalarg_T *const evalarg) +{ + bool doesrange; + bool failed = false; + + for (linenr_T lnum = eap->line1; lnum <= eap->line2; lnum++) { + if (eap->addr_count > 0) { // -V560 + if (lnum > curbuf->b_ml.ml_line_count) { + // If the function deleted lines or switched to another buffer + // the line number may become invalid. + emsg(_(e_invrange)); + break; + } + curwin->w_cursor.lnum = lnum; + curwin->w_cursor.col = 0; + curwin->w_cursor.coladd = 0; + } + *arg = startarg; + + funcexe_T funcexe = *funcexe_init; + funcexe.fe_doesrange = &doesrange; + typval_T rettv; + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this + if (get_func_tv(name, -1, &rettv, arg, evalarg, &funcexe) == FAIL) { + failed = true; + break; + } + + // Handle a function returning a Funcref, Dictionary or List. + if (handle_subscript((const char **)arg, &rettv, &EVALARG_EVALUATE, true) == FAIL) { + failed = true; + break; + } + + tv_clear(&rettv); + if (doesrange) { + break; + } + + // Stop when immediately aborting on error, or when an interrupt + // occurred or an exception was thrown but not caught. + // get_func_tv() returned OK, so that the check for trailing + // characters below is executed. + if (aborting()) { + break; + } + } + + return failed; +} + +/// Core part of ":defer func(arg)". "arg" points to the "(" and is advanced. +/// +/// @return FAIL or OK. +static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) +{ + typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments + int argcount = 0; // number of arguments found + int ret = FAIL; + + if (current_funccal == NULL) { + semsg(_(e_str_not_inside_function), "defer"); + return FAIL; + } + if (get_func_arguments(arg, evalarg, false, argvars, &argcount) == FAIL) { + goto theend; + } + char *saved_name = xstrdup(name); + + if (current_funccal->fc_defer.ga_itemsize == 0) { + ga_init(¤t_funccal->fc_defer, sizeof(defer_T), 10); + } + defer_T *dr = GA_APPEND_VIA_PTR(defer_T, ¤t_funccal->fc_defer); + dr->dr_name = saved_name; + dr->dr_argcount = argcount; + while (argcount > 0) { + argcount--; + dr->dr_argvars[argcount] = argvars[argcount]; + } + ret = OK; + +theend: + while (--argcount >= 0) { + tv_clear(&argvars[argcount]); + } + return ret; +} + +/// Invoked after a function has finished: invoke ":defer" functions. +static void handle_defer(void) +{ + for (int idx = current_funccal->fc_defer.ga_len - 1; idx >= 0; idx--) { + defer_T *dr = ((defer_T *)current_funccal->fc_defer.ga_data) + idx; + funcexe_T funcexe = { .fe_evaluate = true }; + typval_T rettv; + rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this + call_func(dr->dr_name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe); + tv_clear(&rettv); + xfree(dr->dr_name); + for (int i = dr->dr_argcount - 1; i >= 0; i--) { + tv_clear(&dr->dr_argvars[i]); + } + } + ga_clear(¤t_funccal->fc_defer); +} + /// ":1,25call func(arg1, arg2)" function call. +/// ":defer func(arg1, arg2)" deferred function call. void ex_call(exarg_T *eap) { char *arg = eap->arg; @@ -3041,9 +3176,6 @@ void ex_call(exarg_T *eap) char *name; char *tofree; int len; - typval_T rettv; - linenr_T lnum; - bool doesrange; bool failed = false; funcdict_T fudi; partial_T *partial = NULL; @@ -3051,6 +3183,7 @@ void ex_call(exarg_T *eap) fill_evalarg_from_eap(&evalarg, eap, eap->skip); if (eap->skip) { + typval_T rettv; // trans_function_name() doesn't work well when skipping, use eval0() // instead to skip to any following command, e.g. for: // :if 0 | call dict.foo().bar() | endif. @@ -3089,59 +3222,24 @@ void ex_call(exarg_T *eap) // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. startarg = skipwhite(arg); - rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { semsg(_(e_missingparen), eap->arg); goto end; } - lnum = eap->line1; - for (; lnum <= eap->line2; lnum++) { - if (eap->addr_count > 0) { // -V560 - if (lnum > curbuf->b_ml.ml_line_count) { - // If the function deleted lines or switched to another buffer - // the line number may become invalid. - emsg(_(e_invrange)); - break; - } - curwin->w_cursor.lnum = lnum; - curwin->w_cursor.col = 0; - curwin->w_cursor.coladd = 0; - } + if (eap->cmdidx == CMD_defer) { arg = startarg; - + failed = ex_defer_inner(name, &arg, &evalarg) == FAIL; + } else { funcexe_T funcexe = FUNCEXE_INIT; - funcexe.fe_firstline = eap->line1; - funcexe.fe_lastline = eap->line2; - funcexe.fe_doesrange = &doesrange; - funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; + funcexe.fe_firstline = eap->line1; + funcexe.fe_lastline = eap->line2; funcexe.fe_found_var = found_var; - if (get_func_tv(name, -1, &rettv, &arg, &evalarg, &funcexe) == FAIL) { - failed = true; - break; - } - - // Handle a function returning a Funcref, Dictionary or List. - if (handle_subscript((const char **)&arg, &rettv, &EVALARG_EVALUATE, true) == FAIL) { - failed = true; - break; - } - - tv_clear(&rettv); - if (doesrange) { - break; - } - - // Stop when immediately aborting on error, or when an interrupt - // occurred or an exception was thrown but not caught. - // get_func_tv() returned OK, so that the check for trailing - // characters below is executed. - if (aborting()) { - break; - } + funcexe.fe_evaluate = true; + failed = ex_call_inner(eap, name, &arg, startarg, &funcexe, &evalarg); } // When inside :try we need to check for following "| catch" or "| endtry". -- cgit From 0167649ce4071e60d985b65f3f9408ffb21cb58c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 11:07:48 +0800 Subject: vim-patch:9.0.0379: cleaning up after writefile() is a hassle Problem: Cleaning up after writefile() is a hassle. Solution: Add the 'D' flag to defer deleting the written file. Very useful in tests. https://github.com/vim/vim/commit/806a273f3c84ecd475913d901890bb1929be9a0a Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 21 +++++++++++++++++++-- src/nvim/eval/userfunc.c | 24 +++++++++++++++--------- 2 files changed, 34 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 99e511a7a4..66fd663e5e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9296,6 +9296,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool binary = false; bool append = false; + bool defer = false; bool do_fsync = !!p_fs; bool mkdir_p = false; if (argvars[2].v_type != VAR_UNKNOWN) { @@ -9309,6 +9310,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) binary = true; break; case 'a': append = true; break; + case 'D': + defer = true; break; case 's': do_fsync = true; break; case 'S': @@ -9328,6 +9331,12 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (fname == NULL) { return; } + + if (defer && get_current_funccal() == NULL) { + semsg(_(e_str_not_inside_function), "defer"); + return; + } + FileDescriptor fp; int error; if (*fname == NUL) { @@ -9336,9 +9345,17 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ((append ? kFileAppend : kFileTruncate) | (mkdir_p ? kFileMkDir : kFileCreate) | kFileCreate), 0666)) != 0) { - semsg(_("E482: Can't open file %s for writing: %s"), - fname, os_strerror(error)); + semsg(_("E482: Can't open file %s for writing: %s"), fname, os_strerror(error)); } else { + if (defer) { + typval_T tv = { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrdup(fname), + }; + add_defer("delete", 1, &tv); + } + bool write_ok; if (argvars[0].v_type == VAR_BLOB) { write_ok = write_blob(&fp, argvars[0].vval.v_blob); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9853622ee0..4b9bc1fdec 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -478,6 +478,7 @@ void emsg_funcname(const char *errmsg, const char *name) /// Get function arguments at "*arg" and advance it. /// Return them in "*argvars[MAX_FUNC_ARGS + 1]" and the count in "argcount". +/// On failure FAIL is returned but the "argvars[argcount]" are still set. static int get_func_arguments(char **arg, evalarg_T *const evalarg, int partial_argc, typval_T *argvars, int *argcount) { @@ -3119,16 +3120,28 @@ static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) { typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments int argcount = 0; // number of arguments found - int ret = FAIL; if (current_funccal == NULL) { semsg(_(e_str_not_inside_function), "defer"); return FAIL; } if (get_func_arguments(arg, evalarg, false, argvars, &argcount) == FAIL) { - goto theend; + while (--argcount >= 0) { + tv_clear(&argvars[argcount]); + } + return FAIL; } + add_defer(name, argcount, argvars); + return OK; +} + +/// Add a deferred call for "name" with arguments "argvars[argcount]". +/// Consumes "argvars[]". +/// Caller must check that current_funccal is not NULL. +void add_defer(char *name, int argcount_arg, typval_T *argvars) +{ char *saved_name = xstrdup(name); + int argcount = argcount_arg; if (current_funccal->fc_defer.ga_itemsize == 0) { ga_init(¤t_funccal->fc_defer, sizeof(defer_T), 10); @@ -3140,13 +3153,6 @@ static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) argcount--; dr->dr_argvars[argcount] = argvars[argcount]; } - ret = OK; - -theend: - while (--argcount >= 0) { - tv_clear(&argvars[argcount]); - } - return ret; } /// Invoked after a function has finished: invoke ":defer" functions. -- cgit From 335bef0c211dc962499814d248670ff17758a642 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 10:51:27 +0800 Subject: vim-patch:9.0.0390: cannot use a partial with :defer Problem: Cannot use a partial with :defer. Solution: Add the partial arguments before the other arguments. Disallow using a dictionary. https://github.com/vim/vim/commit/86d87256c4005c6215da5af2597fbf6f6304421f Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4b9bc1fdec..e9e780747a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -81,6 +81,8 @@ static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); static const char e_missing_heredoc_end_marker_str[] = N_("E1145: Missing heredoc end marker: %s"); +static const char e_cannot_use_partial_with_dictionary_for_defer[] + = N_("E1300: Cannot use a partial with dictionary for :defer"); void func_init(void) { @@ -3062,7 +3064,7 @@ void ex_return(exarg_T *eap) } static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg, - funcexe_T *funcexe_init, evalarg_T *const evalarg) + const funcexe_T *const funcexe_init, evalarg_T *const evalarg) { bool doesrange; bool failed = false; @@ -3116,16 +3118,32 @@ static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg, /// Core part of ":defer func(arg)". "arg" points to the "(" and is advanced. /// /// @return FAIL or OK. -static int ex_defer_inner(char *name, char **arg, evalarg_T *const evalarg) +static int ex_defer_inner(char *name, char **arg, const partial_T *const partial, + evalarg_T *const evalarg) { typval_T argvars[MAX_FUNC_ARGS + 1]; // vars for arguments + int partial_argc = 0; // number of partial arguments int argcount = 0; // number of arguments found if (current_funccal == NULL) { semsg(_(e_str_not_inside_function), "defer"); return FAIL; } - if (get_func_arguments(arg, evalarg, false, argvars, &argcount) == FAIL) { + if (partial != NULL) { + if (partial->pt_dict != NULL) { + emsg(_(e_cannot_use_partial_with_dictionary_for_defer)); + return FAIL; + } + if (partial->pt_argc > 0) { + partial_argc = partial->pt_argc; + for (int i = 0; i < partial_argc; i++) { + tv_copy(&partial->pt_argv[i], &argvars[i]); + } + } + } + int r = get_func_arguments(arg, evalarg, false, argvars + partial_argc, &argcount); + argcount += partial_argc; + if (r == FAIL) { while (--argcount >= 0) { tv_clear(&argvars[argcount]); } @@ -3236,7 +3254,7 @@ void ex_call(exarg_T *eap) if (eap->cmdidx == CMD_defer) { arg = startarg; - failed = ex_defer_inner(name, &arg, &evalarg) == FAIL; + failed = ex_defer_inner(name, &arg, partial, &evalarg) == FAIL; } else { funcexe_T funcexe = FUNCEXE_INIT; funcexe.fe_partial = partial; -- cgit From 7b05ddbb72717f995fedc81583d73f82c78c881d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 11:37:41 +0800 Subject: vim-patch:9.0.0397: :defer not tested with exceptions and ":qa!" Problem: :defer not tested with exceptions and ":qa!". Solution: Test :defer works when exceptions are thrown and when ":qa!" is used. Invoke the deferred calls on exit. https://github.com/vim/vim/commit/58779858fb5a82a3233af5d4237a3cece88c10d4 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e9e780747a..0a8e5c349a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1176,7 +1176,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett } // Invoke functions added with ":defer". - handle_defer(); + handle_defer_one(current_funccal); RedrawingDisabled--; @@ -3174,10 +3174,10 @@ void add_defer(char *name, int argcount_arg, typval_T *argvars) } /// Invoked after a function has finished: invoke ":defer" functions. -static void handle_defer(void) +static void handle_defer_one(funccall_T *funccal) { - for (int idx = current_funccal->fc_defer.ga_len - 1; idx >= 0; idx--) { - defer_T *dr = ((defer_T *)current_funccal->fc_defer.ga_data) + idx; + for (int idx = funccal->fc_defer.ga_len - 1; idx >= 0; idx--) { + defer_T *dr = ((defer_T *)funccal->fc_defer.ga_data) + idx; funcexe_T funcexe = { .fe_evaluate = true }; typval_T rettv; rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this @@ -3188,7 +3188,15 @@ static void handle_defer(void) tv_clear(&dr->dr_argvars[i]); } } - ga_clear(¤t_funccal->fc_defer); + ga_clear(&funccal->fc_defer); +} + +/// Called when exiting: call all defer functions. +void invoke_all_defer(void) +{ + for (funccall_T *funccal = current_funccal; funccal != NULL; funccal = funccal->caller) { + handle_defer_one(funccal); + } } /// ":1,25call func(arg1, arg2)" function call. -- cgit From f39b33ee491a4a8d4b08425e582dd0dd53617edf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 11:46:17 +0800 Subject: vim-patch:9.0.0411: only created files can be cleaned up with one call MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Only created files can be cleaned up with one call. Solution: Add flags to mkdir() to delete with a deferred function. Expand the writefile() name to a full path to handle changing directory. https://github.com/vim/vim/commit/6f14da15ac900589f2f413d77898b9bff3b31ece vim-patch:8.2.3742: dec mouse test fails without gnome terminfo entry Problem: Dec mouse test fails without gnome terminfo entry. Solution: Check if there is a gnome entry. Also fix 'acd' test on MS-Windows. (Dominique Pellé, closes vim/vim#9282) https://github.com/vim/vim/commit/f589fd3e1047cdf90566b68aaf9a13389e54d26a Cherry-pick test_autochdir.vim changes from patch 9.0.0313. Cherry-pick test_autocmd.vim changes from patch 9.0.0323. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 41 ++++++++++++++++++++++++++++++++++------- src/nvim/eval/userfunc.c | 11 +++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 66fd663e5e..f53b283c79 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4892,6 +4892,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) *path_tail_with_sep((char *)dir) = NUL; } + bool defer = false; + bool defer_recurse = false; + char *created = NULL; if (argvars[1].v_type != VAR_UNKNOWN) { if (argvars[2].v_type != VAR_UNKNOWN) { prot = (int)tv_get_number_chk(&argvars[2], NULL); @@ -4899,9 +4902,17 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } } - if (strcmp(tv_get_string(&argvars[1]), "p") == 0) { + const char *arg2 = tv_get_string(&argvars[1]); + defer = vim_strchr(arg2, 'D') != NULL; + defer_recurse = vim_strchr(arg2, 'R') != NULL; + if ((defer || defer_recurse) && !can_add_defer()) { + return; + } + + if (vim_strchr(arg2, 'p') != NULL) { char *failed_dir; - int ret = os_mkdir_recurse(dir, prot, &failed_dir); + int ret = os_mkdir_recurse(dir, prot, &failed_dir, + defer || defer_recurse ? &created : NULL); if (ret != 0) { semsg(_(e_mkdir), failed_dir, os_strerror(ret)); xfree(failed_dir); @@ -4909,10 +4920,27 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } rettv->vval.v_number = OK; - return; } } - rettv->vval.v_number = vim_mkdir_emsg(dir, prot); + if (rettv->vval.v_number == FAIL) { + rettv->vval.v_number = vim_mkdir_emsg(dir, prot); + } + + // Handle "D" and "R": deferred deletion of the created directory. + if (rettv->vval.v_number == OK + && created == NULL && (defer || defer_recurse)) { + created = FullName_save(dir, false); + } + if (created != NULL) { + typval_T tv[2]; + tv[0].v_type = VAR_STRING; + tv[0].v_lock = VAR_UNLOCKED; + tv[0].vval.v_string = created; + tv[1].v_type = VAR_STRING; + tv[1].v_lock = VAR_UNLOCKED; + tv[1].vval.v_string = xstrdup(defer_recurse ? "rf" : "d"); + add_defer("delete", 2, tv); + } } /// "mode()" function @@ -9332,8 +9360,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - if (defer && get_current_funccal() == NULL) { - semsg(_(e_str_not_inside_function), "defer"); + if (defer && !can_add_defer()) { return; } @@ -9351,7 +9378,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) typval_T tv = { .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrdup(fname), + .vval.v_string = FullName_save(fname, false), }; add_defer("delete", 1, &tv); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 0a8e5c349a..808fb316fe 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3153,6 +3153,17 @@ static int ex_defer_inner(char *name, char **arg, const partial_T *const partial return OK; } +/// Return true if currently inside a function call. +/// Give an error message and return FALSE when not. +bool can_add_defer(void) +{ + if (get_current_funccal() == NULL) { + semsg(_(e_str_not_inside_function), "defer"); + return false; + } + return true; +} + /// Add a deferred call for "name" with arguments "argvars[argcount]". /// Consumes "argvars[]". /// Caller must check that current_funccal is not NULL. -- cgit From b1a341a48a59bf489ffe492d69cfaeb94b87fd78 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 10:59:59 +0800 Subject: vim-patch:9.0.1446: unnecessary checks for the "skip" flag when skipping Problem: Unnecessary checks for the "skip" flag when skipping. Solution: Remove the unnecessary checks. (closes vim/vim#12254) https://github.com/vim/vim/commit/5299c0933f942c61bfd48064c91365e518fa868c --- src/nvim/eval/userfunc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 808fb316fe..f91962ac09 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3063,6 +3063,7 @@ void ex_return(exarg_T *eap) clear_evalarg(&evalarg, eap); } +/// Lower level implementation of "call". Only called when not skipping. static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg, const funcexe_T *const funcexe_init, evalarg_T *const evalarg) { @@ -3070,7 +3071,7 @@ static int ex_call_inner(exarg_T *eap, char *name, char **arg, char *startarg, bool failed = false; for (linenr_T lnum = eap->line1; lnum <= eap->line2; lnum++) { - if (eap->addr_count > 0) { // -V560 + if (eap->addr_count > 0) { if (lnum > curbuf->b_ml.ml_line_count) { // If the function deleted lines or switched to another buffer // the line number may become invalid. -- cgit From 42e55ba009ecc14afa1b519c8de02cb30c0d1671 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 16 Apr 2023 16:57:25 +0800 Subject: vim-patch:9.0.0398: members of funccall_T are inconsistently named (#23123) Problem: Members of funccall_T are inconsistently named. Solution: Use the "fc_" prefix for all members. https://github.com/vim/vim/commit/ca16c60f337ed33d5dd66a6e90aaf95b619c5e47 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval_defs.h | 43 ++++---- src/nvim/eval/userfunc.c | 256 ++++++++++++++++++++++---------------------- 2 files changed, 149 insertions(+), 150 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 517e59f3c2..3e49417f6f 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -284,28 +284,27 @@ enum { FIXVAR_CNT = 12, }; typedef struct funccall_S funccall_T; struct funccall_S { - ufunc_T *func; ///< Function being called. - int linenr; ///< Next line to be executed. - int returned; ///< ":return" used. - /// Fixed variables for arguments. - TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fixvar[FIXVAR_CNT]; - dict_T l_vars; ///< l: local function variables. - ScopeDictDictItem l_vars_var; ///< Variable for l: scope. - dict_T l_avars; ///< a: argument variables. - ScopeDictDictItem l_avars_var; ///< Variable for a: scope. - list_T l_varlist; ///< List for a:000. - listitem_T l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. - typval_T *rettv; ///< Return value. - linenr_T breakpoint; ///< Next line with breakpoint or zero. - int dbg_tick; ///< debug_tick when breakpoint was set. - int level; ///< Top nesting level of executed function. - garray_T fc_defer; ///< Functions to be called on return. - proftime_T prof_child; ///< Time spent in a child. - funccall_T *caller; ///< Calling function or NULL; or next funccal in - ///< list pointed to by previous_funccal. - int fc_refcount; ///< Number of user functions that reference this funccall. - int fc_copyID; ///< CopyID used for garbage collection. - garray_T fc_funcs; ///< List of ufunc_T* which keep a reference to "func". + ufunc_T *fc_func; ///< Function being called. + int fc_linenr; ///< Next line to be executed. + int fc_returned; ///< ":return" used. + TV_DICTITEM_STRUCT(VAR_SHORT_LEN + 1) fc_fixvar[FIXVAR_CNT]; ///< Fixed variables for arguments. + dict_T fc_l_vars; ///< l: local function variables. + ScopeDictDictItem fc_l_vars_var; ///< Variable for l: scope. + dict_T fc_l_avars; ///< a: argument variables. + ScopeDictDictItem fc_l_avars_var; ///< Variable for a: scope. + list_T fc_l_varlist; ///< List for a:000. + listitem_T fc_l_listitems[MAX_FUNC_ARGS]; ///< List items for a:000. + typval_T *fc_rettv; ///< Return value. + linenr_T fc_breakpoint; ///< Next line with breakpoint or zero. + int fc_dbg_tick; ///< "debug_tick" when breakpoint was set. + int fc_level; ///< Top nesting level of executed function. + garray_T fc_defer; ///< Functions to be called on return. + proftime_T fc_prof_child; ///< Time spent in a child. + funccall_T *fc_caller; ///< Calling function or NULL; or next funccal in + ///< list pointed to by previous_funccal. + int fc_refcount; ///< Number of user functions that reference this funccall. + int fc_copyID; ///< CopyID used for garbage collection. + garray_T fc_ufuncs; ///< List of ufunc_T* which keep a reference to "fc_func". }; /// Structure to hold info for a user function. diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f91962ac09..734a6655bb 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -235,9 +235,9 @@ static void register_closure(ufunc_T *fp) funccal_unref(fp->uf_scoped, fp, false); fp->uf_scoped = current_funccal; current_funccal->fc_refcount++; - ga_grow(¤t_funccal->fc_funcs, 1); - ((ufunc_T **)current_funccal->fc_funcs.ga_data) - [current_funccal->fc_funcs.ga_len++] = fp; + ga_grow(¤t_funccal->fc_ufuncs, 1); + ((ufunc_T **)current_funccal->fc_ufuncs.ga_data) + [current_funccal->fc_ufuncs.ga_len++] = fp; } /// @return a name for a lambda. Returned in static memory. @@ -678,8 +678,8 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) /// Free "fc" static void free_funccal(funccall_T *fc) { - for (int i = 0; i < fc->fc_funcs.ga_len; i++) { - ufunc_T *fp = ((ufunc_T **)(fc->fc_funcs.ga_data))[i]; + for (int i = 0; i < fc->fc_ufuncs.ga_len; i++) { + ufunc_T *fp = ((ufunc_T **)(fc->fc_ufuncs.ga_data))[i]; // When garbage collecting a funccall_T may be freed before the // function that references it, clear its uf_scoped field. @@ -689,9 +689,9 @@ static void free_funccal(funccall_T *fc) fp->uf_scoped = NULL; } } - ga_clear(&fc->fc_funcs); + ga_clear(&fc->fc_ufuncs); - func_ptr_unref(fc->func); + func_ptr_unref(fc->fc_func); xfree(fc); } @@ -701,13 +701,13 @@ static void free_funccal(funccall_T *fc) static void free_funccal_contents(funccall_T *fc) { // Free all l: variables. - vars_clear(&fc->l_vars.dv_hashtab); + vars_clear(&fc->fc_l_vars.dv_hashtab); // Free all a: variables. - vars_clear(&fc->l_avars.dv_hashtab); + vars_clear(&fc->fc_l_avars.dv_hashtab); // Free the a:000 variables. - TV_LIST_ITER(&fc->l_varlist, li, { + TV_LIST_ITER(&fc->fc_l_varlist, li, { tv_clear(TV_LIST_ITEM_TV(li)); }); @@ -721,11 +721,11 @@ static void cleanup_function_call(funccall_T *fc) bool may_free_fc = fc->fc_refcount <= 0; bool free_fc = true; - current_funccal = fc->caller; + current_funccal = fc->fc_caller; // Free all l: variables if not referred. - if (may_free_fc && fc->l_vars.dv_refcount == DO_NOT_FREE_CNT) { - vars_clear(&fc->l_vars.dv_hashtab); + if (may_free_fc && fc->fc_l_vars.dv_refcount == DO_NOT_FREE_CNT) { + vars_clear(&fc->fc_l_vars.dv_hashtab); } else { free_fc = false; } @@ -733,25 +733,25 @@ static void cleanup_function_call(funccall_T *fc) // If the a:000 list and the l: and a: dicts are not referenced and // there is no closure using it, we can free the funccall_T and what's // in it. - if (may_free_fc && fc->l_avars.dv_refcount == DO_NOT_FREE_CNT) { - vars_clear_ext(&fc->l_avars.dv_hashtab, false); + if (may_free_fc && fc->fc_l_avars.dv_refcount == DO_NOT_FREE_CNT) { + vars_clear_ext(&fc->fc_l_avars.dv_hashtab, false); } else { free_fc = false; // Make a copy of the a: variables, since we didn't do that above. - TV_DICT_ITER(&fc->l_avars, di, { + TV_DICT_ITER(&fc->fc_l_avars, di, { tv_copy(&di->di_tv, &di->di_tv); }); } - if (may_free_fc && fc->l_varlist.lv_refcount // NOLINT(runtime/deprecated) + if (may_free_fc && fc->fc_l_varlist.lv_refcount // NOLINT(runtime/deprecated) == DO_NOT_FREE_CNT) { - fc->l_varlist.lv_first = NULL; // NOLINT(runtime/deprecated) + fc->fc_l_varlist.lv_first = NULL; // NOLINT(runtime/deprecated) } else { free_fc = false; // Make a copy of the a:000 items, since we didn't do that above. - TV_LIST_ITER(&fc->l_varlist, li, { + TV_LIST_ITER(&fc->fc_l_varlist, li, { tv_copy(TV_LIST_ITEM_TV(li), TV_LIST_ITEM_TV(li)); }); } @@ -764,7 +764,7 @@ static void cleanup_function_call(funccall_T *fc) // "fc" is still in use. This can happen when returning "a:000", // assigning "l:" to a global variable or defining a closure. // Link "fc" in the list for garbage collection later. - fc->caller = previous_funccal; + fc->fc_caller = previous_funccal; previous_funccal = fc; if (want_garbage_collect) { @@ -795,17 +795,17 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) fc->fc_refcount--; if (force ? fc->fc_refcount <= 0 : !fc_referenced(fc)) { - for (funccall_T **pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->caller) { + for (funccall_T **pfc = &previous_funccal; *pfc != NULL; pfc = &(*pfc)->fc_caller) { if (fc == *pfc) { - *pfc = fc->caller; + *pfc = fc->fc_caller; free_funccal_contents(fc); return; } } } - for (i = 0; i < fc->fc_funcs.ga_len; i++) { - if (((ufunc_T **)(fc->fc_funcs.ga_data))[i] == fp) { - ((ufunc_T **)(fc->fc_funcs.ga_data))[i] = NULL; + for (i = 0; i < fc->fc_ufuncs.ga_len; i++) { + if (((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] == fp) { + ((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] = NULL; } } } @@ -899,7 +899,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett int save_did_emsg; static int depth = 0; dictitem_T *v; - int fixvar_idx = 0; // index in fixvar[] + int fixvar_idx = 0; // index in fc_fixvar[] int ai; bool islambda = false; char numbuf[NUMBUFLEN]; @@ -931,39 +931,39 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett line_breakcheck(); // prepare the funccall_T structure fc = xcalloc(1, sizeof(funccall_T)); - fc->caller = current_funccal; + fc->fc_caller = current_funccal; current_funccal = fc; - fc->func = fp; - fc->rettv = rettv; - fc->level = ex_nesting_level; + fc->fc_func = fp; + fc->fc_rettv = rettv; + fc->fc_level = ex_nesting_level; // Check if this function has a breakpoint. - fc->breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); - fc->dbg_tick = debug_tick; + fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); + fc->fc_dbg_tick = debug_tick; // Set up fields for closure. - ga_init(&fc->fc_funcs, sizeof(ufunc_T *), 1); + ga_init(&fc->fc_ufuncs, sizeof(ufunc_T *), 1); func_ptr_ref(fp); if (strncmp(fp->uf_name, "", 8) == 0) { islambda = true; } - // Note about using fc->fixvar[]: This is an array of FIXVAR_CNT variables + // Note about using fc->fc_fixvar[]: This is an array of FIXVAR_CNT variables // with names up to VAR_SHORT_LEN long. This avoids having to alloc/free // each argument variable and saves a lot of time. // // Init l: variables. - init_var_dict(&fc->l_vars, &fc->l_vars_var, VAR_DEF_SCOPE); + init_var_dict(&fc->fc_l_vars, &fc->fc_l_vars_var, VAR_DEF_SCOPE); if (selfdict != NULL) { // Set l:self to "selfdict". Use "name" to avoid a warning from // some compiler that checks the destination size. - v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; + v = (dictitem_T *)&fc->fc_fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = (char *)v->di_key; STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_vars.dv_hashtab, v->di_key); + hash_add(&fc->fc_l_vars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = VAR_UNLOCKED; v->di_tv.vval.v_dict = selfdict; @@ -973,38 +973,38 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Init a: variables, unless none found (in lambda). // Set a:0 to "argcount" less number of named arguments, if >= 0. // Set a:000 to a list with room for the "..." arguments. - init_var_dict(&fc->l_avars, &fc->l_avars_var, VAR_SCOPE); + init_var_dict(&fc->fc_l_avars, &fc->fc_l_avars_var, VAR_SCOPE); if ((fp->uf_flags & FC_NOARGS) == 0) { - add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], "0", + add_nr_var(&fc->fc_l_avars, (dictitem_T *)&fc->fc_fixvar[fixvar_idx++], "0", (varnumber_T)(argcount >= fp->uf_args.ga_len ? argcount - fp->uf_args.ga_len : 0)); } - fc->l_avars.dv_lock = VAR_FIXED; + fc->fc_l_avars.dv_lock = VAR_FIXED; if ((fp->uf_flags & FC_NOARGS) == 0) { // Use "name" to avoid a warning from some compiler that checks the // destination size. - v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; + v = (dictitem_T *)&fc->fc_fixvar[fixvar_idx++]; #ifndef __clang_analyzer__ name = (char *)v->di_key; STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_avars.dv_hashtab, v->di_key); + hash_add(&fc->fc_l_avars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; - v->di_tv.vval.v_list = &fc->l_varlist; + v->di_tv.vval.v_list = &fc->fc_l_varlist; } - tv_list_init_static(&fc->l_varlist); - tv_list_set_lock(&fc->l_varlist, VAR_FIXED); + tv_list_init_static(&fc->fc_l_varlist); + tv_list_set_lock(&fc->fc_l_varlist, VAR_FIXED); // Set a:firstline to "firstline" and a:lastline to "lastline". // Set a:name to named arguments. // Set a:N to the "..." arguments. // Skipped when no a: variables used (in lambda). if ((fp->uf_flags & FC_NOARGS) == 0) { - add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + add_nr_var(&fc->fc_l_avars, (dictitem_T *)&fc->fc_fixvar[fixvar_idx++], "firstline", (varnumber_T)firstline); - add_nr_var(&fc->l_avars, (dictitem_T *)&fc->fixvar[fixvar_idx++], + add_nr_var(&fc->fc_l_avars, (dictitem_T *)&fc->fc_fixvar[fixvar_idx++], "lastline", (varnumber_T)lastline); } bool default_arg_err = false; @@ -1045,7 +1045,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett name = numbuf; } if (fixvar_idx < FIXVAR_CNT && strlen(name) <= VAR_SHORT_LEN) { - v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; + v = (dictitem_T *)&fc->fc_fixvar[fixvar_idx++]; v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; } else { v = xmalloc(sizeof(dictitem_T) + strlen(name)); @@ -1067,17 +1067,17 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Named arguments can be accessed without the "a:" prefix in lambda // expressions. Add to the l: dict. tv_copy(&v->di_tv, &v->di_tv); - hash_add(&fc->l_vars.dv_hashtab, v->di_key); + hash_add(&fc->fc_l_vars.dv_hashtab, v->di_key); } else { - hash_add(&fc->l_avars.dv_hashtab, v->di_key); + hash_add(&fc->fc_l_avars.dv_hashtab, v->di_key); } if (ai >= 0 && ai < MAX_FUNC_ARGS) { - listitem_T *li = &fc->l_listitems[ai]; + listitem_T *li = &fc->fc_l_listitems[ai]; *TV_LIST_ITEM_TV(li) = argvars[i]; TV_LIST_ITEM_TV(li)->v_lock = VAR_FIXED; - tv_list_append(&fc->l_varlist, li); + tv_list_append(&fc->fc_l_varlist, li); } } @@ -1142,7 +1142,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett bool func_or_func_caller_profiling = do_profiling_yes && (fp->uf_profiling - || (fc->caller != NULL && fc->caller->func->uf_profiling)); + || (fc->fc_caller != NULL && fc->fc_caller->fc_func->uf_profiling)); if (func_or_func_caller_profiling) { fp->uf_tm_count++; @@ -1194,11 +1194,11 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start); fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start, fp->uf_tm_children); - if (fc->caller != NULL && fc->caller->func->uf_profiling) { - fc->caller->func->uf_tm_children = - profile_add(fc->caller->func->uf_tm_children, call_start); - fc->caller->func->uf_tml_children = - profile_add(fc->caller->func->uf_tml_children, call_start); + if (fc->fc_caller != NULL && fc->fc_caller->fc_func->uf_profiling) { + fc->fc_caller->fc_func->uf_tm_children = + profile_add(fc->fc_caller->fc_func->uf_tm_children, call_start); + fc->fc_caller->fc_func->uf_tml_children = + profile_add(fc->fc_caller->fc_func->uf_tml_children, call_start); } if (started_profiling) { // make a ":profdel func" stop profiling the function @@ -1213,9 +1213,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett if (aborting()) { smsg(_("%s aborted"), SOURCING_NAME); - } else if (fc->rettv->v_type == VAR_NUMBER) { + } else if (fc->fc_rettv->v_type == VAR_NUMBER) { smsg(_("%s returning #%" PRId64 ""), - SOURCING_NAME, (int64_t)fc->rettv->vval.v_number); + SOURCING_NAME, (int64_t)fc->fc_rettv->vval.v_number); } else { char buf[MSG_BUF_LEN]; @@ -1223,7 +1223,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // 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 *s = encode_tv2string(fc->rettv, NULL); + char *s = encode_tv2string(fc->fc_rettv, NULL); char *tofree = s; emsg_off--; if (s != NULL) { @@ -1361,7 +1361,7 @@ void free_all_functions(void) // Clean up the current_funccal chain and the funccal stack. while (current_funccal != NULL) { - tv_clear(current_funccal->rettv); + tv_clear(current_funccal->fc_rettv); cleanup_function_call(current_funccal); // -V595 if (current_funccal == NULL && funccal_stack != NULL) { restore_funccal(); @@ -2994,10 +2994,10 @@ static inline bool fc_referenced(const funccall_T *const fc) FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL { - return ((fc->l_varlist.lv_refcount // NOLINT(runtime/deprecated) + return ((fc->fc_l_varlist.lv_refcount // NOLINT(runtime/deprecated) != DO_NOT_FREE_CNT) - || fc->l_vars.dv_refcount != DO_NOT_FREE_CNT - || fc->l_avars.dv_refcount != DO_NOT_FREE_CNT + || fc->fc_l_vars.dv_refcount != DO_NOT_FREE_CNT + || fc->fc_l_avars.dv_refcount != DO_NOT_FREE_CNT || fc->fc_refcount > 0); } @@ -3005,9 +3005,9 @@ static inline bool fc_referenced(const funccall_T *const fc) /// referenced from anywhere that is in use. static int can_free_funccal(funccall_T *fc, int copyID) { - return fc->l_varlist.lv_copyID != copyID - && fc->l_vars.dv_copyID != copyID - && fc->l_avars.dv_copyID != copyID + return fc->fc_l_varlist.lv_copyID != copyID + && fc->fc_l_vars.dv_copyID != copyID + && fc->fc_l_avars.dv_copyID != copyID && fc->fc_copyID != copyID; } @@ -3206,7 +3206,7 @@ static void handle_defer_one(funccall_T *funccal) /// Called when exiting: call all defer functions. void invoke_all_defer(void) { - for (funccall_T *funccal = current_funccal; funccal != NULL; funccal = funccal->caller) { + for (funccall_T *funccal = current_funccal; funccal != NULL; funccal = funccal->fc_caller) { handle_defer_one(funccal); } } @@ -3323,7 +3323,7 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) if (reanimate) { // Undo the return. - current_funccal->returned = false; + current_funccal->fc_returned = false; } // Cleanup (and deactivate) conditionals, but stop when a try conditional @@ -3343,8 +3343,8 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) // When undoing a return in order to make it pending, get the stored // return rettv. if (reanimate) { - assert(current_funccal->rettv); - rettv = current_funccal->rettv; + assert(current_funccal->fc_rettv); + rettv = current_funccal->fc_rettv; } if (rettv != NULL) { @@ -3359,20 +3359,20 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) // The pending return value could be overwritten by a ":return" // without argument in a finally clause; reset the default // return value. - current_funccal->rettv->v_type = VAR_NUMBER; - current_funccal->rettv->vval.v_number = 0; + current_funccal->fc_rettv->v_type = VAR_NUMBER; + current_funccal->fc_rettv->vval.v_number = 0; } } report_make_pending(CSTP_RETURN, rettv); } else { - current_funccal->returned = true; + current_funccal->fc_returned = true; // If the return is carried out now, store the return value. For // a return immediately after reanimation, the value is already // there. if (!reanimate && rettv != NULL) { - tv_clear(current_funccal->rettv); - *current_funccal->rettv = *(typval_T *)rettv; + tv_clear(current_funccal->fc_rettv); + *current_funccal->fc_rettv = *(typval_T *)rettv; if (!is_cmd) { xfree(rettv); } @@ -3412,14 +3412,14 @@ char *get_return_cmd(void *rettv) char *get_func_line(int c, void *cookie, int indent, bool do_concat) { funccall_T *fcp = (funccall_T *)cookie; - ufunc_T *fp = fcp->func; + ufunc_T *fp = fcp->fc_func; char *retval; garray_T *gap; // growarray with function lines // If breakpoints have been added/deleted need to check for it. - if (fcp->dbg_tick != debug_tick) { - fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); - fcp->dbg_tick = debug_tick; + if (fcp->fc_dbg_tick != debug_tick) { + fcp->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); + fcp->fc_dbg_tick = debug_tick; } if (do_profiling == PROF_YES) { func_line_end(cookie); @@ -3427,19 +3427,19 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) gap = &fp->uf_lines; if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) - || fcp->returned) { + || fcp->fc_returned) { retval = NULL; } else { // Skip NULL lines (continuation lines). - while (fcp->linenr < gap->ga_len - && ((char **)(gap->ga_data))[fcp->linenr] == NULL) { - fcp->linenr++; + while (fcp->fc_linenr < gap->ga_len + && ((char **)(gap->ga_data))[fcp->fc_linenr] == NULL) { + fcp->fc_linenr++; } - if (fcp->linenr >= gap->ga_len) { + if (fcp->fc_linenr >= gap->ga_len) { retval = NULL; } else { - retval = xstrdup(((char **)(gap->ga_data))[fcp->linenr++]); - SOURCING_LNUM = fcp->linenr; + retval = xstrdup(((char **)(gap->ga_data))[fcp->fc_linenr++]); + SOURCING_LNUM = fcp->fc_linenr; if (do_profiling == PROF_YES) { func_line_start(cookie); } @@ -3447,11 +3447,11 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) } // Did we encounter a breakpoint? - if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) { + if (fcp->fc_breakpoint != 0 && fcp->fc_breakpoint <= SOURCING_LNUM) { dbg_breakpoint(fp->uf_name, SOURCING_LNUM); // Find next breakpoint. - fcp->breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); - fcp->dbg_tick = debug_tick; + fcp->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, SOURCING_LNUM); + fcp->fc_dbg_tick = debug_tick; } return retval; @@ -3465,14 +3465,14 @@ int func_has_ended(void *cookie) // Ignore the "abort" flag if the abortion behavior has been changed due to // an error inside a try conditional. - return ((fcp->func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) - || fcp->returned; + return ((fcp->fc_func->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) + || fcp->fc_returned; } /// @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; + return ((funccall_T *)cookie)->fc_func->uf_flags & FC_ABORT; } /// Turn "dict.Func" into a partial for "Func" bound to "dict". @@ -3537,31 +3537,31 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) /// @return the name of the executed function. char *func_name(void *cookie) { - return ((funccall_T *)cookie)->func->uf_name; + return ((funccall_T *)cookie)->fc_func->uf_name; } /// @return the address holding the next breakpoint line for a funccall cookie. linenr_T *func_breakpoint(void *cookie) { - return &((funccall_T *)cookie)->breakpoint; + return &((funccall_T *)cookie)->fc_breakpoint; } /// @return the address holding the debug tick for a funccall cookie. int *func_dbg_tick(void *cookie) { - return &((funccall_T *)cookie)->dbg_tick; + return &((funccall_T *)cookie)->fc_dbg_tick; } /// @return the nesting level for a funccall cookie. int func_level(void *cookie) { - return ((funccall_T *)cookie)->level; + return ((funccall_T *)cookie)->fc_level; } /// @return true when a function was ended by a ":return" command. int current_func_returned(void) { - return current_funccal->returned; + return current_funccal->fc_returned; } bool free_unref_funccal(int copyID, int testing) @@ -3572,12 +3572,12 @@ bool free_unref_funccal(int copyID, int testing) for (funccall_T **pfc = &previous_funccal; *pfc != NULL;) { if (can_free_funccal(*pfc, copyID)) { funccall_T *fc = *pfc; - *pfc = fc->caller; + *pfc = fc->fc_caller; free_funccal_contents(fc); did_free = true; did_free_funccal = true; } else { - pfc = &(*pfc)->caller; + pfc = &(*pfc)->fc_caller; } } if (did_free_funccal) { @@ -3594,7 +3594,7 @@ funccall_T *get_funccal(void) funccall_T *funccal = current_funccal; if (debug_backtrace_level > 0) { for (int i = 0; i < debug_backtrace_level; i++) { - funccall_T *temp_funccal = funccal->caller; + funccall_T *temp_funccal = funccal->fc_caller; if (temp_funccal) { funccal = temp_funccal; } else { @@ -3614,7 +3614,7 @@ hashtab_T *get_funccal_local_ht(void) if (current_funccal == NULL) { return NULL; } - return &get_funccal()->l_vars.dv_hashtab; + return &get_funccal()->fc_l_vars.dv_hashtab; } /// @return the l: scope variable or @@ -3624,7 +3624,7 @@ dictitem_T *get_funccal_local_var(void) if (current_funccal == NULL) { return NULL; } - return (dictitem_T *)&get_funccal()->l_vars_var; + return (dictitem_T *)&get_funccal()->fc_l_vars_var; } /// @return the hashtable used for argument in the current funccal or @@ -3634,7 +3634,7 @@ hashtab_T *get_funccal_args_ht(void) if (current_funccal == NULL) { return NULL; } - return &get_funccal()->l_avars.dv_hashtab; + return &get_funccal()->fc_l_avars.dv_hashtab; } /// @return the a: scope variable or @@ -3644,14 +3644,14 @@ dictitem_T *get_funccal_args_var(void) if (current_funccal == NULL) { return NULL; } - return (dictitem_T *)¤t_funccal->l_avars_var; + return (dictitem_T *)¤t_funccal->fc_l_avars_var; } /// List function variables, if there is a function. void list_func_vars(int *first) { if (current_funccal != NULL) { - list_hashtable_vars(¤t_funccal->l_vars.dv_hashtab, "l:", false, + list_hashtable_vars(¤t_funccal->fc_l_vars.dv_hashtab, "l:", false, first); } } @@ -3660,8 +3660,8 @@ void list_func_vars(int *first) /// 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) { - return ¤t_funccal->l_vars; + if (current_funccal != NULL && ht == ¤t_funccal->fc_l_vars.dv_hashtab) { + return ¤t_funccal->fc_l_vars; } return NULL; } @@ -3669,7 +3669,7 @@ dict_T *get_current_funccal_dict(hashtab_T *ht) /// Search hashitem in parent scope. hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) { - if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + if (current_funccal == NULL || current_funccal->fc_func->uf_scoped == NULL) { return NULL; } @@ -3679,7 +3679,7 @@ hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) const char *varname; // Search in parent scope which is possible to reference from lambda - current_funccal = current_funccal->func->uf_scoped; + current_funccal = current_funccal->fc_func->uf_scoped; while (current_funccal != NULL) { hashtab_T *ht = find_var_ht(name, namelen, &varname); if (ht != NULL && *varname != NUL) { @@ -3689,10 +3689,10 @@ hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) break; } } - if (current_funccal == current_funccal->func->uf_scoped) { + if (current_funccal == current_funccal->fc_func->uf_scoped) { break; } - current_funccal = current_funccal->func->uf_scoped; + current_funccal = current_funccal->fc_func->uf_scoped; } current_funccal = old_current_funccal; @@ -3702,7 +3702,7 @@ hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht) /// Search variable in parent scope. dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no_autoload) { - if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) { + if (current_funccal == NULL || current_funccal->fc_func->uf_scoped == NULL) { return NULL; } @@ -3711,7 +3711,7 @@ dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no const char *varname; // Search in parent scope which is possible to reference from lambda - current_funccal = current_funccal->func->uf_scoped; + current_funccal = current_funccal->fc_func->uf_scoped; while (current_funccal) { hashtab_T *ht = find_var_ht(name, namelen, &varname); if (ht != NULL && *varname != NUL) { @@ -3721,10 +3721,10 @@ dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no break; } } - if (current_funccal == current_funccal->func->uf_scoped) { + if (current_funccal == current_funccal->fc_func->uf_scoped) { break; } - current_funccal = current_funccal->func->uf_scoped; + current_funccal = current_funccal->fc_func->uf_scoped; } current_funccal = old_current_funccal; @@ -3735,11 +3735,11 @@ dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen, int no bool set_ref_in_previous_funccal(int copyID) { for (funccall_T *fc = previous_funccal; fc != NULL; - fc = fc->caller) { + fc = fc->fc_caller) { fc->fc_copyID = copyID + 1; - if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID + 1, NULL) - || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID + 1, NULL) - || set_ref_in_list(&fc->l_varlist, copyID + 1, NULL)) { + if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID + 1, NULL) + || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID + 1, NULL) + || set_ref_in_list(&fc->fc_l_varlist, copyID + 1, NULL)) { return true; } } @@ -3750,10 +3750,10 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID) { if (fc->fc_copyID != copyID) { fc->fc_copyID = copyID; - if (set_ref_in_ht(&fc->l_vars.dv_hashtab, copyID, NULL) - || set_ref_in_ht(&fc->l_avars.dv_hashtab, copyID, NULL) - || set_ref_in_list(&fc->l_varlist, copyID, NULL) - || set_ref_in_func(NULL, fc->func, copyID)) { + if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID, NULL) + || set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID, NULL) + || set_ref_in_list(&fc->fc_l_varlist, copyID, NULL) + || set_ref_in_func(NULL, fc->fc_func, copyID)) { return true; } } @@ -3764,7 +3764,7 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID) bool set_ref_in_call_stack(int copyID) { for (funccall_T *fc = current_funccal; fc != NULL; - fc = fc->caller) { + fc = fc->fc_caller) { if (set_ref_in_funccal(fc, copyID)) { return true; } @@ -3774,7 +3774,7 @@ bool set_ref_in_call_stack(int copyID) for (funccal_entry_T *entry = funccal_stack; entry != NULL; entry = entry->next) { for (funccall_T *fc = entry->top_funccal; fc != NULL; - fc = fc->caller) { + fc = fc->fc_caller) { if (set_ref_in_funccal(fc, copyID)) { return true; } @@ -3839,7 +3839,7 @@ bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) fp = find_func(fname); } if (fp != NULL) { - for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) { + for (fc = fp->uf_scoped; fc != NULL; fc = fc->fc_func->uf_scoped) { abort = abort || set_ref_in_funccal(fc, copyID); } } -- cgit From 78535664bd29e6f2bd4b64c20cb29ef40f9bccd4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 17 Apr 2023 09:07:30 +0800 Subject: vim-patch:8.2.2172: Vim9: number of arguments is not always checked (#23142) Problem: Vim9: number of arguments is not always checked. (Yegappan Lakshmanan) Solution: Check number of arguments when calling function by name. https://github.com/vim/vim/commit/5082471f91dd42ed8c35e0f649d0a6572e6fe3fc Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 734a6655bb..6016ad0646 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1290,6 +1290,21 @@ static bool func_name_refcount(const char *name) return isdigit((uint8_t)(*name)) || *name == '<'; } +/// Check the argument count for user function "fp". +/// @return FCERR_UNKNOWN if OK, FCERR_TOOFEW or FCERR_TOOMANY otherwise. +static int check_user_func_argcount(ufunc_T *fp, int argcount) + FUNC_ATTR_NONNULL_ALL +{ + const int regular_args = fp->uf_args.ga_len; + + if (argcount < regular_args - fp->uf_def_args.ga_len) { + return FCERR_TOOFEW; + } else if (!fp->uf_varargs && argcount > regular_args) { + return FCERR_TOOMANY; + } + return FCERR_UNKNOWN; +} + /// Call a user function after checking the arguments. static int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict) @@ -1302,12 +1317,11 @@ static int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, ty if ((fp->uf_flags & FC_RANGE) && funcexe->fe_doesrange != NULL) { *funcexe->fe_doesrange = true; } - int error; - if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) { - error = FCERR_TOOFEW; - } else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len) { - error = FCERR_TOOMANY; - } else if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { + int error = check_user_func_argcount(fp, argcount); + if (error != FCERR_UNKNOWN) { + return error; + } + if ((fp->uf_flags & FC_DICT) && selfdict == NULL) { error = FCERR_DICT; } else { // Call the user function. -- cgit From 6bfba3660c5fbb22104cd87bd66a1381007fca22 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 17 Apr 2023 08:56:23 +0800 Subject: vim-patch:9.0.0406: deferred functions not invoked when partial func exits Problem: Deferred functions not invoked when partial func exits. Solution: Create a funccall_T when calling a :def function. https://github.com/vim/vim/commit/9667b2c888351b04751bdb43cba0d4ffc8c13ab1 The remove_funccal() function is currently unused, but it will be used in patch 9.0.0618. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 6016ad0646..32f9f9182c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -881,6 +881,27 @@ static void func_clear_free(ufunc_T *fp, bool force) func_free(fp); } +/// Allocate a funccall_T, link it in current_funccal and fill in "fp" and "rettv". +/// Must be followed by one call to remove_funccal() or cleanup_function_call(). +funccall_T *create_funccal(ufunc_T *fp, typval_T *rettv) +{ + funccall_T *fc = xcalloc(1, sizeof(funccall_T)); + fc->fc_caller = current_funccal; + current_funccal = fc; + fc->fc_func = fp; + func_ptr_ref(fp); + fc->fc_rettv = rettv; + return fc; +} + +/// Restore current_funccal. +void remove_funccal(void) +{ + funccall_T *fc = current_funccal; + current_funccal = fc->fc_caller; + free_funccal(fc); +} + /// Call a user function /// /// @param fp Function to call. @@ -895,7 +916,6 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett FUNC_ATTR_NONNULL_ARG(1, 3, 4) { bool using_sandbox = false; - funccall_T *fc; int save_did_emsg; static int depth = 0; dictitem_T *v; @@ -930,19 +950,13 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // check for CTRL-C hit line_breakcheck(); // prepare the funccall_T structure - fc = xcalloc(1, sizeof(funccall_T)); - fc->fc_caller = current_funccal; - current_funccal = fc; - fc->fc_func = fp; - fc->fc_rettv = rettv; + funccall_T *fc = create_funccal(fp, rettv); fc->fc_level = ex_nesting_level; // Check if this function has a breakpoint. fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); fc->fc_dbg_tick = debug_tick; - // Set up fields for closure. ga_init(&fc->fc_ufuncs, sizeof(ufunc_T *), 1); - func_ptr_ref(fp); if (strncmp(fp->uf_name, "", 8) == 0) { islambda = true; -- cgit From 7a3f86481e96e5c30db5af74760e475bac8cc403 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 17 Apr 2023 09:08:25 +0800 Subject: vim-patch:9.0.0419: the :defer command does not check the function arguments Problem: The :defer command does not check the function argument count and types. Solution: Check the function arguments when adding a deferred function. https://github.com/vim/vim/commit/169003289fb4b2ad18fd7f5807e0d05efff0be85 Cherry-pick check_internal_func() from Vim, but use EvalFuncDef pointer as first argument. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 25 +++++++++++++++++++++++++ src/nvim/eval/userfunc.c | 31 +++++++++++++++++++++++++++---- 2 files changed, 52 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f53b283c79..b064379210 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -228,6 +228,31 @@ const EvalFuncDef *find_internal_func(const char *const name) return index >= 0 ? &functions[index] : NULL; } +/// Check the argument count to use for internal function "fdef". +/// @return -1 for failure, 0 if no method base accepted, 1 if method base is +/// first argument, 2 if method base is second argument, etc. +int check_internal_func(const EvalFuncDef *const fdef, const int argcount) + FUNC_ATTR_NONNULL_ALL +{ + int res; + + if (argcount < fdef->min_argc) { + res = FCERR_TOOFEW; + } else if (argcount > fdef->max_argc) { + res = FCERR_TOOMANY; + } else { + return fdef->base_arg; + } + + const char *const name = fdef->name; + if (res == FCERR_TOOMANY) { + semsg(_(e_toomanyarg), name); + } else { + semsg(_(e_toofewarg), name); + } + return -1; +} + int call_internal_func(const char *const fname, const int argcount, typval_T *const argvars, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 32f9f9182c..65918ba2bf 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -72,7 +72,7 @@ static funccall_T *current_funccal = NULL; // item in it is still being used. static funccall_T *previous_funccal = NULL; -static const char *e_unknownfunc = N_("E117: Unknown function: %s"); +static const char *e_unknown_function_str = N_("E117: Unknown function: %s"); static const char *e_funcexts = N_("E122: Function %s already exists, add ! to replace it"); static const char *e_funcdict = N_("E717: Dictionary entry already exists"); static const char *e_funcref = N_("E718: Funcref required"); @@ -1523,14 +1523,14 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv /// 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 *name, funcexe_T *funcexe) - FUNC_ATTR_NONNULL_ALL + FUNC_ATTR_NONNULL_ARG(2) { switch (error) { case FCERR_UNKNOWN: if (funcexe->fe_found_var) { semsg(_(e_not_callable_type_str), name); } else { - emsg_funcname(e_unknownfunc, name); + emsg_funcname(e_unknown_function_str, name); } break; case FCERR_NOTMETHOD: @@ -1543,7 +1543,7 @@ static void user_func_error(int error, const char *name, funcexe_T *funcexe) emsg_funcname(_(e_toomanyarg), name); break; case FCERR_TOOFEW: - emsg_funcname(N_("E119: Not enough arguments for function: %s"), name); + emsg_funcname(_(e_toofewarg), name); break; case FCERR_SCRIPT: emsg_funcname(N_("E120: Using not in a script context: %s"), name); @@ -3172,6 +3172,29 @@ static int ex_defer_inner(char *name, char **arg, const partial_T *const partial } int r = get_func_arguments(arg, evalarg, false, argvars + partial_argc, &argcount); argcount += partial_argc; + + if (r == OK) { + if (builtin_function(name, -1)) { + const EvalFuncDef *const fdef = find_internal_func(name); + if (fdef == NULL) { + emsg_funcname(e_unknown_function_str, name); + r = FAIL; + } else if (check_internal_func(fdef, argcount) == -1) { + r = FAIL; + } + } else { + ufunc_T *ufunc = find_func(name); + // we tolerate an unknown function here, it might be defined later + if (ufunc != NULL) { + int error = check_user_func_argcount(ufunc, argcount); + if (error != FCERR_UNKNOWN) { + user_func_error(error, name, NULL); + r = FAIL; + } + } + } + } + if (r == FAIL) { while (--argcount >= 0) { tv_clear(&argvars[argcount]); -- cgit From 9722b3b9f983a3401423c41f05dd559f6aa410cd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 17 Apr 2023 14:38:53 +0800 Subject: vim-patch:9.0.1400: find_file_in_path() is not reentrant (#23146) Problem: find_file_in_path() is not reentrant. Solution: Instead of global variables pass pointers to the functions. (closes vim/vim#12093) https://github.com/vim/vim/commit/5145c9a829cd43cb9e7962b181bf99226eb3a53f Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b064379210..28901d6e55 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2146,6 +2146,9 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } if (*fname != NUL && !error) { + char *file_to_find = NULL; + char *search_ctx = NULL; + do { if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) { xfree(fresult); @@ -2156,13 +2159,17 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) find_what, curbuf->b_ffname, (find_what == FINDFILE_DIR ? "" - : curbuf->b_p_sua)); + : curbuf->b_p_sua), + &file_to_find, &search_ctx); first = false; if (fresult != NULL && rettv->v_type == VAR_LIST) { tv_list_append_string(rettv->vval.v_list, fresult, -1); } } while ((rettv->v_type == VAR_LIST || --count > 0) && fresult != NULL); + + xfree(file_to_find); + vim_findfile_cleanup(search_ctx); } if (rettv->v_type == VAR_STRING) { -- cgit From e83682e652ff68cf9a05f0076bb088e9231d2059 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 17 Apr 2023 19:22:55 +0800 Subject: refactor: suppress clang false positives (#23154) --- src/nvim/eval/userfunc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 65918ba2bf..e138c50b6a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -536,6 +536,7 @@ int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, evalarg_ : funcexe->fe_partial->pt_argc), argvars, &argcount); + assert(ret == OK || ret == FAIL); // suppress clang false positive if (ret == OK) { int i = 0; -- cgit From 9180c18c462a4945657899b732189da6f2ea2eaf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 18 Apr 2023 14:31:40 +0800 Subject: vim-patch:9.0.0864: crash when using "!!" without a previous shell command Problem: Crash when using "!!" without a previous shell command. Solution: Check "prevcmd" is not NULL. (closes vim/vim#11487) https://github.com/vim/vim/commit/6600447c7b0a1be3a64d07a318bacdfaae0cac4b Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e138c50b6a..63d5f94f11 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3207,7 +3207,7 @@ static int ex_defer_inner(char *name, char **arg, const partial_T *const partial } /// Return true if currently inside a function call. -/// Give an error message and return FALSE when not. +/// Give an error message and return false when not. bool can_add_defer(void) { if (get_current_funccal() == NULL) { -- cgit From 8e0ad6e261b81e9e2649bdba103904867b7ff6ef Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 19 Apr 2023 07:52:53 +0800 Subject: vim-patch:9.0.1462: recursively calling :defer function if it does :qa Problem: Recursively calling :defer function if it does :qa. Solution: Clear the defer entry before calling the function. (closes vim/vim#12266) https://github.com/vim/vim/commit/42994bf678f46dc9ca66e49f512261da8864fff6 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 63d5f94f11..e8b50d8c94 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3242,12 +3242,24 @@ static void handle_defer_one(funccall_T *funccal) { for (int idx = funccal->fc_defer.ga_len - 1; idx >= 0; idx--) { defer_T *dr = ((defer_T *)funccal->fc_defer.ga_data) + idx; + + if (dr->dr_name == NULL) { + // already being called, can happen if function does ":qa" + continue; + } + funcexe_T funcexe = { .fe_evaluate = true }; + typval_T rettv; rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this - call_func(dr->dr_name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe); + + char *name = dr->dr_name; + dr->dr_name = NULL; + + call_func(name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe); + tv_clear(&rettv); - xfree(dr->dr_name); + xfree(name); for (int i = dr->dr_argcount - 1; i >= 0; i--) { tv_clear(&dr->dr_argvars[i]); } -- cgit From a0c982671ee2f4c4e87a6480d2ea4d23ba807273 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 19 Apr 2023 07:59:35 +0800 Subject: vim-patch:9.0.1469: deferred functions not called from autocommands Problem: Deferred functions not called from autocommands. Solution: Also go through the funccal_stack. (closes vim/vim#12267) https://github.com/vim/vim/commit/960cf9119e3f4922ca9719feb5e0c0bc5e3b9840 --- src/nvim/eval/userfunc.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e8b50d8c94..4cb2f9bd2b 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3270,8 +3270,14 @@ static void handle_defer_one(funccall_T *funccal) /// Called when exiting: call all defer functions. void invoke_all_defer(void) { - for (funccall_T *funccal = current_funccal; funccal != NULL; funccal = funccal->fc_caller) { - handle_defer_one(funccal); + for (funccal_entry_T *fce = funccal_stack; fce != NULL; fce = fce->next) { + for (funccall_T *fc = fce->top_funccal; fc != NULL; fc = fc->fc_caller) { + handle_defer_one(fc); + } + } + + for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller) { + handle_defer_one(fc); } } -- cgit From 85c61d67160133ba53762bc1e5e7bbd7a0c582c0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 19 Apr 2023 10:06:34 +0800 Subject: vim-patch:9.0.1007: there is no way to get a list of swap file names Problem: There is no way to get a list of swap file names. Solution: Add the swapfilelist() function. Use it in the test script to clean up. Remove deleting individual swap files. https://github.com/vim/vim/commit/c216a7a21a25a701b84b79abc1ba6ab0baa3a311 vim-patch:9.0.1005: a failed test may leave a swap file behind Problem: A failed test may leave a swap file behind. Solution: Delete the swap file to avoid another test to fail. Use another file name. https://github.com/vim/vim/commit/d0f8d39d20f8d42f7451f781f7be0bcd20e06741 Cherry-pick test_window_cmd.vim changes from patch 8.2.1593. Remove FUNC_ATTR_UNUSED from eval functions as fptr is always unused. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 28901d6e55..d9226214c6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -44,6 +44,7 @@ #include "nvim/eval/executor.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" @@ -3850,8 +3851,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// "interrupt()" function -static void f_interrupt(typval_T *argvars FUNC_ATTR_UNUSED, typval_T *rettv FUNC_ATTR_UNUSED, - EvalFuncData fptr FUNC_ATTR_UNUSED) +static void f_interrupt(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { got_int = true; } @@ -8523,6 +8523,13 @@ static void f_substitute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } +/// "swapfilelist()" function +static void f_swapfilelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, kListLenUnknown); + recover_names(NULL, false, rettv->vval.v_list, 0, NULL); +} + /// "swapinfo(swap_filename)" function static void f_swapinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From 0d7bed34a29ef1add5d225a6809882fa6dce49d9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 19 Apr 2023 22:09:48 +0800 Subject: vim-patch:9.0.1470: deferred functions invoked in unexpected order (#23199) Problem: Deferred functions invoked in unexpected order when using :qa and autocommands. Solution: Call deferred functions for the current funccal before using the stack. (closes vim/vim#12278) https://github.com/vim/vim/commit/1be4b81bfb3d7edf0e2ae41711d429e8fa5e0555 --- src/nvim/eval/userfunc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4cb2f9bd2b..51e109fdfb 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3270,15 +3270,15 @@ static void handle_defer_one(funccall_T *funccal) /// Called when exiting: call all defer functions. void invoke_all_defer(void) { + for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller) { + handle_defer_one(fc); + } + for (funccal_entry_T *fce = funccal_stack; fce != NULL; fce = fce->next) { for (funccall_T *fc = fce->top_funccal; fc != NULL; fc = fc->fc_caller) { handle_defer_one(fc); } } - - for (funccall_T *fc = current_funccal; fc != NULL; fc = fc->fc_caller) { - handle_defer_one(fc); - } } /// ":1,25call func(arg1, arg2)" function call. -- cgit From 706f871014b46300180156590ff269ee38473989 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 19 Apr 2023 17:04:00 +0100 Subject: build: update uncrustify to 0.76 --- src/nvim/eval/funcs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d9226214c6..d903d498e7 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2265,7 +2265,8 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "foreground()" function static void f_foreground(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{} +{ +} static void f_funcref(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -2941,7 +2942,8 @@ static void f_gettagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// 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(). static void dummy_timer_close_cb(TimeWatcher *tw, void *data) -- cgit From 9802de933484cc0a69ee328f3e4e6efbb83c308e Mon Sep 17 00:00:00 2001 From: Andreas Schneider Date: Fri, 21 Apr 2023 11:07:56 +0200 Subject: fix(userfunc): fix possible out of bound access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In file included from /usr/include/string.h:535, from gsrc/nvim/eval/userfunc.c:11: In function ‘strcpy’, inlined from ‘cat_func_name’ at gsrc/nvim/eval/userfunc.c:662:5, inlined from ‘get_user_func_name’ at gsrc/nvim/eval/userfunc.c:2854:5: /usr/include/bits/string_fortified.h:79:10: warning: ‘__builtin___strcpy_chk’ offset 0 from the object at ‘’ is out of the bounds of referenced subobject ‘uf_name’ with ty pe ‘char[]’ at offset 0 [-Warray-bounds=] 79 | return __builtin___strcpy_chk (__dest, __src, __glibc_objsize (__dest)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In file included from gsrc/nvim/eval/typval.h:10, from gsrc/nvim/buffer_defs.h:20, from gsrc/nvim/autocmd.h:8, from gsrc/nvim/eval/userfunc.c:15: gsrc/nvim/eval/typval_defs.h: In function ‘get_user_func_name’: gsrc/nvim/eval/typval_defs.h:342:8: note: subobject ‘uf_name’ declared here 342 | char uf_name[]; ///< Name of function (actual size equals name); | ^~~~~~~ --- src/nvim/eval/userfunc.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 51e109fdfb..b71e6c9cff 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -653,14 +653,20 @@ ufunc_T *find_func(const char *name) /// 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 *buf, ufunc_T *fp) +static void cat_func_name(char *buf, size_t buflen, ufunc_T *fp) { - if ((uint8_t)fp->uf_name[0] == K_SPECIAL) { - STRCPY(buf, ""); - STRCAT(buf, fp->uf_name + 3); + int len = -1; + size_t uflen = strlen(fp->uf_name); + assert(uflen > 0); + + if ((uint8_t)fp->uf_name[0] == K_SPECIAL && uflen > 3) { + len = snprintf(buf, buflen, "%s", fp->uf_name + 3); } else { - STRCPY(buf, fp->uf_name); + len = snprintf(buf, buflen, "%s", fp->uf_name); } + + (void)len; // Avoid unused warning on release builds + assert(len > 0); } /// Add a number variable "name" to dict "dp" with value "nr". @@ -2851,7 +2857,7 @@ char *get_user_func_name(expand_T *xp, int idx) return fp->uf_name; // Prevent overflow. } - cat_func_name(IObuff, fp); + cat_func_name(IObuff, IOSIZE, fp); if (xp->xp_context != EXPAND_USER_FUNC) { STRCAT(IObuff, "("); if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) { -- cgit From 1355861b926a05e411ba3d42fa85a2fe238aea8d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 23 Apr 2023 17:44:08 +0800 Subject: fix(typval): don't treat v:null as truthy (#23281) --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7c982de61e..357ef6414d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -4224,7 +4224,7 @@ bool tv2bool(const typval_T *const tv) case VAR_BOOL: return tv->vval.v_bool == kBoolVarTrue; case VAR_SPECIAL: - return tv->vval.v_special == kSpecialVarNull; + return tv->vval.v_special != kSpecialVarNull; case VAR_BLOB: return tv->vval.v_blob != NULL && tv->vval.v_blob->bv_ga.ga_len > 0; case VAR_UNKNOWN: -- cgit From 43c49746d9cf82dba0d56b07d39722f9ebeecf90 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 25 Apr 2023 21:32:12 +0800 Subject: vim-patch:9.0.0335: checks for Dictionary argument often give a vague error (#23309) Problem: Checks for Dictionary argument often give a vague error message. Solution: Give a useful error message. (Yegappan Lakshmanan, closes vim/vim#11009) https://github.com/vim/vim/commit/04c4c5746e15884768d2cb41370c3276a196cd4c Cherry-pick removal of E922 from docs from patch 9.0.1403. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 14 +++------ src/nvim/eval/typval.c | 23 +++++++++++--- src/nvim/eval/window.c | 84 ++++++++++++++++++++++++-------------------------- 3 files changed, 65 insertions(+), 56 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d903d498e7..2a5f1cb720 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -597,8 +597,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) dict_T *selfdict = NULL; if (argvars[2].v_type != VAR_UNKNOWN) { - if (argvars[2].v_type != VAR_DICT) { - emsg(_(e_dictreq)); + if (tv_check_for_dict_arg(argvars, 2) == FAIL) { if (owned) { func_unref(func); } @@ -7359,8 +7358,7 @@ static void f_setcharpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_DICT) { - emsg(_(e_dictreq)); + if (tv_check_for_dict_arg(argvars, 0) == FAIL) { return; } @@ -7631,8 +7629,7 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } // second argument: dict with items to set in the tag stack - if (argvars[1].v_type != VAR_DICT) { - emsg(_(e_dictreq)); + if (tv_check_for_dict_arg(argvars, 1) == FAIL) { return; } dict_T *d = argvars[1].vval.v_dict; @@ -8987,11 +8984,10 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (argvars[2].v_type != VAR_UNKNOWN) { - dict_T *dict = argvars[2].vval.v_dict; - if (argvars[2].v_type != VAR_DICT || dict == NULL) { - semsg(_(e_invarg2), tv_get_string(&argvars[2])); + if (tv_check_for_nonnull_dict_arg(argvars, 2) == FAIL) { return; } + dict_T *dict = argvars[2].vval.v_dict; dictitem_T *const di = tv_dict_find(dict, S_LEN("repeat")); if (di != NULL) { repeat = (int)tv_get_number(&di->di_tv); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 357ef6414d..e4b809d98d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -60,6 +60,8 @@ static const char e_invalid_value_for_blob_nr[] = N_("E1239: Invalid value for blob: %d"); static const char e_string_or_function_required_for_argument_nr[] = N_("E1256: String or function required for argument %d"); +static const char e_non_null_dict_required_for_argument_nr[] + = N_("E1297: Non-NULL Dictionary required for argument %d"); bool tv_in_free_unref_items = false; @@ -1232,8 +1234,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (argvars[2].v_type != VAR_UNKNOWN) { // optional third argument: {dict} - if (argvars[2].v_type != VAR_DICT) { - emsg(_(e_dictreq)); + if (tv_check_for_dict_arg(argvars, 2) == FAIL) { goto theend; } info.item_compare_selfdict = argvars[2].vval.v_dict; @@ -2993,10 +2994,10 @@ void f_values(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "has_key()" function void f_has_key(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_DICT) { - emsg(_(e_dictreq)); + if (tv_check_for_dict_arg(argvars, 0) == FAIL) { return; } + if (argvars[0].vval.v_dict == NULL) { return; } @@ -4051,6 +4052,20 @@ int tv_check_for_dict_arg(const typval_T *const args, const int idx) return OK; } +/// Give an error and return FAIL unless "args[idx]" is a non-NULL dict. +int tv_check_for_nonnull_dict_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (tv_check_for_dict_arg(args, idx) == FAIL) { + return FAIL; + } + if (args[idx].vval.v_dict == NULL) { + semsg(_(e_non_null_dict_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Check for an optional dict argument at "idx" int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 25de236d90..9976c56879 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -651,8 +651,7 @@ void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) dict_T *d; dictitem_T *di; - if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { - emsg(_(e_invarg)); + if (tv_check_for_nonnull_dict_arg(argvars, 2) == FAIL) { return; } @@ -796,51 +795,50 @@ void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "winrestview()" function void f_winrestview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - dict_T *dict = argvars[0].vval.v_dict; + if (tv_check_for_nonnull_dict_arg(argvars, 0) == FAIL) { + return; + } - if (argvars[0].v_type != VAR_DICT || dict == NULL) { - emsg(_(e_invarg)); - } else { - dictitem_T *di; - if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { - curwin->w_cursor.lnum = (linenr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { - curwin->w_cursor.col = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { - curwin->w_cursor.coladd = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { - curwin->w_curswant = (colnr_T)tv_get_number(&di->di_tv); - curwin->w_set_curswant = false; - } - if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { - set_topline(curwin, (linenr_T)tv_get_number(&di->di_tv)); - } - if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { - curwin->w_topfill = (int)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { - curwin->w_leftcol = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { - curwin->w_skipcol = (colnr_T)tv_get_number(&di->di_tv); - } + dict_T *dict = argvars[0].vval.v_dict; + dictitem_T *di; + if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { + curwin->w_cursor.lnum = (linenr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { + curwin->w_cursor.col = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { + curwin->w_cursor.coladd = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { + curwin->w_curswant = (colnr_T)tv_get_number(&di->di_tv); + curwin->w_set_curswant = false; + } + if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { + set_topline(curwin, (linenr_T)tv_get_number(&di->di_tv)); + } + if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { + curwin->w_topfill = (int)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { + curwin->w_leftcol = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { + curwin->w_skipcol = (colnr_T)tv_get_number(&di->di_tv); + } - check_cursor(); - win_new_height(curwin, curwin->w_height); - win_new_width(curwin, curwin->w_width); - changed_window_setting(); + check_cursor(); + win_new_height(curwin, curwin->w_height); + win_new_width(curwin, curwin->w_width); + changed_window_setting(); - if (curwin->w_topline <= 0) { - curwin->w_topline = 1; - } - if (curwin->w_topline > curbuf->b_ml.ml_line_count) { - curwin->w_topline = curbuf->b_ml.ml_line_count; - } - check_topfill(curwin, true); + if (curwin->w_topline <= 0) { + curwin->w_topline = 1; + } + if (curwin->w_topline > curbuf->b_ml.ml_line_count) { + curwin->w_topline = curbuf->b_ml.ml_line_count; } + check_topfill(curwin, true); } /// "winsaveview()" function -- cgit From bfa92d3861e425b59f9b1793c08247965a8e53f5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 25 Apr 2023 22:22:26 +0800 Subject: vim-patch:8.2.5019: cannot get the first screen column of a character (#23312) Problem: Cannot get the first screen column of a character. Solution: Let virtcol() optionally return a list. (closes vim/vim#10482, closes vim/vim#7964) https://github.com/vim/vim/commit/0f7a3e1de6f71e8e1423fe594890d6aa7f94e132 Co-authored-by: LemonBoy --- src/nvim/eval/funcs.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 2a5f1cb720..72e25411ff 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9275,10 +9275,11 @@ static void f_undotree(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead)); } -/// "virtcol(string)" function +/// "virtcol(string, bool)" function static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - colnr_T vcol = 0; + colnr_T vcol_start = 0; + colnr_T vcol_end = 0; int fnum = curbuf->b_fnum; pos_T *fp = var2fpos(&argvars[0], false, &fnum, false); @@ -9293,11 +9294,18 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) fp->col = (colnr_T)len; } } - getvvcol(curwin, fp, NULL, NULL, &vcol); - vcol++; + getvvcol(curwin, fp, &vcol_start, NULL, &vcol_end); + vcol_start++; + vcol_end++; } - rettv->vval.v_number = vcol; + if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) { + tv_list_alloc_ret(rettv, 2); + tv_list_append_number(rettv->vval.v_list, vcol_start); + tv_list_append_number(rettv->vval.v_list, vcol_end); + } else { + rettv->vval.v_number = vcol_end; + } } /// "visualmode()" function -- cgit From 255e547e18e127ab70ffa2e423f7753786cb424e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 25 Apr 2023 22:21:19 +0800 Subject: fix(timer): allow timer_info() to get info about current timer --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 72e25411ff..3cf18e1c68 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8944,7 +8944,7 @@ static void f_timer_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } tv_list_alloc_ret(rettv, 1); timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); - if (timer != NULL && !timer->stopped) { + if (timer != NULL && (!timer->stopped || timer->refcount > 1)) { add_timer_info(rettv, timer); } } else { -- cgit From ac9f8669a8e4bd0cf13468d316d1746be65d3cdc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 25 Apr 2023 23:19:00 +0800 Subject: vim-patch:9.0.0875: using freed memory when executing delfunc at more prompt (#23314) Problem: Using freed memory when executing delfunc at the more prompt. Solution: Check function list not changed in another place. (closes vim/vim#11437) https://github.com/vim/vim/commit/398a26f7fcd58fbc6e2329f892edbb7479a971bb Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 80 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 57 insertions(+), 23 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index b71e6c9cff..854a0732ab 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -77,6 +77,8 @@ static const char *e_funcexts = N_("E122: Function %s already exists, add ! to r static const char *e_funcdict = N_("E717: Dictionary entry already exists"); static const char *e_funcref = N_("E718: Funcref required"); static const char *e_nofunc = N_("E130: Unknown function: %s"); +static const char e_function_list_was_modified[] + = N_("E454: Function list was modified"); static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); static const char e_missing_heredoc_end_marker_str[] @@ -1752,14 +1754,33 @@ char *printable_func_name(ufunc_T *fp) return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; } +/// When "prev_ht_changed" does not equal "ht_changed" give an error and return +/// true. Otherwise return false. +static int function_list_modified(const int prev_ht_changed) +{ + if (prev_ht_changed != func_hashtab.ht_changed) { + emsg(_(e_function_list_was_modified)); + return true; + } + return false; +} + /// List the head of the function: "name(arg1, arg2)". /// /// @param[in] fp Function pointer. /// @param[in] indent Indent line. /// @param[in] force Include bang "!" (i.e.: "function!"). -static void list_func_head(ufunc_T *fp, int indent, bool force) +static int list_func_head(ufunc_T *fp, bool indent, bool force) { + const int prev_ht_changed = func_hashtab.ht_changed; + msg_start(); + + // a callback at the more prompt may have deleted the function + if (function_list_modified(prev_ht_changed)) { + return FAIL; + } + if (indent) { msg_puts(" "); } @@ -1805,6 +1826,8 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) if (p_verbose > 0) { last_set_msg(fp->uf_script_ctx); } + + return OK; } /// Get a function name, translating "" and "". @@ -2085,7 +2108,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) /// Otherwise functions matching "regmatch". static void list_functions(regmatch_T *regmatch) { - const int changed = func_hashtab.ht_changed; + const int prev_ht_changed = func_hashtab.ht_changed; size_t todo = func_hashtab.ht_used; const hashitem_T *const ht_array = func_hashtab.ht_array; @@ -2098,9 +2121,10 @@ static void list_functions(regmatch_T *regmatch) && !func_name_refcount(fp->uf_name)) : (!isdigit((uint8_t)(*fp->uf_name)) && vim_regexec(regmatch, fp->uf_name, 0))) { - list_func_head(fp, false, false); - if (changed != func_hashtab.ht_changed) { - emsg(_("E454: function list was modified")); + if (list_func_head(fp, false, false) == FAIL) { + return; + } + if (function_list_modified(prev_ht_changed)) { return; } } @@ -2229,27 +2253,37 @@ void ex_function(exarg_T *eap) if (!eap->skip && !got_int) { fp = find_func(name); if (fp != NULL) { - list_func_head(fp, !eap->forceit, eap->forceit); - for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) { - if (FUNCLINE(fp, j) == NULL) { - continue; - } - msg_putchar('\n'); - if (!eap->forceit) { - msg_outnum((long)j + 1); - if (j < 9) { - msg_putchar(' '); + // Check no function was added or removed from a callback, e.g. at + // the more prompt. "fp" may then be invalid. + const int prev_ht_changed = func_hashtab.ht_changed; + + if (list_func_head(fp, !eap->forceit, eap->forceit) == OK) { + for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) { + if (FUNCLINE(fp, j) == NULL) { + continue; } - if (j < 99) { - msg_putchar(' '); + msg_putchar('\n'); + if (!eap->forceit) { + msg_outnum((long)j + 1); + if (j < 9) { + msg_putchar(' '); + } + if (j < 99) { + msg_putchar(' '); + } + if (function_list_modified(prev_ht_changed)) { + break; + } + } + msg_prt_line(FUNCLINE(fp, j), false); + line_breakcheck(); // show multiple lines at a time! + } + if (!got_int) { + msg_putchar('\n'); + if (!function_list_modified(prev_ht_changed)) { + msg_puts(eap->forceit ? "endfunction" : " endfunction"); } } - msg_prt_line(FUNCLINE(fp, j), false); - line_breakcheck(); // show multiple lines at a time! - } - if (!got_int) { - msg_putchar('\n'); - msg_puts(eap->forceit ? "endfunction" : " endfunction"); } } else { emsg_funcname(N_("E123: Undefined function: %s"), name); -- cgit From 7e0d66801297677ecbb6b35d0c9139e672920be4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 25 Apr 2023 23:39:15 +0800 Subject: vim-patch:partial:9.0.0359: error message for wrong argument type is not specific (#23315) Problem: Error message for wrong argument type is not specific. Solution: Include more information in the error. (Yegappan Lakshmanan, closes vim/vim#11037) https://github.com/vim/vim/commit/8deb2b30c77035bb682ccf80b781455ac1d6038b Skip reduce() and deepcopy() changes because of missing patches. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 45 +++++++++++++++++++-------------------------- src/nvim/eval/typval.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 26 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3cf18e1c68..afb8d841a4 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -793,12 +793,9 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { rettv->vval.v_number = -1; - if (argvars[0].v_type != VAR_STRING - || argvars[1].v_type != VAR_NUMBER - || (argvars[2].v_type != VAR_UNKNOWN - && argvars[2].v_type != VAR_NUMBER - && argvars[2].v_type != VAR_BOOL)) { - emsg(_(e_invarg)); + if ((tv_check_for_string_arg(argvars, 0) == FAIL + || tv_check_for_number_arg(argvars, 1) == FAIL + || tv_check_for_opt_bool_arg(argvars, 2) == FAIL)) { return; } @@ -3114,14 +3111,12 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "gettext()" function static void f_gettext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_STRING - || argvars[0].vval.v_string == NULL - || *argvars[0].vval.v_string == NUL) { - semsg(_(e_invarg2), tv_get_string(&argvars[0])); - } else { - rettv->v_type = VAR_STRING; - rettv->vval.v_string = xstrdup(_(argvars[0].vval.v_string)); + if (tv_check_for_nonempty_string_arg(argvars, 0) == FAIL) { + return; } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = xstrdup(_(argvars[0].vval.v_string)); } /// "has()" function @@ -7641,7 +7636,9 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // default is to replace the stack. if (argvars[2].v_type == VAR_UNKNOWN) { // action = 'r'; - } else if (argvars[2].v_type == VAR_STRING) { + } else if (tv_check_for_string_arg(argvars, 2) == FAIL) { + return; + } else { const char *actstr; actstr = tv_get_string_chk(&argvars[2]); if (actstr == NULL) { @@ -7654,9 +7651,6 @@ static void f_settagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) semsg(_(e_invact2), actstr); return; } - } else { - emsg(_(e_stringreq)); - return; } if (set_tagstack(wp, d, action) == OK) { @@ -8937,12 +8931,13 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "timer_info([timer])" function static void f_timer_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + tv_list_alloc_ret(rettv, kListLenUnknown); + + if (tv_check_for_opt_number_arg(argvars, 0) == FAIL) { + return; + } + if (argvars[0].v_type != VAR_UNKNOWN) { - if (argvars[0].v_type != VAR_NUMBER) { - emsg(_(e_number_exp)); - return; - } - tv_list_alloc_ret(rettv, 1); timer_T *timer = find_timer_by_nr(tv_get_number(&argvars[0])); if (timer != NULL && (!timer->stopped || timer->refcount > 1)) { add_timer_info(rettv, timer); @@ -9008,8 +9003,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "timer_stop(timerid)" function static void f_timer_stop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_NUMBER) { - emsg(_(e_number_exp)); + if (tv_check_for_number_arg(argvars, 0) == FAIL) { return; } @@ -9136,8 +9130,7 @@ static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - if (argvars[1].v_type != VAR_UNKNOWN && argvars[1].v_type != VAR_STRING) { - semsg(_(e_invarg2), tv_get_string(&argvars[1])); + if (tv_check_for_opt_string_arg(argvars, 1) == FAIL) { return; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index e4b809d98d..6556e274ab 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -50,6 +50,8 @@ static const char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); static const char e_list_required_for_argument_nr[] = N_("E1211: List required for argument %d"); +static const char e_bool_required_for_argument_nr[] + = N_("E1212: Bool required for argument %d"); static const char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); static const char e_list_or_blob_required_for_argument_nr[] @@ -4000,6 +4002,14 @@ int tv_check_for_nonempty_string_arg(const typval_T *const args, const int idx) return OK; } +/// Check for an optional string argument at "idx" +int tv_check_for_opt_string_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return (args[idx].v_type == VAR_UNKNOWN + || tv_check_for_string_arg(args, idx) != FAIL) ? OK : FAIL; +} + /// Give an error and return FAIL unless "args[idx]" is a number. int tv_check_for_number_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE @@ -4019,6 +4029,31 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a bool. +int tv_check_for_bool_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_BOOL + && !(args[idx].v_type == VAR_NUMBER + && (args[idx].vval.v_number == 0 + || args[idx].vval.v_number == 1))) { + semsg(_(e_bool_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Check for an optional bool argument at "idx". +/// Return FAIL if the type is wrong. +int tv_check_for_opt_bool_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type == VAR_UNKNOWN) { + return OK; + } + return tv_check_for_bool_arg(args, idx); +} + /// Give an error and return FAIL unless "args[idx]" is a blob. int tv_check_for_blob_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE -- cgit From 907018e547c9b989781667d2cf951e1abf99ab9d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 26 Apr 2023 00:23:11 +0800 Subject: vim-patch:8.2.3139: functions for string manipulation are spread out (#23316) Problem: Functions for string manipulation are spread out. Solution: Move string related functions to a new source file. (Yegappan Lakshmanan, closes vim/vim#8470) https://github.com/vim/vim/commit/a2438132a675be4dde3acbdf03ba1fdb2f09427c Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 621 -------------------------------------------------- 1 file changed, 621 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index afb8d841a4..5c9d39b91f 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -149,8 +149,6 @@ PRAGMA_DIAG_POP static const char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static const char *e_invalwindow = N_("E957: Invalid window number"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); -static const char e_using_number_as_bool_nr[] - = N_("E1023: Using a Number as a Bool: %d"); static const char e_missing_function_argument[] = N_("E1132: Missing function argument"); @@ -529,41 +527,6 @@ static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -static void byteidx(typval_T *argvars, typval_T *rettv, int comp) -{ - const char *const str = tv_get_string_chk(&argvars[0]); - varnumber_T idx = tv_get_number_chk(&argvars[1], NULL); - rettv->vval.v_number = -1; - if (str == NULL || idx < 0) { - return; - } - - const char *t = str; - for (; idx > 0; idx--) { - if (*t == NUL) { // EOL reached. - return; - } - if (comp) { - t += utf_ptr2len(t); - } else { - t += utfc_ptr2len(t); - } - } - rettv->vval.v_number = (varnumber_T)(t - str); -} - -/// "byteidx()" function -static void f_byteidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - byteidx(argvars, rettv, false); -} - -/// "byteidxcomp()" function -static void f_byteidxcomp(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - byteidx(argvars, rettv, true); -} - /// "call(func, arglist [, dict])" function static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -788,50 +751,6 @@ static void f_charcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) get_col(argvars, rettv, true); } -/// "charidx()" function -static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = -1; - - if ((tv_check_for_string_arg(argvars, 0) == FAIL - || tv_check_for_number_arg(argvars, 1) == FAIL - || tv_check_for_opt_bool_arg(argvars, 2) == FAIL)) { - return; - } - - const char *str = tv_get_string_chk(&argvars[0]); - varnumber_T idx = tv_get_number_chk(&argvars[1], NULL); - if (str == NULL || idx < 0) { - return; - } - int countcc = 0; - if (argvars[2].v_type != VAR_UNKNOWN) { - countcc = (int)tv_get_number(&argvars[2]); - } - if (countcc < 0 || countcc > 1) { - semsg(_(e_using_number_as_bool_nr), countcc); - return; - } - - int (*ptr2len)(const char *); - if (countcc) { - ptr2len = utf_ptr2len; - } else { - ptr2len = utfc_ptr2len; - } - - const char *p; - int len; - for (p = str, len = 0; p <= str + idx; len++) { - if (*p == NUL) { - return; - } - p += ptr2len(p); - } - - rettv->vval.v_number = len > 0 ? len - 1 : 0; -} - /// "chdir(dir)" function static void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3447,34 +3366,6 @@ static void f_hostname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = xstrdup(hostname); } -/// iconv() function -static void f_iconv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - vimconv_T vimconv; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - const char *const str = tv_get_string(&argvars[0]); - char buf1[NUMBUFLEN]; - char *const from = enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[1], buf1))); - char buf2[NUMBUFLEN]; - char *const to = enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[2], buf2))); - vimconv.vc_type = CONV_NONE; - convert_setup(&vimconv, from, to); - - // If the encodings are equal, no conversion needed. - if (vimconv.vc_type == CONV_NONE) { - rettv->vval.v_string = xstrdup(str); - } else { - rettv->vval.v_string = string_convert(&vimconv, (char *)str, NULL); - } - - convert_setup(&vimconv, NULL, NULL); - xfree(from); - xfree(to); -} - /// "indent()" function static void f_indent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -8041,60 +7932,6 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->v_type = VAR_FLOAT; } -/// "str2list()" function -static void f_str2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_list_alloc_ret(rettv, kListLenUnknown); - const char *p = tv_get_string(&argvars[0]); - - for (; *p != NUL; p += utf_ptr2len(p)) { - tv_list_append_number(rettv->vval.v_list, utf_ptr2char(p)); - } -} - -/// "str2nr()" function -static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int base = 10; - int what = 0; - - if (argvars[1].v_type != VAR_UNKNOWN) { - base = (int)tv_get_number(&argvars[1]); - if (base != 2 && base != 8 && base != 10 && base != 16) { - emsg(_(e_invarg)); - return; - } - if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2])) { - what |= STR2NR_QUOTE; - } - } - - char *p = skipwhite(tv_get_string(&argvars[0])); - bool isneg = (*p == '-'); - if (*p == '+' || *p == '-') { - p = skipwhite(p + 1); - } - switch (base) { - case 2: - what |= STR2NR_BIN | STR2NR_FORCE; - break; - case 8: - what |= STR2NR_OCT | STR2NR_OOCT | STR2NR_FORCE; - break; - case 16: - what |= STR2NR_HEX | STR2NR_FORCE; - break; - } - varnumber_T n; - vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false, NULL); - // Text after the number is silently ignored. - if (isneg) { - rettv->vval.v_number = -n; - } else { - rettv->vval.v_number = n; - } -} - /// "strftime({format}[, {time}])" function static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -8145,235 +7982,6 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(enc); } -/// "strgetchar()" function -static void f_strgetchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = -1; - - const char *const str = tv_get_string_chk(&argvars[0]); - if (str == NULL) { - return; - } - bool error = false; - varnumber_T charidx = tv_get_number_chk(&argvars[1], &error); - if (error) { - return; - } - - const size_t len = strlen(str); - size_t byteidx = 0; - - while (charidx >= 0 && byteidx < len) { - if (charidx == 0) { - rettv->vval.v_number = utf_ptr2char(str + byteidx); - break; - } - charidx--; - byteidx += (size_t)utf_ptr2len(str + byteidx); - } -} - -/// "stridx()" function -static void f_stridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = -1; - - char buf[NUMBUFLEN]; - const char *const needle = tv_get_string_chk(&argvars[1]); - const char *haystack = tv_get_string_buf_chk(&argvars[0], buf); - const char *const haystack_start = haystack; - if (needle == NULL || haystack == NULL) { - return; // Type error; errmsg already given. - } - - if (argvars[2].v_type != VAR_UNKNOWN) { - bool error = false; - - const ptrdiff_t start_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], - &error); - if (error || start_idx >= (ptrdiff_t)strlen(haystack)) { - return; - } - if (start_idx >= 0) { - haystack += start_idx; - } - } - - const char *pos = strstr(haystack, needle); - if (pos != NULL) { - rettv->vval.v_number = (varnumber_T)(pos - haystack_start); - } -} - -/// "string()" function -static void f_string(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = encode_tv2string(&argvars[0], NULL); -} - -/// "strlen()" function -static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); -} - -static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc) -{ - const char *s = tv_get_string(&argvars[0]); - varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(const char **pp); - - func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; - while (*s != NUL) { - func_mb_ptr2char_adv(&s); - len++; - } - rettv->vval.v_number = len; -} - -/// "strcharlen()" function -static void f_strcharlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - strchar_common(argvars, rettv, true); -} - -/// "strchars()" function -static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int skipcc = false; - - if (argvars[1].v_type != VAR_UNKNOWN) { - skipcc = (int)tv_get_bool(&argvars[1]); - } - if (skipcc < 0 || skipcc > 1) { - semsg(_(e_using_number_as_bool_nr), skipcc); - } else { - strchar_common(argvars, rettv, skipcc); - } -} - -/// "strdisplaywidth()" function -static void f_strdisplaywidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const char *const s = tv_get_string(&argvars[0]); - int col = 0; - - if (argvars[1].v_type != VAR_UNKNOWN) { - col = (int)tv_get_number(&argvars[1]); - } - - rettv->vval.v_number = (varnumber_T)(linetabsize_col(col, (char *)s) - col); -} - -/// "strwidth()" function -static void f_strwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const char *const s = tv_get_string(&argvars[0]); - - rettv->vval.v_number = (varnumber_T)mb_string2cells(s); -} - -/// "strcharpart()" function -static void f_strcharpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const char *const p = tv_get_string(&argvars[0]); - const size_t slen = strlen(p); - - int nbyte = 0; - bool error = false; - varnumber_T nchar = tv_get_number_chk(&argvars[1], &error); - if (!error) { - if (nchar > 0) { - while (nchar > 0 && (size_t)nbyte < slen) { - nbyte += utf_ptr2len(p + nbyte); - nchar--; - } - } else { - nbyte = (int)nchar; - } - } - int len = 0; - if (argvars[2].v_type != VAR_UNKNOWN) { - int charlen = (int)tv_get_number(&argvars[2]); - while (charlen > 0 && nbyte + len < (int)slen) { - int off = nbyte + len; - - if (off < 0) { - len += 1; - } else { - len += utf_ptr2len(p + off); - } - charlen--; - } - } else { - len = (int)slen - nbyte; // default: all bytes that are available. - } - - // Only return the overlap between the specified part and the actual - // string. - if (nbyte < 0) { - len += nbyte; - nbyte = 0; - } else if ((size_t)nbyte > slen) { - nbyte = (int)slen; - } - if (len < 0) { - len = 0; - } else if (nbyte + len > (int)slen) { - len = (int)slen - nbyte; - } - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = xstrndup(p + nbyte, (size_t)len); -} - -/// "strpart()" function -static void f_strpart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - bool error = false; - - const char *const p = tv_get_string(&argvars[0]); - const size_t slen = strlen(p); - - varnumber_T n = tv_get_number_chk(&argvars[1], &error); - varnumber_T len; - if (error) { - len = 0; - } else if (argvars[2].v_type != VAR_UNKNOWN) { - len = tv_get_number(&argvars[2]); - } else { - len = (varnumber_T)slen - n; // Default len: all bytes that are available. - } - - // Only return the overlap between the specified part and the actual - // string. - if (n < 0) { - len += n; - n = 0; - } else if (n > (varnumber_T)slen) { - n = (varnumber_T)slen; - } - if (len < 0) { - len = 0; - } else if (n + len > (varnumber_T)slen) { - len = (varnumber_T)slen - n; - } - - if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN) { - int off; - - // length in characters - for (off = (int)n; off < (int)slen && len > 0; len--) { - off += utfc_ptr2len(p + off); - } - len = off - n; - } - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = xmemdupz(p + n, (size_t)len); -} - /// "strptime({format}, {timestring})" function static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -8406,56 +8014,6 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(enc); } -/// "strridx()" function -static void f_strridx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - char buf[NUMBUFLEN]; - const char *const needle = tv_get_string_chk(&argvars[1]); - const char *const haystack = tv_get_string_buf_chk(&argvars[0], buf); - - rettv->vval.v_number = -1; - if (needle == NULL || haystack == NULL) { - return; // Type error; errmsg already given. - } - - const size_t haystack_len = strlen(haystack); - ptrdiff_t end_idx; - if (argvars[2].v_type != VAR_UNKNOWN) { - // Third argument: upper limit for index. - end_idx = (ptrdiff_t)tv_get_number_chk(&argvars[2], NULL); - if (end_idx < 0) { - return; // Can never find a match. - } - } else { - end_idx = (ptrdiff_t)haystack_len; - } - - const char *lastmatch = NULL; - if (*needle == NUL) { - // Empty string matches past the end. - lastmatch = haystack + end_idx; - } else { - for (const char *rest = haystack; *rest != NUL; rest++) { - rest = strstr(rest, needle); - if (rest == NULL || rest > haystack + end_idx) { - break; - } - lastmatch = rest; - } - } - - if (lastmatch != NULL) { - rettv->vval.v_number = (varnumber_T)(lastmatch - haystack); - } -} - -/// "strtrans()" function -static void f_strtrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = transstr(tv_get_string(&argvars[0]), true); -} - /// "submatch()" function static void f_submatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -9020,185 +8578,6 @@ static void f_timer_stopall(typval_T *argvars, typval_T *unused, EvalFuncData fp timer_stop_all(); } -/// "tolower(string)" function -static void f_tolower(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), false); -} - -/// "toupper(string)" function -static void f_toupper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = strcase_save(tv_get_string(&argvars[0]), true); -} - -/// "tr(string, fromstr, tostr)" function -static void f_tr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - char buf[NUMBUFLEN]; - char buf2[NUMBUFLEN]; - - const char *in_str = tv_get_string(&argvars[0]); - const char *fromstr = tv_get_string_buf_chk(&argvars[1], buf); - const char *tostr = tv_get_string_buf_chk(&argvars[2], buf2); - - // Default return value: empty string. - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - if (fromstr == NULL || tostr == NULL) { - return; // Type error; errmsg already given. - } - garray_T ga; - ga_init(&ga, (int)sizeof(char), 80); - - // fromstr and tostr have to contain the same number of chars. - bool first = true; - while (*in_str != NUL) { - const char *cpstr = 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(p); - if (fromlen == inlen && strncmp(in_str, p, (size_t)inlen) == 0) { - int tolen; - for (p = tostr; *p != NUL; p += tolen) { - tolen = utfc_ptr2len(p); - if (idx-- == 0) { - cplen = tolen; - cpstr = p; - break; - } - } - if (*p == NUL) { // tostr is shorter than fromstr. - goto error; - } - break; - } - idx++; - } - - if (first && cpstr == in_str) { - // Check that fromstr and tostr have the same number of - // (multi-byte) characters. Done only once when a character - // of in_str doesn't appear in fromstr. - first = false; - int tolen; - for (const char *p = tostr; *p != NUL; p += tolen) { - tolen = utfc_ptr2len(p); - idx--; - } - if (idx != 0) { - goto error; - } - } - - ga_grow(&ga, cplen); - memmove((char *)ga.ga_data + ga.ga_len, cpstr, (size_t)cplen); - ga.ga_len += cplen; - - in_str += inlen; - } - - // add a terminating NUL - ga_append(&ga, NUL); - - rettv->vval.v_string = ga.ga_data; - return; -error: - semsg(_(e_invarg2), fromstr); - ga_clear(&ga); -} - -/// "trim({expr})" function -static void f_trim(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - char buf1[NUMBUFLEN]; - char buf2[NUMBUFLEN]; - const char *head = tv_get_string_buf_chk(&argvars[0], buf1); - const char *mask = NULL; - const char *prev; - const char *p; - int dir = 0; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - if (head == NULL) { - return; - } - - if (tv_check_for_opt_string_arg(argvars, 1) == FAIL) { - return; - } - - if (argvars[1].v_type == VAR_STRING) { - mask = tv_get_string_buf_chk(&argvars[1], buf2); - if (argvars[2].v_type != VAR_UNKNOWN) { - bool error = false; - // leading or trailing characters to trim - dir = (int)tv_get_number_chk(&argvars[2], &error); - if (error) { - return; - } - if (dir < 0 || dir > 2) { - semsg(_(e_invarg2), tv_get_string(&argvars[2])); - return; - } - } - } - - int c1; - if (dir == 0 || dir == 1) { - // Trim leading characters - while (*head != NUL) { - c1 = utf_ptr2char(head); - if (mask == NULL) { - if (c1 > ' ' && c1 != 0xa0) { - break; - } - } else { - for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char(p)) { - break; - } - } - if (*p == NUL) { - break; - } - } - MB_PTR_ADV(head); - } - } - - const char *tail = head + strlen(head); - if (dir == 0 || dir == 2) { - // Trim trailing characters - for (; tail > head; tail = prev) { - prev = tail; - MB_PTR_BACK(head, prev); - c1 = utf_ptr2char(prev); - if (mask == NULL) { - if (c1 > ' ' && c1 != 0xa0) { - break; - } - } else { - for (p = mask; *p != NUL; MB_PTR_ADV(p)) { - if (c1 == utf_ptr2char(p)) { - break; - } - } - if (*p == NUL) { - break; - } - } - } - } - rettv->vval.v_string = xstrnsave(head, (size_t)(tail - head)); -} - /// "type(expr)" function static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From 3b0df1780e2c8526bda5dead18ee7cc45925caba Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 26 Apr 2023 23:23:44 +0200 Subject: refactor: uncrustify Notable changes: replace all infinite loops to `while(true)` and remove `int` from `unsigned int`. --- src/nvim/eval/buffer.c | 2 +- src/nvim/eval/encode.c | 4 ++-- src/nvim/eval/funcs.c | 16 ++++++++-------- src/nvim/eval/typval.c | 2 +- src/nvim/eval/userfunc.c | 4 ++-- src/nvim/eval/vars.c | 6 +++--- 6 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index d9cc18a402..aad88619b7 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -172,7 +172,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ } // Default result is zero == OK. - for (;;) { + while (true) { if (lines->v_type == VAR_LIST) { // List argument, get next string. if (li == NULL) { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index b056a1784c..be0cf79e85 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -418,7 +418,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s ga_concat(gap, "v:null") #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - ga_concat(gap, ((num)? "v:true": "v:false")) + ga_concat(gap, ((num) ? "v:true" : "v:false")) #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) @@ -544,7 +544,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s #undef TYPVAL_ENCODE_CONV_BOOL #define TYPVAL_ENCODE_CONV_BOOL(tv, num) \ - ga_concat(gap, ((num)? "true": "false")) + ga_concat(gap, ((num) ? "true" : "false")) #undef TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER #define TYPVAL_ENCODE_CONV_UNSIGNED_NUMBER(tv, num) \ diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5c9d39b91f..91f78b8ed6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -643,7 +643,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool crlf = false; #else Channel *chan = find_channel(id); - bool crlf = (chan != NULL && chan->term) ? true: false; + bool crlf = (chan != NULL && chan->term) ? true : false; #endif if (argvars[1].v_type == VAR_BLOB) { @@ -4593,7 +4593,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; - for (;;) { + while (true) { if (l != NULL) { if (li == NULL) { match = false; @@ -4960,7 +4960,7 @@ static void msgpackparse_unpack_list(const list_T *const list, list_T *const ret } msgpack_unpacked unpacked; msgpack_unpacked_init(&unpacked); - do { + while (true) { if (!msgpack_unpacker_reserve_buffer(unpacker, IOSIZE)) { emsg(_(e_outofmem)); goto end; @@ -4990,7 +4990,7 @@ static void msgpackparse_unpack_list(const list_T *const list, list_T *const ret if (rlret == OK) { break; } - } while (true); + } end: msgpack_unpacker_free(unpacker); @@ -6026,8 +6026,8 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char *const buf = xmallocz(MAXPATHL); char *cpy; - for (;;) { - for (;;) { + while (true) { + while (true) { len = readlink(p, buf, MAXPATHL); if (len <= 0) { break; @@ -6409,7 +6409,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) int subpatnum; // Repeat until {skip} returns false. - for (;;) { + while (true) { subpatnum = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, 1, options, RE_SEARCH, &sia); // finding the first match again means there is no match where {skip} @@ -6989,7 +6989,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir pos_T foundpos; clearpos(&foundpos); char *pat = pat3; - for (;;) { + while (true) { searchit_arg_T sia = { .sa_stop_lnum = lnum_stop, .sa_tm = &tm, diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6556e274ab..cf355a22fa 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1042,7 +1042,7 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) if (sortinfo->item_compare_lc) { res = strcoll(p1, p2); } else { - res = sortinfo->item_compare_ic ? STRICMP(p1, p2): strcmp(p1, p2); + res = sortinfo->item_compare_ic ? STRICMP(p1, p2) : strcmp(p1, p2); } } else { double n1, n2; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 854a0732ab..0e22cf54cf 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2343,7 +2343,7 @@ void ex_function(exarg_T *eap) } // find extra arguments "range", "dict", "abort" and "closure" - for (;;) { + while (true) { p = skipwhite(p); if (strncmp(p, "range", 5) == 0) { flags |= FC_RANGE; @@ -2403,7 +2403,7 @@ void ex_function(exarg_T *eap) indent = 2; nesting = 0; - for (;;) { + while (true) { if (KeyTyped) { msg_scroll = true; saved_wait_return = false; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index d3ca2624eb..593ba9f6c3 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -220,7 +220,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) char *theline = NULL; list_T *l = tv_list_alloc(0); - for (;;) { + while (true) { int mi = 0; int ti = 0; @@ -502,7 +502,7 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon) const char *s; // "[var, var]": find the matching ']'. const char *p = arg; - for (;;) { + while (true) { p = skipwhite(p + 1); // skip whites after '[', ';' or ',' s = skip_var_one(p); if (s == p) { @@ -1012,7 +1012,7 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ // Delete a range of List items. listitem_T *const first_li = lp->ll_li; listitem_T *last_li = first_li; - for (;;) { + while (true) { listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li); if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, lp->ll_name, -- cgit From 9f29176033926b81553985deaba0ea162ca40215 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Apr 2023 00:01:22 +0800 Subject: vim-patch:9.0.1492: using uninitialized memory when argument is missing (#23351) Problem: Using uninitialized memory when argument is missing. Solution: Check there are sufficient arguments before the base. (closes vim/vim#12302) https://github.com/vim/vim/commit/b7f2270bab102d68f83a6300699b7f98efad81f2 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 91f78b8ed6..ebc34564e2 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -287,6 +287,9 @@ int call_internal_method(const char *const fname, const int argcount, typval_T * typval_T argv[MAX_FUNC_ARGS + 1]; const ptrdiff_t base_index = fdef->base_arg == BASE_LAST ? argcount : fdef->base_arg - 1; + if (argcount < base_index) { + return FCERR_TOOFEW; + } memcpy(argv, argvars, (size_t)base_index * sizeof(typval_T)); argv[base_index] = *basetv; memcpy(argv + base_index + 1, argvars + base_index, -- cgit From ff34c91194f9ab9d02808f2880029c38a4655eb5 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 17 Apr 2023 17:23:47 +0100 Subject: vim-patch:9.0.1330: handling new value of an option has a long "else if" chain Problem: Handling new value of an option has a long "else if" chain. Solution: Use a function pointer. (Yegappan Lakshmanan, closes vim/vim#12015) https://github.com/vim/vim/commit/af93691b53f38784efce0b93fe7644c44a7e382e --- src/nvim/eval/funcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ebc34564e2..f898063fb0 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7711,7 +7711,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr const int wo_spell_save = curwin->w_p_spell; if (!curwin->w_p_spell) { - did_set_spelllang(curwin); + parse_spelllang(curwin); curwin->w_p_spell = true; } @@ -7768,7 +7768,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr const int wo_spell_save = curwin->w_p_spell; if (!curwin->w_p_spell) { - did_set_spelllang(curwin); + parse_spelllang(curwin); curwin->w_p_spell = true; } -- cgit From 4bcf8c15b3079ca72d6557890b50b35565fcd577 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 29 Apr 2023 08:12:32 +0800 Subject: vim-patch:8.2.0578: heredoc for interfaces does not support "trim" Problem: Heredoc for interfaces does not support "trim". Solution: Update the script heredoc support to be same as the :let command. (Yegappan Lakshmanan, closes vim/vim#5916) https://github.com/vim/vim/commit/6c2b7b8055b96463f78abb70f58c4c6d6d4b9d55 --- src/nvim/eval/userfunc.c | 9 ++++++++- src/nvim/eval/vars.c | 19 +++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 0e22cf54cf..1f5a6eaec4 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2571,11 +2571,18 @@ void ex_function(exarg_T *eap) && (!ASCII_ISALPHA(p[2]) || p[2] == 's')))) { // ":python <<" continues until a dot, like ":append" p = skipwhite(arg + 2); + if (strncmp(p, "trim", 4) == 0) { + // Ignore leading white space. + p = skipwhite(p + 4); + heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); + } if (*p == NUL) { skip_until = xstrdup("."); } else { - skip_until = xstrdup(p); + skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p)); } + do_concat = false; + is_heredoc = true; } // Check for ":let v =<< [trim] EOF" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 593ba9f6c3..dee3867a5a 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -155,14 +155,19 @@ char *eval_all_expr_in_str(char *str) /// marker, then the leading indentation before the lines (matching the /// indentation in the 'cmd' line) is stripped. /// +/// When getting lines for an embedded script (e.g. python, lua, perl, ruby, +/// tcl, mzscheme), "script_get" is set to true. In this case, if the marker is +/// missing, then '.' is accepted as a marker. +/// /// @return a List with {lines} or NULL on failure. -static list_T *heredoc_get(exarg_T *eap, char *cmd) +list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) { char *marker; char *p; int marker_indent_len = 0; int text_indent_len = 0; char *text_indent = NULL; + char dot[] = "."; if (eap->getline == NULL) { emsg(_("E991: cannot use =<< here")); @@ -214,8 +219,14 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) return NULL; } } else { - emsg(_("E172: Missing marker")); - return NULL; + // When getting lines for an embedded script, if the marker is missing, + // accept '.' as the marker. + if (script_get) { + marker = dot; + } else { + emsg(_("E172: Missing marker")); + return NULL; + } } char *theline = NULL; @@ -353,7 +364,7 @@ void ex_let(exarg_T *eap) if (expr[0] == '=' && expr[1] == '<' && expr[2] == '<') { // HERE document - list_T *l = heredoc_get(eap, expr + 3); + list_T *l = heredoc_get(eap, expr + 3, false); if (l != NULL) { tv_list_set_ret(&rettv, l); if (!eap->skip) { -- cgit From 2eb1f62e29c54fe4d3cebcff388ea6c239313980 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 29 Apr 2023 08:50:04 +0800 Subject: vim-patch:8.2.0672: heredoc in scripts does not accept lower case marker Problem: Heredoc in scripts does not accept lower case marker. Solution: Allow lower case only in non-Vim scripts. (Ken Takata, closes vim/vim#6019) https://github.com/vim/vim/commit/6ab0953fefe31fef91e40752a675ceb60fc2fe03 --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index dee3867a5a..9a653db657 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -214,7 +214,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) return NULL; } *p = NUL; - if (islower((uint8_t)(*marker))) { + if (!script_get && islower((uint8_t)(*marker))) { emsg(_("E221: Marker cannot start with lower case letter")); return NULL; } -- cgit From 7b6d041baed712b071acfa8bb71727a5f5e27561 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 29 Apr 2023 09:23:31 +0800 Subject: fix(heredoc): allow missing end marker for scripts Also do not crash when getting heredoc fails. --- src/nvim/eval/vars.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9a653db657..de6c4bab60 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -163,7 +163,6 @@ char *eval_all_expr_in_str(char *str) list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) { char *marker; - char *p; int marker_indent_len = 0; int text_indent_len = 0; char *text_indent = NULL; @@ -187,7 +186,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) // The amount of indentation trimmed is the same as the indentation // of the first line after the :let command line. To find the end // marker the indent of the :let command line is trimmed. - p = *eap->cmdlinep; + char *p = *eap->cmdlinep; while (ascii_iswhite(*p)) { p++; marker_indent_len++; @@ -208,7 +207,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) // The marker is the next word. if (*cmd != NUL && *cmd != '"') { marker = skipwhite(cmd); - p = skiptowhite(marker); + char *p = skiptowhite(marker); if (*skipwhite(p) != NUL && *skipwhite(p) != '"') { semsg(_(e_trailing_arg), p); return NULL; @@ -238,7 +237,9 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) xfree(theline); theline = eap->getline(NUL, eap->cookie, 0, false); if (theline == NULL) { - semsg(_("E990: Missing end marker '%s'"), marker); + if (!script_get) { + semsg(_("E990: Missing end marker '%s'"), marker); + } break; } @@ -260,7 +261,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) if (text_indent_len == -1 && *theline != NUL) { // set the text indent from the first line. - p = theline; + char *p = theline; text_indent_len = 0; while (ascii_iswhite(*p)) { p++; -- cgit From bff3f4fa8bbadf7494bcf3098eee8da39cc2c436 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 3 May 2023 00:05:46 +0800 Subject: vim-patch:9.0.1505: error when heredoc content looks like heredoc (#23446) Problem: Error when heredoc content looks like heredoc. Solution: Handle curly expressions. (closes vim/vim#12325) https://github.com/vim/vim/commit/a93d9cdc74f70ca2c85781496ffae4ca738fcd88 --- src/nvim/eval/userfunc.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1f5a6eaec4..bfda2c4b9b 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2587,19 +2587,13 @@ void ex_function(exarg_T *eap) // Check for ":let v =<< [trim] EOF" // and ":let [a, b] =<< [trim] EOF" - arg = skipwhite(skiptowhite(p)); - if (*arg == '[') { - arg = vim_strchr(arg, ']'); - } - if (arg != NULL) { - arg = skipwhite(skiptowhite(arg)); - if (arg[0] == '=' - && arg[1] == '<' - && arg[2] == '<' - && (p[0] == 'l' - && p[1] == 'e' - && (!ASCII_ISALNUM(p[2]) - || (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) { + arg = p; + if (checkforcmd(&arg, "let", 2)) { + while (vim_strchr("$@&", *arg) != NULL) { + arg++; + } + arg = skipwhite(find_name_end(arg, NULL, NULL, FNE_INCL_BR)); + if (arg[0] == '=' && arg[1] == '<' && arg[2] == '<') { p = skipwhite(arg + 3); while (true) { if (strncmp(p, "trim", 4) == 0) { -- cgit From 1659cd15bebfd8553bb91f24d833789451705b03 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 13:54:55 +0800 Subject: vim-patch:8.2.0987: Vim9: cannot assign to [var; var] Problem: Vim9: cannot assign to [var; var]. Solution: Assign rest of items to a list. https://github.com/vim/vim/commit/9af78769eeae0318e07aa8b6af4d6e2244481ca7 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index cf355a22fa..297adf7f9c 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -765,6 +765,17 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) return OK; } +list_T *tv_list_slice(list_T *ol, int n1, int n2) +{ + list_T *l = tv_list_alloc(n2 - n1 + 1); + listitem_T *item = tv_list_find(ol, n1); + for (; n1 <= n2; n1++) { + tv_list_append_tv(l, TV_LIST_ITEM_TV(item)); + item = TV_LIST_ITEM_NEXT(rettv->vval.v_list, item); + } + return l; +} + typedef struct { char *s; char *tofree; -- cgit From f4043e290e10007e51596a489a5ef444e28e5de8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 14:03:32 +0800 Subject: vim-patch:8.2.1463: Vim9: list slice not supported yet Problem: Vim9: list slice not supported yet. Solution: Add support for list slicing. https://github.com/vim/vim/commit/ed5918771fcf9877d8445e74c62ab1ce6b8e28c1 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 45 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 297adf7f9c..ba1d60959a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -765,7 +765,7 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) return OK; } -list_T *tv_list_slice(list_T *ol, int n1, int n2) +static list_T *tv_list_slice(list_T *ol, int n1, int n2) { list_T *l = tv_list_alloc(n2 - n1 + 1); listitem_T *item = tv_list_find(ol, n1); @@ -776,6 +776,50 @@ list_T *tv_list_slice(list_T *ol, int n1, int n2) return l; } +int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typval_T *rettv, + bool verbose) +{ + int len = tv_list_len(rettv->vval.v_list); + int n1 = n1_arg; + int n2 = n2_arg; + + if (n1 < 0) { + n1 = len + n1; + } + if (n1 < 0 || n1 >= len) { + // For a range we allow invalid values and return an empty + // list. A list index out of range is an error. + if (!range) { + if (verbose) { + semsg(_(e_listidx), (int64_t)n1); + } + return FAIL; + } + n1 = len; + } + if (range) { + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len - 1; + } + if (n2 < 0 || n2 + 1 < n1) { + n2 = -1; + } + list_T *l = tv_list_slice(rettv->vval.v_list, n1, n2); + tv_clear(rettv); + tv_list_set_ret(rettv, l); + } else { + // copy the item to "var1" to avoid that freeing the list makes it + // invalid. + typval_T var1; + tv_copy(TV_LIST_ITEM_TV(tv_list_find(rettv->vval.v_list, (int)n1)), &var1); + tv_clear(rettv); + *rettv = var1; + } + return OK; +} + typedef struct { char *s; char *tofree; -- cgit From 7ac63906eae92b5d31fc7e380ef05b8bce73ad8b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 14:15:54 +0800 Subject: vim-patch:8.2.1466: Vim9: cannot index or slice a variable with type "any" Problem: Vim9: cannot index or slice a variable with type "any". Solution: Add runtime index and slice. https://github.com/vim/vim/commit/cc673e746ab98566556ff964d7a76f2fb46d7f84 Omit E1024 and E1062: Vim9 script only. Omit string_slice() and char_idx2byte(): Vim9 script only. Remove the first tv_is_luafunc() check because it always returns false. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ba1d60959a..8028688ac8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -795,7 +795,7 @@ int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typ } return FAIL; } - n1 = len; + n1 = n1 < 0 ? 0 : len; } if (range) { if (n2 < 0) { -- cgit From 47132823ab1c4f458c945df89d12e897d77db8a8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 16:12:52 +0800 Subject: vim-patch:8.2.3336: behavior of negative index in list change changed Problem: Behavior of negative index in list change changed. (Naruhiko Nishino) Solution: Only change it for Vim9 script. (closes vim/vim#8749) https://github.com/vim/vim/commit/92f05f21afdb8a43581554a252cb2fc050f9e03b Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8028688ac8..0b2be3074f 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -787,15 +787,15 @@ int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typ n1 = len + n1; } if (n1 < 0 || n1 >= len) { - // For a range we allow invalid values and return an empty - // list. A list index out of range is an error. + // For a range we allow invalid values and return an empty list. + // A list index out of range is an error. if (!range) { if (verbose) { semsg(_(e_listidx), (int64_t)n1); } return FAIL; } - n1 = n1 < 0 ? 0 : len; + n1 = len; } if (range) { if (n2 < 0) { -- cgit From b441dafdf53e367c7d43177274bd781c5c73e6e0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 16:46:38 +0800 Subject: vim-patch:8.2.2344: using inclusive index for slice is not always desired Problem: Using inclusive index for slice is not always desired. Solution: Add the slice() method, which has an exclusive index. (closes vim/vim#7408) https://github.com/vim/vim/commit/6601b62943a19d4f8818c3638440663d67a17b6a Cherry-pick a line in docs added later. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 0b2be3074f..794debf771 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -765,10 +765,10 @@ int tv_list_concat(list_T *const l1, list_T *const l2, typval_T *const tv) return OK; } -static list_T *tv_list_slice(list_T *ol, int n1, int n2) +static list_T *tv_list_slice(list_T *ol, varnumber_T n1, varnumber_T n2) { list_T *l = tv_list_alloc(n2 - n1 + 1); - listitem_T *item = tv_list_find(ol, n1); + listitem_T *item = tv_list_find(ol, (int)n1); for (; n1 <= n2; n1++) { tv_list_append_tv(l, TV_LIST_ITEM_TV(item)); item = TV_LIST_ITEM_NEXT(rettv->vval.v_list, item); @@ -776,12 +776,12 @@ static list_T *tv_list_slice(list_T *ol, int n1, int n2) return l; } -int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typval_T *rettv, - bool verbose) +int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumber_T n2_arg, + bool exclusive, typval_T *rettv, bool verbose) { int len = tv_list_len(rettv->vval.v_list); - int n1 = n1_arg; - int n2 = n2_arg; + varnumber_T n1 = n1_arg; + varnumber_T n2 = n2_arg; if (n1 < 0) { n1 = len + n1; @@ -801,7 +801,10 @@ int tv_list_slice_or_index(list_T *list, bool range, int n1_arg, int n2_arg, typ if (n2 < 0) { n2 = len + n2; } else if (n2 >= len) { - n2 = len - 1; + n2 = len - (exclusive ? 0 : 1); + } + if (exclusive) { + n2--; } if (n2 < 0 || n2 + 1 < n1) { n2 = -1; @@ -2800,14 +2803,14 @@ int tv_blob_check_range(int bloblen, varnumber_T n1, varnumber_T n2, bool quiet) /// Set bytes "n1" to "n2" (inclusive) in "dest" to the value of "src". /// Caller must make sure "src" is a blob. /// Returns FAIL if the number of bytes does not match. -int tv_blob_set_range(blob_T *dest, int n1, int n2, typval_T *src) +int tv_blob_set_range(blob_T *dest, varnumber_T n1, varnumber_T n2, typval_T *src) { if (n2 - n1 + 1 != tv_blob_len(src->vval.v_blob)) { emsg(_("E972: Blob value does not have the right number of bytes")); return FAIL; } - for (int il = n1, ir = 0; il <= n2; il++) { + for (int il = (int)n1, ir = 0; il <= (int)n2; il++) { tv_blob_set(dest, il, tv_blob_get(src->vval.v_blob, ir++)); } return OK; -- cgit From 8752da89b83281426e81e5c4a392308848f4bfb6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 17:51:14 +0800 Subject: vim-patch:8.2.2756: Vim9: blob index and slice not implemented yet Problem: Vim9: blob index and slice not implemented yet. Solution: Implement blob index and slice. https://github.com/vim/vim/commit/cfc3023cb6ce5aaec13f49bc4b821feb05e3fb03 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 794debf771..8b51500e18 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2776,6 +2776,60 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } +int tv_blob_slice_or_index(const blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, + bool exclusive, typval_T *rettv) +{ + int len = tv_blob_len(rettv->vval.v_blob); + if (is_range) { + // The resulting variable is a sub-blob. If the indexes + // are out of range the result is empty. + if (n1 < 0) { + n1 = len + n1; + if (n1 < 0) { + n1 = 0; + } + } + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len - (exclusive ? 0 : 1); + } + if (exclusive) { + n2--; + } + if (n1 >= len || n2 < 0 || n1 > n2) { + tv_clear(rettv); + rettv->v_type = VAR_BLOB; + rettv->vval.v_blob = NULL; + } else { + blob_T *const new_blob = tv_blob_alloc(); + ga_grow(&new_blob->bv_ga, (int)(n2 - n1 + 1)); + new_blob->bv_ga.ga_len = (int)(n2 - n1 + 1); + for (int i = (int)n1; i <= (int)n2; i++) { + tv_blob_set(new_blob, i - (int)n1, tv_blob_get(rettv->vval.v_blob, i)); + } + tv_clear(rettv); + tv_blob_set_ret(rettv, new_blob); + } + } else { + // The resulting variable is a byte value. + // If the index is too big or negative that is an error. + if (n1 < 0) { + n1 = len + n1; + } + if (n1 < len && n1 >= 0) { + const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)n1); + tv_clear(rettv); + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = v; + } else { + semsg(_(e_blobidx), (int64_t)n1); + return FAIL; + } + } + return OK; +} + /// Check if "n1" is a valid index for a blob with length "bloblen". int tv_blob_check_index(int bloblen, varnumber_T n1, bool quiet) { -- cgit From fe7cdc7cc0037bb41bd940bee7818a5235ffaa79 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 19:07:54 +0800 Subject: vim-patch:9.0.0601: too much indent (#23472) Problem: Too much indent. Solution: Return out early from a funtion. (Yegappan Lakshmanan, close vim/vim#11238) https://github.com/vim/vim/commit/368aa6908862874fdb901c534ee99033ac977e4a Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 109 +++++++++++++++++++++++++++++-------------------- 1 file changed, 64 insertions(+), 45 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8b51500e18..5f44cceb91 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2776,60 +2776,79 @@ bool tv_blob_equal(const blob_T *const b1, const blob_T *const b2) return true; } -int tv_blob_slice_or_index(const blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, - bool exclusive, typval_T *rettv) +/// Returns a slice of "blob" from index "n1" to "n2" in "rettv". The length of +/// the blob is "len". Returns an empty blob if the indexes are out of range. +static int tv_blob_slice(const blob_T *blob, int len, varnumber_T n1, varnumber_T n2, + bool exclusive, typval_T *rettv) { - int len = tv_blob_len(rettv->vval.v_blob); - if (is_range) { - // The resulting variable is a sub-blob. If the indexes - // are out of range the result is empty. + // The resulting variable is a sub-blob. If the indexes + // are out of range the result is empty. + if (n1 < 0) { + n1 = len + n1; if (n1 < 0) { - n1 = len + n1; - if (n1 < 0) { - n1 = 0; - } - } - if (n2 < 0) { - n2 = len + n2; - } else if (n2 >= len) { - n2 = len - (exclusive ? 0 : 1); - } - if (exclusive) { - n2--; - } - if (n1 >= len || n2 < 0 || n1 > n2) { - tv_clear(rettv); - rettv->v_type = VAR_BLOB; - rettv->vval.v_blob = NULL; - } else { - blob_T *const new_blob = tv_blob_alloc(); - ga_grow(&new_blob->bv_ga, (int)(n2 - n1 + 1)); - new_blob->bv_ga.ga_len = (int)(n2 - n1 + 1); - for (int i = (int)n1; i <= (int)n2; i++) { - tv_blob_set(new_blob, i - (int)n1, tv_blob_get(rettv->vval.v_blob, i)); - } - tv_clear(rettv); - tv_blob_set_ret(rettv, new_blob); + n1 = 0; } + } + if (n2 < 0) { + n2 = len + n2; + } else if (n2 >= len) { + n2 = len - (exclusive ? 0 : 1); + } + if (exclusive) { + n2--; + } + if (n1 >= len || n2 < 0 || n1 > n2) { + tv_clear(rettv); + rettv->v_type = VAR_BLOB; + rettv->vval.v_blob = NULL; } else { - // The resulting variable is a byte value. - // If the index is too big or negative that is an error. - if (n1 < 0) { - n1 = len + n1; - } - if (n1 < len && n1 >= 0) { - const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)n1); - tv_clear(rettv); - rettv->v_type = VAR_NUMBER; - rettv->vval.v_number = v; - } else { - semsg(_(e_blobidx), (int64_t)n1); - return FAIL; + blob_T *const new_blob = tv_blob_alloc(); + ga_grow(&new_blob->bv_ga, (int)(n2 - n1 + 1)); + new_blob->bv_ga.ga_len = (int)(n2 - n1 + 1); + for (int i = (int)n1; i <= (int)n2; i++) { + tv_blob_set(new_blob, i - (int)n1, tv_blob_get(rettv->vval.v_blob, i)); } + tv_clear(rettv); + tv_blob_set_ret(rettv, new_blob); + } + + return OK; +} + +/// Return the byte value in "blob" at index "idx" in "rettv". If the index is +/// too big or negative that is an error. The length of the blob is "len". +static int tv_blob_index(const blob_T *blob, int len, varnumber_T idx, typval_T *rettv) +{ + // The resulting variable is a byte value. + // If the index is too big or negative that is an error. + if (idx < 0) { + idx = len + idx; + } + if (idx < len && idx >= 0) { + const int v = (int)tv_blob_get(rettv->vval.v_blob, (int)idx); + tv_clear(rettv); + rettv->v_type = VAR_NUMBER; + rettv->vval.v_number = v; + } else { + semsg(_(e_blobidx), idx); + return FAIL; } + return OK; } +int tv_blob_slice_or_index(const blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2, + bool exclusive, typval_T *rettv) +{ + int len = tv_blob_len(rettv->vval.v_blob); + + if (is_range) { + return tv_blob_slice(blob, len, n1, n2, exclusive, rettv); + } else { + return tv_blob_index(blob, len, n1, rettv); + } +} + /// Check if "n1" is a valid index for a blob with length "bloblen". int tv_blob_check_index(int bloblen, varnumber_T n1, bool quiet) { -- cgit From b16729f8162ce21a52f079c3849f5011b768d0ce Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 4 May 2023 23:17:43 +0800 Subject: vim-patch:8.2.1697: inconsistent capitalization of error messages (#23476) Problem: Inconsistent capitalization of error messages. Solution: Always start with a capital. https://github.com/vim/vim/commit/7707228aace9aff16434edf5377a354c6ad07316 Most of these errors are Vim9 script only. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index bfda2c4b9b..fbb5e8d10c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -79,6 +79,8 @@ static const char *e_funcref = N_("E718: Funcref required"); static const char *e_nofunc = N_("E130: Unknown function: %s"); static const char e_function_list_was_modified[] = N_("E454: Function list was modified"); +static const char e_function_nesting_too_deep[] + = N_("E1058: Function nesting too deep"); static const char e_no_white_space_allowed_before_str_str[] = N_("E1068: No white space allowed before '%s': %s"); static const char e_missing_heredoc_end_marker_str[] @@ -2528,7 +2530,7 @@ void ex_function(exarg_T *eap) xfree(trans_function_name(&p, true, 0, NULL, NULL)); if (*skipwhite(p) == '(') { if (nesting == MAX_FUNC_NESTING - 1) { - emsg(_("E1058: function nesting too deep")); + emsg(_(e_function_nesting_too_deep)); } else { nesting++; indent += 2; -- cgit From f6299e9d6e13935cc67c2fab16c1a5f6dbc515f3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 06:22:18 +0800 Subject: vim-patch:8.2.3221: Vim9: argument types are not checked at compile time (#23480) Problem: Vim9: argument types are not checked at compile time. Solution: Add several more type checks. (Yegappan Lakshmanan, closes vim/vim#8632) https://github.com/vim/vim/commit/a764e73d4ffc5d046807c757eaacb9b0a5408152 Cherry-pick test_assert.vim change from patch 8.2.3229. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5f44cceb91..79f514bc71 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -52,6 +52,8 @@ static const char e_list_required_for_argument_nr[] = N_("E1211: List required for argument %d"); static const char e_bool_required_for_argument_nr[] = N_("E1212: Bool required for argument %d"); +static const char e_string_or_number_required_for_argument_nr[] + = N_("E1220: String or Number required for argument %d"); static const char e_string_or_list_required_for_argument_nr[] = N_("E1222: String or List required for argument %d"); static const char e_list_or_blob_required_for_argument_nr[] @@ -4160,6 +4162,17 @@ int tv_check_for_opt_number_arg(const typval_T *const args, const int idx) || tv_check_for_number_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a float or a number. +int tv_check_for_float_or_nr_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER) { + semsg(_(e_number_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Give an error and return FAIL unless "args[idx]" is a bool. int tv_check_for_bool_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE @@ -4240,6 +4253,18 @@ int tv_check_for_opt_dict_arg(const typval_T *const args, const int idx) || tv_check_for_dict_arg(args, idx) != FAIL) ? OK : FAIL; } +/// Give an error and return FAIL unless "args[idx]" is a string or +/// a number. +int tv_check_for_string_or_number_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_NUMBER) { + semsg(_(e_string_or_number_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + /// Give an error and return FAIL unless "args[idx]" is a string or a list. int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE @@ -4251,6 +4276,14 @@ int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) return OK; } +/// Check for an optional string or list argument at 'idx' +int tv_check_for_opt_string_or_list_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + return (args[idx].v_type == VAR_UNKNOWN + || tv_check_for_string_or_list_arg(args, idx) != FAIL) ? OK : FAIL; +} + /// Give an error and return FAIL unless "args[idx]" is a string /// or a function reference. int tv_check_for_string_or_func_arg(const typval_T *const args, const int idx) -- cgit From 75119fcc86e055895af824f7fdbba2f42c1cbbe8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 07:02:43 +0800 Subject: vim-patch:8.2.3135: Vim9: builtin function arguments not checked at compile time Problem: Vim9: builtin function arguments not checked at compile time. Solution: Add more type checks. (Yegappan Lakshmanan, closes vim/vim#8539) https://github.com/vim/vim/commit/5b73992d8f82be7ac4b6f46c17f53ffb9640e5fa Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 79f514bc71..b4aa0bdeb0 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3933,15 +3933,15 @@ bool tv_check_num(const typval_T *const tv) return false; } -#define FUNC_ERROR "E729: using Funcref as a String" +#define FUNC_ERROR "E729: Using a Funcref as a String" static const char *const str_errors[] = { [VAR_PARTIAL]= N_(FUNC_ERROR), [VAR_FUNC]= N_(FUNC_ERROR), - [VAR_LIST]= N_("E730: using List as a String"), - [VAR_DICT]= N_("E731: using Dictionary as a String"), + [VAR_LIST]= N_("E730: Using a List as a String"), + [VAR_DICT]= N_("E731: Using a Dictionary as a String"), [VAR_FLOAT]= e_float_as_string, - [VAR_BLOB]= N_("E976: using Blob as a String"), + [VAR_BLOB]= N_("E976: Using a Blob as a String"), [VAR_UNKNOWN]= e_inval_string, }; -- cgit From 88cfb49bee3c9102082c7010acb92244e4ad1348 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 07:14:39 +0800 Subject: vim-patch:8.2.4890: inconsistent capitalization in error messages Problem: Inconsistent capitalization in error messages. Solution: Make capitalization consistent. (Doug Kearns) https://github.com/vim/vim/commit/cf030578b26460643dca4a40e7f2e3bc19c749aa Co-authored-by: Bram Moolenaar --- src/nvim/eval/executor.c | 3 ++- src/nvim/eval/executor.h | 2 +- src/nvim/eval/funcs.c | 10 ++++++---- src/nvim/eval/typval.c | 18 +++++++++++------- src/nvim/eval/vars.c | 8 ++++++-- 5 files changed, 26 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 9caea2fef1..7668fb129f 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -20,7 +20,8 @@ # include "eval/executor.c.generated.h" // IWYU pragma: export #endif -char *e_listidx = N_("E684: list index out of range: %" PRId64); +char *e_list_index_out_of_range_nr + = N_("E684: List index out of range: %" PRId64); /// Handle tv1 += tv2, -=, *=, /=, %=, .= /// diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h index 3d789f76a5..42abf77f4a 100644 --- a/src/nvim/eval/executor.h +++ b/src/nvim/eval/executor.h @@ -3,7 +3,7 @@ #include "nvim/eval/typval.h" -extern char *e_listidx; +extern char *e_list_index_out_of_range_nr; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/executor.h.generated.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f898063fb0..927c1b3d5c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -148,6 +148,8 @@ PRAGMA_DIAG_POP static const char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static const char *e_invalwindow = N_("E957: Invalid window number"); +static const char e_invalid_submatch_number_nr[] + = N_("E935: Invalid submatch number: %d"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); static const char e_missing_function_argument[] = N_("E1132: Missing function argument"); @@ -928,7 +930,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!error) { li = tv_list_find(l, (int)idx); if (li == NULL) { - semsg(_(e_listidx), idx); + semsg(_(e_list_index_out_of_range_nr), idx); } } } @@ -1902,7 +1904,7 @@ static void extend(typval_T *argvars, typval_T *rettv, char *arg_errmsg, bool is } else { item = tv_list_find(l1, (int)before); if (item == NULL) { - semsg(_(e_listidx), (int64_t)before); + semsg(_(e_list_index_out_of_range_nr), (int64_t)before); return; } } @@ -3729,7 +3731,7 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (before != tv_list_len(l)) { item = tv_list_find(l, (int)before); if (item == NULL) { - semsg(_(e_listidx), before); + semsg(_(e_list_index_out_of_range_nr), before); l = NULL; } } @@ -8027,7 +8029,7 @@ static void f_submatch(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (no < 0 || no >= NSUBEXP) { - semsg(_("E935: invalid submatch number: %d"), no); + semsg(_(e_invalid_submatch_number_nr), no); return; } int retList = 0; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index b4aa0bdeb0..5f0c082ada 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -40,6 +40,10 @@ # include "eval/typval.c.generated.h" #endif +static const char e_variable_nested_too_deep_for_unlock[] + = N_("E743: Variable nested too deep for (un)lock"); +static const char e_using_invalid_value_as_string[] + = N_("E908: Using an invalid value as a String"); static const char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); static const char e_non_empty_string_required_for_argument_nr[] @@ -793,7 +797,7 @@ int tv_list_slice_or_index(list_T *list, bool range, varnumber_T n1_arg, varnumb // A list index out of range is an error. if (!range) { if (verbose) { - semsg(_(e_listidx), (int64_t)n1); + semsg(_(e_list_index_out_of_range_nr), (int64_t)n1); } return FAIL; } @@ -987,7 +991,7 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) if (error) { // Type error: do nothing, errmsg already given. } else if ((item = tv_list_find(l, (int)idx)) == NULL) { - semsg(_(e_listidx), idx); + semsg(_(e_list_index_out_of_range_nr), idx); } else { if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. @@ -1001,7 +1005,7 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) if (error) { // Type error: do nothing. } else if ((item2 = tv_list_find(l, (int)end)) == NULL) { - semsg(_(e_listidx), end); + semsg(_(e_list_index_out_of_range_nr), end); } else { int cnt = 0; @@ -1575,7 +1579,7 @@ const char *tv_list_find_str(list_T *const l, const int n) { const listitem_T *const li = tv_list_find(l, n); if (li == NULL) { - semsg(_(e_listidx), (int64_t)n); + semsg(_(e_list_index_out_of_range_nr), (int64_t)n); return NULL; } return tv_get_string(TV_LIST_ITEM_TV(li)); @@ -3583,7 +3587,7 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const boo static int recurse = 0; if (recurse >= DICT_MAXNEST) { - emsg(_("E743: variable nested too deep for (un)lock")); + emsg(_(e_variable_nested_too_deep_for_unlock)); return; } if (deep == 0) { @@ -3940,9 +3944,9 @@ static const char *const str_errors[] = { [VAR_FUNC]= N_(FUNC_ERROR), [VAR_LIST]= N_("E730: Using a List as a String"), [VAR_DICT]= N_("E731: Using a Dictionary as a String"), - [VAR_FLOAT]= e_float_as_string, + [VAR_FLOAT]= e_using_float_as_string, [VAR_BLOB]= N_("E976: Using a Blob as a String"), - [VAR_UNKNOWN]= e_inval_string, + [VAR_UNKNOWN]= e_using_invalid_value_as_string, }; #undef FUNC_ERROR diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index de6c4bab60..64177d13e8 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -52,6 +52,10 @@ static const char *e_letunexp = N_("E18: Unexpected characters in :let"); static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); +static const char e_setting_str_to_value_with_wrong_type[] + = N_("E963: Setting %s to value with wrong type"); +static const char e_cannot_use_heredoc_here[] + = N_("E991: Cannot use =<< here"); /// Evaluate one Vim expression {expr} in string "p" and append the /// resulting string to "gap". "p" points to the opening "{". @@ -169,7 +173,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) char dot[] = "."; if (eap->getline == NULL) { - emsg(_("E991: cannot use =<< here")); + emsg(_(e_cannot_use_heredoc_here)); return NULL; } @@ -1457,7 +1461,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, } return; } else if (v->di_tv.v_type != tv->v_type) { - semsg(_("E963: setting %s to value with wrong type"), name); + semsg(_(e_setting_str_to_value_with_wrong_type), name); return; } } -- cgit From 050b24cbccbe6e08f31fd33a854b91f7e8920834 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 5 May 2023 12:40:31 +0800 Subject: vim-patch:9.0.0543: insufficient testing for assert and test functions Problem: Insufficient testing for assert and test functions. Solution: Add a few more tests. (Yegappan Lakshmanan, closes vim/vim#11190) https://github.com/vim/vim/commit/e24b5e0b0f5ab015215ef2761baa98ccb1ba8606 Cherry-pick E1219 from patch 8.2.3229. Cherry-pick test_assert.vim change from patch 9.0.0491. Cherry-pick the whole Test_refcount() function and skip it. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5f0c082ada..5755178b18 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -56,6 +56,8 @@ static const char e_list_required_for_argument_nr[] = N_("E1211: List required for argument %d"); static const char e_bool_required_for_argument_nr[] = N_("E1212: Bool required for argument %d"); +static const char e_float_or_number_required_for_argument_nr[] + = N_("E1219: Float or Number required for argument %d"); static const char e_string_or_number_required_for_argument_nr[] = N_("E1220: String or Number required for argument %d"); static const char e_string_or_list_required_for_argument_nr[] @@ -4171,7 +4173,7 @@ int tv_check_for_float_or_nr_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { if (args[idx].v_type != VAR_FLOAT && args[idx].v_type != VAR_NUMBER) { - semsg(_(e_number_required_for_argument_nr), idx + 1); + semsg(_(e_float_or_number_required_for_argument_nr), idx + 1); return FAIL; } return OK; -- cgit From e8661133c533345e8d83a38b077e45922988fa90 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 6 May 2023 09:34:29 +0800 Subject: vim-patch:9.0.0904: various comment and indent flaws (#23498) Problem: Various comment and indent flaws. Solution: Improve comments and indenting. https://github.com/vim/vim/commit/88456cd3c49a3dd1fda17cf350daa9b8216b1aa6 Omit test_function_lists.vim change as that file is likely not applicable to Nvim due to the existence of Nvim-only functions. Co-authored-by: Bram Moolenaar --- src/nvim/eval/window.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 9976c56879..30c295de46 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -98,6 +98,7 @@ win_T *win_id2wp(int id) } /// Return the window and tab pointer of window "id". +/// Returns NULL when not found. win_T *win_id2wp_tp(int id, tabpage_T **tpp) { FOR_ALL_TAB_WINDOWS(tp, wp) { -- cgit From c2441a8fb950b23088f08db4ceb10c0d25e613d6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 8 May 2023 10:24:44 +0800 Subject: vim-patch:8.2.4073: Coverity warns for using NULL pointer Problem: Coverity warns for using NULL pointer. Solution: Bail out when running out of memory. Check for running over end of a string. https://github.com/vim/vim/commit/54598066ca4cfaf0761aedf47e4ba9844674791e Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index fbb5e8d10c..11ed537210 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -467,12 +467,10 @@ char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, b /// @param name function name void emsg_funcname(const char *errmsg, const char *name) { - char *p; + char *p = (char *)name; - if ((uint8_t)(*name) == K_SPECIAL) { + if ((uint8_t)name[0] == K_SPECIAL && name[1] != NUL && name[2] != NUL) { p = concat_str("", name + 3); - } else { - p = (char *)name; } semsg(_(errmsg), p); @@ -1863,8 +1861,7 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part // Check for hard coded : already translated function ID (from a user // command). - if ((unsigned char)(*pp)[0] == K_SPECIAL && (unsigned char)(*pp)[1] == KS_EXTRA - && (*pp)[2] == KE_SNR) { + if ((uint8_t)(*pp)[0] == K_SPECIAL && (uint8_t)(*pp)[1] == KS_EXTRA && (*pp)[2] == KE_SNR) { *pp += 3; len = get_id_len((const char **)pp) + 3; return xmemdupz(start, (size_t)len); @@ -2232,6 +2229,10 @@ void ex_function(exarg_T *eap) eap->skip = true; } + if (name == NULL) { + goto ret_free; + } + // An error in a function call during evaluation of an expression in magic // braces should not cause the function not to be defined. saved_did_emsg = did_emsg; -- cgit From 03828536fa14cbbc39e3e3a182ad9b7901da5da7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 8 May 2023 11:10:13 +0800 Subject: vim-patch:8.2.4075: test failures Problem: Test failures. Solution: Change check for NULL pointer. https://github.com/vim/vim/commit/78a70533c3707aa50cbf998c7807221945aa9787 :export is N/A. Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 11ed537210..7e20a298dd 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2137,7 +2137,6 @@ void ex_function(exarg_T *eap) char *theline; char *line_to_free = NULL; char c; - int saved_did_emsg; bool saved_wait_return = need_wait_return; char *name = NULL; char *p; @@ -2229,13 +2228,9 @@ void ex_function(exarg_T *eap) eap->skip = true; } - if (name == NULL) { - goto ret_free; - } - // An error in a function call during evaluation of an expression in magic // braces should not cause the function not to be defined. - saved_did_emsg = did_emsg; + const int saved_did_emsg = did_emsg; did_emsg = false; // -- cgit From d745433817499c34ccf230469417fb0ea29b7ab9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 8 May 2023 22:40:18 +0800 Subject: vim-patch:9.0.1522: some functions give two error messages Problem: Some functions give two error messages. Solution: Do not give a second error message. (closes vim/vim#12352) https://github.com/vim/vim/commit/e4098457ab9c94225b1b0e3c5e06b82b75587971 It seems that tv_get_bool() is actually not exactly the same as tv_get_number(), so change it to a function instead. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 22 ++++++++++++++++++++++ src/nvim/eval/typval.h | 4 ---- 2 files changed, 22 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5755178b18..cb8f8ce44d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2166,6 +2166,16 @@ varnumber_T tv_dict_get_number_def(const dict_T *const d, const char *const key, return tv_get_number(&di->di_tv); } +varnumber_T tv_dict_get_bool(const dict_T *const d, const char *const key, const int def) + FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + dictitem_T *const di = tv_dict_find(d, key, -1); + if (di == NULL) { + return def; + } + return tv_get_bool(&di->di_tv); +} + /// Converts a dict to an environment char **tv_dict_to_env(dict_T *denv) { @@ -4049,6 +4059,18 @@ varnumber_T tv_get_number_chk(const typval_T *const tv, bool *const ret_error) return (ret_error == NULL ? -1 : 0); } +varnumber_T tv_get_bool(const typval_T *const tv) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT +{ + return tv_get_number_chk(tv, NULL); +} + +varnumber_T tv_get_bool_chk(const typval_T *const tv, bool *const ret_error) + FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(1) +{ + return tv_get_number_chk(tv, ret_error); +} + /// Get the line number from VimL object /// /// @param[in] tv Object to get value from. Is expected to be a number or diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 84e4067f9d..767fd706b3 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -567,8 +567,4 @@ EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE); # include "eval/typval.h.generated.h" #endif -#define tv_get_bool tv_get_number -#define tv_get_bool_chk tv_get_number_chk -#define tv_dict_get_bool tv_dict_get_number_def - #endif // NVIM_EVAL_TYPVAL_H -- cgit From 6a273af10517d1f7e4ea85635f1d25a9158adeb5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 13 May 2023 10:40:53 +0800 Subject: refactor: remove typval.h from most header files (#23601) Because typval_defs.h is enough for most of them. --- src/nvim/eval/decode.h | 4 ++-- src/nvim/eval/executor.h | 2 +- src/nvim/eval/funcs.h | 1 - src/nvim/eval/gc.h | 1 - src/nvim/eval/typval_encode.h | 2 +- src/nvim/eval/userfunc.h | 1 - 6 files changed, 4 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index f1be5a1f69..7455130221 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -4,8 +4,8 @@ #include #include -#include "nvim/eval/typval.h" -#include "nvim/globals.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/types.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h index 42abf77f4a..e8bf147245 100644 --- a/src/nvim/eval/executor.h +++ b/src/nvim/eval/executor.h @@ -1,7 +1,7 @@ #ifndef NVIM_EVAL_EXECUTOR_H #define NVIM_EVAL_EXECUTOR_H -#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" extern char *e_list_index_out_of_range_nr; diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 1ae031a952..65a95196de 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -6,7 +6,6 @@ #include "nvim/api/private/dispatch.h" #include "nvim/buffer_defs.h" -#include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/types.h" diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h index 3185750c3b..66e959ced5 100644 --- a/src/nvim/eval/gc.h +++ b/src/nvim/eval/gc.h @@ -1,7 +1,6 @@ #ifndef NVIM_EVAL_GC_H #define NVIM_EVAL_GC_H -#include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" extern dict_T *gc_first_dict; diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 2f19144da3..171b0417d0 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -11,7 +11,7 @@ #include #include "klib/kvec.h" -#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" /// Type of the stack entry diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 4a98afb00e..562c549b4b 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -5,7 +5,6 @@ #include #include "nvim/eval.h" -#include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" #include "nvim/garray.h" -- cgit From d36dd2bae8e899b40cc21603e600a5046213bc36 Mon Sep 17 00:00:00 2001 From: ii14 <59243201+ii14@users.noreply.github.com> Date: Tue, 16 May 2023 05:33:03 +0200 Subject: refactor: use xstrl{cpy,cat} on IObuff (#23648) Replace usage of STR{CPY,CAT} with xstrl{cpy,cat} when using on IObuff Co-authored-by: ii14 --- src/nvim/eval/userfunc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 7e20a298dd..a52b8d3f18 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2892,9 +2892,9 @@ char *get_user_func_name(expand_T *xp, int idx) cat_func_name(IObuff, IOSIZE, fp); if (xp->xp_context != EXPAND_USER_FUNC) { - STRCAT(IObuff, "("); + xstrlcat(IObuff, "(", IOSIZE); if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) { - STRCAT(IObuff, ")"); + xstrlcat(IObuff, ")", IOSIZE); } } return IObuff; @@ -3505,7 +3505,7 @@ char *get_return_cmd(void *rettv) s = ""; } - STRCPY(IObuff, ":return "); + xstrlcpy(IObuff, ":return ", IOSIZE); xstrlcpy(IObuff + 8, s, IOSIZE - 8); if (strlen(s) + 8 >= IOSIZE) { STRCPY(IObuff + IOSIZE - 4, "..."); -- cgit From c48f94d1f30056272ed030ad3f4529055ac07853 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 28 May 2023 16:34:47 +0200 Subject: build: remove LOG_LIST_ACTIONS option and related code It has not been used for a long time and the likelihood of it still working is low. --- src/nvim/eval/typval.c | 80 --------------------------------------------- src/nvim/eval/typval.h | 74 ----------------------------------------- src/nvim/eval/typval_defs.h | 21 ------------ 3 files changed, 175 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index cb8f8ce44d..42e9dc8f03 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -82,70 +82,6 @@ bool tv_in_free_unref_items = false; const char *const tv_empty_string = ""; //{{{1 Lists -//{{{2 List log -#ifdef LOG_LIST_ACTIONS -ListLog *list_log_first = NULL; -ListLog *list_log_last = NULL; - -/// Write list log to the given file -/// -/// @param[in] fname File to write log to. Will be appended to if already -/// present. -void list_write_log(const char *const fname) - FUNC_ATTR_NONNULL_ALL -{ - FileDescriptor fp; - const int fo_ret = file_open(&fp, fname, kFileCreate|kFileAppend, 0600); - if (fo_ret != 0) { - semsg(_("E5142: Failed to open file %s: %s"), fname, os_strerror(fo_ret)); - return; - } - for (ListLog *chunk = list_log_first; chunk != NULL;) { - for (size_t i = 0; i < chunk->size; i++) { - char buf[10 + 1 + ((16 + 3) * 3) + (8 + 2) + 2]; - // act : hex " c:" len "[]" "\n\0" - const ListLogEntry entry = chunk->entries[i]; - const size_t snp_len = (size_t)snprintf(buf, sizeof(buf), - "%-10.10s: l:%016" PRIxPTR "[%08d] 1:%016" PRIxPTR " 2:%016" PRIxPTR - "\n", - entry.action, entry.l, entry.len, entry.li1, - entry.li2); - assert(snp_len + 1 == sizeof(buf)); - const ptrdiff_t fw_ret = file_write(&fp, buf, snp_len); - if (fw_ret != (ptrdiff_t)snp_len) { - assert(fw_ret < 0); - if (i) { - memmove(chunk->entries, chunk->entries + i, - sizeof(chunk->entries[0]) * (chunk->size - i)); - chunk->size -= i; - } - semsg(_("E5143: Failed to write to file %s: %s"), - fname, os_strerror((int)fw_ret)); - return; - } - } - list_log_first = chunk->next; - xfree(chunk); - chunk = list_log_first; - } - const int fc_ret = file_close(&fp, true); - if (fc_ret != 0) { - semsg(_("E5144: Failed to close file %s: %s"), fname, os_strerror(fc_ret)); - } -} - -# ifdef EXITFREE -/// Free list log -void list_free_log(void) -{ - for (ListLog *chunk = list_log_first; chunk != NULL;) { - list_log_first = chunk->next; - xfree(chunk); - chunk = list_log_first; - } -} -# endif -#endif //{{{2 List item /// Allocate a list item @@ -252,7 +188,6 @@ list_T *tv_list_alloc(const ptrdiff_t len) list->lv_used_prev = NULL; list->lv_used_next = gc_first_list; gc_first_list = list; - list_log(list, NULL, (void *)(uintptr_t)len, "alloc"); list->lua_table_ref = LUA_NOREF; return list; } @@ -283,8 +218,6 @@ void tv_list_init_static10(staticList10_T *const sl) li->li_prev = li - 1; li->li_next = li + 1; } - list_log((const list_T *)sl, &sl->sl_items[0], &sl->sl_items[SL_SIZE - 1], - "s10init"); #undef SL_SIZE } @@ -296,7 +229,6 @@ void tv_list_init_static(list_T *const l) { CLEAR_POINTER(l); l->lv_refcount = DO_NOT_FREE_CNT; - list_log(l, NULL, NULL, "sinit"); } /// Free items contained in a list @@ -305,7 +237,6 @@ void tv_list_init_static(list_T *const l) void tv_list_free_contents(list_T *const l) FUNC_ATTR_NONNULL_ALL { - list_log(l, NULL, NULL, "freecont"); for (listitem_T *item = l->lv_first; item != NULL; item = l->lv_first) { // Remove the item before deleting it. l->lv_first = item->li_next; @@ -335,7 +266,6 @@ void tv_list_free_list(list_T *const l) if (l->lv_used_next != NULL) { l->lv_used_next->lv_used_prev = l->lv_used_prev; } - list_log(l, NULL, NULL, "freelist"); NLUA_CLEAR_REF(l->lua_table_ref); xfree(l); @@ -382,7 +312,6 @@ void tv_list_unref(list_T *const l) void tv_list_drop_items(list_T *const l, listitem_T *const item, listitem_T *const item2) FUNC_ATTR_NONNULL_ALL { - list_log(l, item, item2, "drop"); // Notify watchers. for (listitem_T *ip = item; ip != item2->li_next; ip = ip->li_next) { l->lv_len--; @@ -400,14 +329,12 @@ void tv_list_drop_items(list_T *const l, listitem_T *const item, listitem_T *con item->li_prev->li_next = item2->li_next; } l->lv_idx_item = NULL; - list_log(l, l->lv_first, l->lv_last, "afterdrop"); } /// Like tv_list_drop_items, but also frees all removed items void tv_list_remove_items(list_T *const l, listitem_T *const item, listitem_T *const item2) FUNC_ATTR_NONNULL_ALL { - list_log(l, item, item2, "remove"); tv_list_drop_items(l, item, item2); for (listitem_T *li = item;;) { tv_clear(TV_LIST_ITEM_TV(li)); @@ -431,7 +358,6 @@ void tv_list_move_items(list_T *const l, listitem_T *const item, listitem_T *con list_T *const tgt_l, const int cnt) FUNC_ATTR_NONNULL_ALL { - list_log(l, item, item2, "move"); tv_list_drop_items(l, item, item2); item->li_prev = tgt_l->lv_last; item2->li_next = NULL; @@ -442,7 +368,6 @@ void tv_list_move_items(list_T *const l, listitem_T *const item, listitem_T *con } tgt_l->lv_last = item2; tgt_l->lv_len += cnt; - list_log(tgt_l, tgt_l->lv_first, tgt_l->lv_last, "movetgt"); } /// Insert list item @@ -470,7 +395,6 @@ void tv_list_insert(list_T *const l, listitem_T *const ni, listitem_T *const ite } item->li_prev = ni; l->lv_len++; - list_log(l, ni, item, "insert"); } } @@ -496,7 +420,6 @@ void tv_list_insert_tv(list_T *const l, typval_T *const tv, listitem_T *const it void tv_list_append(list_T *const l, listitem_T *const item) FUNC_ATTR_NONNULL_ALL { - list_log(l, item, NULL, "append"); if (l->lv_last == NULL) { // empty list l->lv_first = item; @@ -1416,7 +1339,6 @@ void tv_list_reverse(list_T *const l) if (tv_list_len(l) <= 1) { return; } - list_log(l, NULL, NULL, "reverse"); #define SWAP(a, b) \ do { \ tmp = (a); \ @@ -1454,7 +1376,6 @@ void tv_list_item_sort(list_T *const l, ListSortItem *const ptrs, if (len <= 1) { return; } - list_log(l, NULL, NULL, "sort"); int i = 0; TV_LIST_ITER(l, li, { ptrs[i].item = li; @@ -1543,7 +1464,6 @@ listitem_T *tv_list_find(list_T *const l, int n) // Cache the used index. l->lv_idx = idx; l->lv_idx_item = item; - list_log(l, l->lv_idx_item, (void *)(uintptr_t)l->lv_idx, "find"); return item; } diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 767fd706b3..e7b2499346 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -18,74 +18,6 @@ #include "nvim/message.h" #include "nvim/types.h" -#ifdef LOG_LIST_ACTIONS -# include "nvim/memory.h" - -extern ListLog *list_log_first; ///< First list log chunk, NULL if missing -extern ListLog *list_log_last; ///< Last list log chunk - -static inline ListLog *list_log_alloc(const size_t size) - REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT; - -/// Allocate a new log chunk and update globals -/// -/// @param[in] size Number of entries in a new chunk. -/// -/// @return [allocated] Newly allocated chunk. -static inline ListLog *list_log_new(const size_t size) -{ - ListLog *ret = xmalloc(offsetof(ListLog, entries) - + size * sizeof(ret->entries[0])); - ret->size = 0; - ret->capacity = size; - ret->next = NULL; - if (list_log_first == NULL) { - list_log_first = ret; - } else { - list_log_last->next = ret; - } - list_log_last = ret; - return ret; -} - -static inline void list_log(const list_T *const l, const listitem_T *const li1, - const listitem_T *const li2, const char *const action) - REAL_FATTR_ALWAYS_INLINE; - -/// Add new entry to log -/// -/// If last chunk was filled it uses twice as much memory to allocate the next -/// chunk. -/// -/// @param[in] l List to which entry belongs. -/// @param[in] li1 List item 1. -/// @param[in] li2 List item 2, often used for integers and not list items. -/// @param[in] action Logged action. -static inline void list_log(const list_T *const l, const listitem_T *const li1, - const listitem_T *const li2, const char *const action) -{ - ListLog *tgt; - if (list_log_first == NULL) { - tgt = list_log_new(128); - } else if (list_log_last->size == list_log_last->capacity) { - tgt = list_log_new(list_log_last->capacity * 2); - } else { - tgt = list_log_last; - } - tgt->entries[tgt->size++] = (ListLogEntry) { - .l = (uintptr_t)l, - .li1 = (uintptr_t)li1, - .li2 = (uintptr_t)li2, - .len = (l == NULL ? 0 : l->lv_len), - .action = action, - }; -} -#else -# define list_log(...) -# define list_write_log(...) -# define list_free_log() -#endif - // In a hashtab item "hi_key" points to "di_key" in a dictitem. // This avoids adding a pointer to the hashtab item. @@ -174,7 +106,6 @@ static inline int tv_list_len(const list_T *l) /// @param[in] l List to check. static inline int tv_list_len(const list_T *const l) { - list_log(l, NULL, NULL, "len"); if (l == NULL) { return 0; } @@ -258,10 +189,8 @@ static inline listitem_T *tv_list_first(const list_T *l) static inline listitem_T *tv_list_first(const list_T *const l) { if (l == NULL) { - list_log(l, NULL, NULL, "first"); return NULL; } - list_log(l, l->lv_first, NULL, "first"); return l->lv_first; } @@ -276,10 +205,8 @@ static inline listitem_T *tv_list_last(const list_T *l) static inline listitem_T *tv_list_last(const list_T *const l) { if (l == NULL) { - list_log(l, NULL, NULL, "last"); return NULL; } - list_log(l, l->lv_last, NULL, "last"); return l->lv_last; } @@ -416,7 +343,6 @@ extern bool tv_in_free_unref_items; #define _TV_LIST_ITER_MOD(modifier, l, li, code) \ do { \ modifier list_T *const l_ = (l); \ - list_log(l_, NULL, NULL, "iter" #modifier); \ if (l_ != NULL) { \ for (modifier listitem_T *li = l_->lv_first; \ li != NULL; li = li->li_next) { \ diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 3e49417f6f..767603ac0e 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -375,25 +375,4 @@ typedef struct { typedef int (*ListSorter)(const void *, const void *); -#ifdef LOG_LIST_ACTIONS -/// List actions log entry -typedef struct { - uintptr_t l; ///< List log entry belongs to. - uintptr_t li1; ///< First list item log entry belongs to, if applicable. - uintptr_t li2; ///< Second list item log entry belongs to, if applicable. - int len; ///< List length when log entry was created. - const char *action; ///< Logged action. -} ListLogEntry; - -typedef struct list_log ListLog; - -/// List actions log -struct list_log { - ListLog *next; ///< Next chunk or NULL. - size_t capacity; ///< Number of entries in current chunk. - size_t size; ///< Current chunk size. - ListLogEntry entries[]; ///< Actual log entries. -}; -#endif - #endif // NVIM_EVAL_TYPVAL_DEFS_H -- cgit From f215a2aeaacb9635232cfad82de9a9674a86969c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 30 May 2023 22:56:27 +0800 Subject: vim-patch:8.2.3689: ex_let_one() is too long (#23830) Problem: ex_let_one() is too long. Solution: Split into multiple functions. https://github.com/vim/vim/commit/3ccb5795168793e1b119a028da4035f77cef9f69 Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 348 ++++++++++++++++++++++++++++----------------------- 1 file changed, 190 insertions(+), 158 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 64177d13e8..21b25b64f4 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -701,6 +701,189 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) return arg; } +/// Set an environment variable, part of ex_let_one(). +static char *ex_let_env(char *arg, typval_T *const tv, const bool is_const, + const char *const endchars, const char *const op) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (is_const) { + emsg(_("E996: Cannot lock an environment variable")); + return NULL; + } + + // Find the end of the name. + char *arg_end = NULL; + arg++; + char *name = arg; + int len = get_env_len((const char **)&arg); + if (len == 0) { + semsg(_(e_invarg2), name - 1); + } else { + if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { + semsg(_(e_letwrong), op); + } else if (endchars != NULL + && vim_strchr(endchars, (uint8_t)(*skipwhite(arg))) == NULL) { + emsg(_(e_letunexp)); + } else if (!check_secure()) { + char *tofree = NULL; + const char c1 = name[len]; + name[len] = NUL; + const char *p = tv_get_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { + char *s = vim_getenv(name); + if (s != NULL) { + tofree = concat_str(s, p); + p = tofree; + xfree(s); + } + } + if (p != NULL) { + vim_setenv_ext(name, p); + arg_end = arg; + } + name[len] = c1; + xfree(tofree); + } + } + return arg_end; +} + +/// Set an option, part of ex_let_one(). +static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, + const char *const endchars, const char *const op) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (is_const) { + emsg(_("E996: Cannot lock an option")); + return NULL; + } + + // Find the end of the name. + char *arg_end = NULL; + int scope; + char *const p = (char *)find_option_end((const char **)&arg, &scope); + if (p == NULL + || (endchars != NULL + && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { + emsg(_(e_letunexp)); + } else { + varnumber_T n = 0; + getoption_T opt_type; + long numval; + char *stringval = NULL; + const char *s = NULL; + bool failed = false; + uint32_t opt_p_flags; + char *tofree = NULL; + + const char c1 = *p; + *p = NUL; + + opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope); + if (opt_type == gov_bool + || opt_type == gov_number + || opt_type == gov_hidden_bool + || opt_type == gov_hidden_number) { + // number, possibly hidden + n = (long)tv_get_number(tv); + } + + if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) { + // If the option can be set to a function reference or a lambda + // and the passed value is a function reference, then convert it to + // the name (string) of the function reference. + s = tofree = encode_tv2string(tv, NULL); + } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { + // Avoid setting a string option to the text "v:false" or similar. + s = tv_get_string_chk(tv); + } + + if (op != NULL && *op != '=') { + if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.') + || (opt_type == gov_string && *op != '.')) { + semsg(_(e_letwrong), op); + failed = true; // don't set the value + } else { + // number or bool + if (opt_type == gov_number || opt_type == gov_bool) { + switch (*op) { + case '+': + n = numval + n; break; + case '-': + n = numval - n; break; + case '*': + n = numval * n; break; + case '/': + n = num_divide(numval, n); break; + case '%': + n = num_modulus(numval, n); break; + } + s = NULL; + } else if (opt_type == gov_string && stringval != NULL && s != NULL) { + // string + char *const oldstringval = stringval; + stringval = concat_str(stringval, s); + xfree(oldstringval); + s = stringval; + } + } + } + + if (!failed) { + if (opt_type != gov_string || s != NULL) { + const char *err = set_option_value(arg, (long)n, s, scope); + arg_end = p; + if (err != NULL) { + emsg(_(err)); + } + } else { + emsg(_(e_stringreq)); + } + } + *p = c1; + xfree(stringval); + xfree(tofree); + } + return arg_end; +} + +/// Set a register, part of ex_let_one(). +static char *ex_let_register(char *arg, typval_T *const tv, const bool is_const, + const char *const endchars, const char *const op) + FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT +{ + if (is_const) { + emsg(_("E996: Cannot lock a register")); + return NULL; + } + + char *arg_end = NULL; + arg++; + if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { + semsg(_(e_letwrong), op); + } else if (endchars != NULL + && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) { + emsg(_(e_letunexp)); + } else { + char *ptofree = NULL; + const char *p = tv_get_string_chk(tv); + if (p != NULL && op != NULL && *op == '.') { + char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); + if (s != NULL) { + ptofree = concat_str(s, p); + p = ptofree; + xfree(s); + } + } + if (p != NULL) { + write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)strlen(p), false); + arg_end = arg + 1; + } + xfree(ptofree); + } + return arg_end; +} + /// Set one item of `:let var = expr` or `:let [v1, v2] = list` to its value /// /// @param[in] arg Start of the variable name. @@ -718,172 +901,21 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo { char *arg_end = NULL; - // ":let $VAR = expr": Set environment variable. if (*arg == '$') { - if (is_const) { - emsg(_("E996: Cannot lock an environment variable")); - return NULL; - } - // Find the end of the name. - arg++; - char *name = arg; - int len = get_env_len((const char **)&arg); - if (len == 0) { - semsg(_(e_invarg2), name - 1); - } else { - if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { - semsg(_(e_letwrong), op); - } else if (endchars != NULL - && vim_strchr(endchars, (uint8_t)(*skipwhite(arg))) == NULL) { - emsg(_(e_letunexp)); - } else if (!check_secure()) { - char *tofree = NULL; - const char c1 = name[len]; - name[len] = NUL; - const char *p = tv_get_string_chk(tv); - if (p != NULL && op != NULL && *op == '.') { - char *s = vim_getenv(name); - if (s != NULL) { - tofree = concat_str(s, p); - p = tofree; - xfree(s); - } - } - if (p != NULL) { - vim_setenv_ext(name, p); - arg_end = arg; - } - name[len] = c1; - xfree(tofree); - } - } + // ":let $VAR = expr": Set environment variable. + return ex_let_env(arg, tv, is_const, endchars, op); + } else if (*arg == '&') { // ":let &option = expr": Set option value. // ":let &l:option = expr": Set local option value. // ":let &g:option = expr": Set global option value. - } else if (*arg == '&') { - if (is_const) { - emsg(_("E996: Cannot lock an option")); - return NULL; - } - // Find the end of the name. - int scope; - char *const p = (char *)find_option_end((const char **)&arg, &scope); - if (p == NULL - || (endchars != NULL - && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { - emsg(_(e_letunexp)); - } else { - varnumber_T n = 0; - getoption_T opt_type; - long numval; - char *stringval = NULL; - const char *s = NULL; - bool failed = false; - uint32_t opt_p_flags; - char *tofree = NULL; - - const char c1 = *p; - *p = NUL; - - opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope); - if (opt_type == gov_bool - || opt_type == gov_number - || opt_type == gov_hidden_bool - || opt_type == gov_hidden_number) { - // number, possibly hidden - n = (long)tv_get_number(tv); - } - - if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) { - // If the option can be set to a function reference or a lambda - // and the passed value is a function reference, then convert it to - // the name (string) of the function reference. - s = tofree = encode_tv2string(tv, NULL); - } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { - // Avoid setting a string option to the text "v:false" or similar. - s = tv_get_string_chk(tv); - } - - if (op != NULL && *op != '=') { - if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.') - || (opt_type == gov_string && *op != '.')) { - semsg(_(e_letwrong), op); - failed = true; // don't set the value - } else { - // number or bool - if (opt_type == gov_number || opt_type == gov_bool) { - switch (*op) { - case '+': - n = numval + n; break; - case '-': - n = numval - n; break; - case '*': - n = numval * n; break; - case '/': - n = num_divide(numval, n); break; - case '%': - n = num_modulus(numval, n); break; - } - s = NULL; - } else if (opt_type == gov_string && stringval != NULL && s != NULL) { - // string - char *const oldstringval = stringval; - stringval = concat_str(stringval, s); - xfree(oldstringval); - s = stringval; - } - } - } - - if (!failed) { - if (opt_type != gov_string || s != NULL) { - const char *err = set_option_value(arg, (long)n, s, scope); - arg_end = p; - if (err != NULL) { - emsg(_(err)); - } - } else { - emsg(_(e_stringreq)); - } - } - *p = c1; - xfree(stringval); - xfree(tofree); - } - // ":let @r = expr": Set register contents. + return ex_let_option(arg, tv, is_const, endchars, op); } else if (*arg == '@') { - if (is_const) { - emsg(_("E996: Cannot lock a register")); - return NULL; - } - arg++; - if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { - semsg(_(e_letwrong), op); - } else if (endchars != NULL - && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) { - emsg(_(e_letunexp)); - } else { - char *ptofree = NULL; - const char *p = tv_get_string_chk(tv); - if (p != NULL && op != NULL && *op == '.') { - char *s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc); - if (s != NULL) { - ptofree = concat_str(s, p); - p = ptofree; - xfree(s); - } - } - if (p != NULL) { - write_reg_contents(*arg == '@' ? '"' : *arg, p, (ssize_t)strlen(p), false); - arg_end = arg + 1; - } - xfree(ptofree); - } + // ":let @r = expr": Set register contents. + return ex_let_register(arg, tv, is_const, endchars, op); + } else if (eval_isnamec1(*arg) || *arg == '{') { // ":let var = expr": Set internal variable. // ":let {expr} = expr": Idem, name made with curly braces - } else if (eval_isnamec1(*arg) || *arg == '{') { lval_T lv; - char *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START); if (p != NULL && lv.ll_name != NULL) { if (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL) { -- cgit From a0375b68c1803e7453071a20b28249020abe7260 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Jun 2023 04:31:17 +0800 Subject: vim-patch:9.0.1598: screenchar() and others are wrong with DBCS 'encoding' (#23872) Problem: screenchar(), screenchars() and screenstring() do not work properly when 'encoding' is set to a double-byte encoding. Solution: Fix the way the bytes of the characters are obtained. (issue vim/vim#12469) https://github.com/vim/vim/commit/47eec6716b8621fd43bac8ecc9c19089df26705e --- src/nvim/eval/funcs.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 927c1b3d5c..b4f9e4e219 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -62,7 +62,7 @@ #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" -#include "nvim/grid_defs.h" +#include "nvim/grid.h" #include "nvim/hashtab.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" @@ -6745,7 +6745,9 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - c = utf_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col]); + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); + c = utf_ptr2char(buf); } rettv->vval.v_number = c; } @@ -6763,10 +6765,13 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_list_alloc_ret(rettv, 0); return; } + + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); int pcc[MAX_MCO]; - int c = utfc_ptr2char((char *)grid->chars[grid->line_offset[row] + (size_t)col], pcc); + int c = utfc_ptr2char(buf, pcc); int composing_len = 0; - while (pcc[composing_len] != 0) { + while (composing_len < MAX_MCO && pcc[composing_len] != 0) { composing_len++; } tv_list_alloc_ret(rettv, composing_len + 1); @@ -6806,7 +6811,9 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr return; } - rettv->vval.v_string = xstrdup((char *)grid->chars[grid->line_offset[row] + (size_t)col]); + char buf[MB_MAXBYTES + 1]; + grid_getbytes(grid, row, col, buf, NULL); + rettv->vval.v_string = xstrdup(buf); } /// "search()" function @@ -7201,7 +7208,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// Set the cursor or mark position. -/// If 'charpos' is true, then use the column number as a character offset. +/// 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) { -- cgit From 2db719f6c2b677fcbc197b02fe52764a851523b2 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 3 Jun 2023 11:06:00 +0100 Subject: feat(lua): rename vim.loop -> vim.uv (#22846) --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b4f9e4e219..04fd81c713 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3238,7 +3238,7 @@ static bool has_wsl(void) static TriState has_wsl = kNone; if (has_wsl == kNone) { Error err = ERROR_INIT; - Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.loop.os_uname()['release']:lower()" + Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.uv.os_uname()['release']:lower()" ":match('microsoft') and true or false"), (Array)ARRAY_DICT_INIT, &err); assert(!ERROR_SET(&err)); -- cgit From b3d5138fd0066fda26ef7724a542ae45eb42fc84 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 7 Jun 2023 06:05:16 +0600 Subject: refactor(options): remove `getoption_T` and introduce `OptVal` (#23850) Removes the `getoption_T` struct and also introduces the `OptVal` struct to unify the methods of getting/setting different option value types. This is the first of many PRs to reduce code duplication in the Vim option code as well as to make options easier to maintain. It also increases the flexibility and extensibility of options. Which opens the door for things like Array and Dictionary options. --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 228 +++++++++++++++++++++++++++++++------------------- 2 files changed, 143 insertions(+), 87 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 04fd81c713..d465cade3e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7101,7 +7101,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir // If it's still empty it was changed and restored, need to restore in // the complicated way. if (*p_cpo == NUL) { - set_option_value_give_err("cpo", 0L, save_cpo, 0); + set_option_value_give_err("cpo", CSTR_AS_OPTVAL(save_cpo), 0); } free_string_option(save_cpo); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 21b25b64f4..0663c3c54c 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -766,84 +766,84 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, || (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { emsg(_(e_letunexp)); - } else { - varnumber_T n = 0; - getoption_T opt_type; - long numval; - char *stringval = NULL; - const char *s = NULL; - bool failed = false; - uint32_t opt_p_flags; - char *tofree = NULL; - - const char c1 = *p; - *p = NUL; + return NULL; + } - opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope); - if (opt_type == gov_bool - || opt_type == gov_number - || opt_type == gov_hidden_bool - || opt_type == gov_hidden_number) { - // number, possibly hidden - n = (long)tv_get_number(tv); - } - - if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) { - // If the option can be set to a function reference or a lambda - // and the passed value is a function reference, then convert it to - // the name (string) of the function reference. - s = tofree = encode_tv2string(tv, NULL); - } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { - // Avoid setting a string option to the text "v:false" or similar. - s = tv_get_string_chk(tv); - } - - if (op != NULL && *op != '=') { - if (((opt_type == gov_bool || opt_type == gov_number) && *op == '.') - || (opt_type == gov_string && *op != '.')) { - semsg(_(e_letwrong), op); - failed = true; // don't set the value - } else { - // number or bool - if (opt_type == gov_number || opt_type == gov_bool) { - switch (*op) { - case '+': - n = numval + n; break; - case '-': - n = numval - n; break; - case '*': - n = numval * n; break; - case '/': - n = num_divide(numval, n); break; - case '%': - n = num_modulus(numval, n); break; - } - s = NULL; - } else if (opt_type == gov_string && stringval != NULL && s != NULL) { - // string - char *const oldstringval = stringval; - stringval = concat_str(stringval, s); - xfree(oldstringval); - s = stringval; + bool hidden; + bool error; + const char c1 = *p; + *p = NUL; + + OptVal curval = get_option_value(arg, NULL, scope, &hidden); + OptVal newval = tv_to_optval(tv, arg, scope, &error); + + // Ignore errors for num types + if (newval.type != kOptValTypeNumber && newval.type != kOptValTypeBoolean && error) { + goto end; + } + + // Don't assume current and new values are of the same type in order to future-proof the code for + // when an option can have multiple types. + const bool is_num = ((curval.type == kOptValTypeNumber || curval.type == kOptValTypeBoolean) + && (newval.type == kOptValTypeNumber || newval.type == kOptValTypeBoolean)); + const bool is_string = curval.type == kOptValTypeString && newval.type == kOptValTypeString; + + if (op != NULL && *op != '=') { + if (!hidden && ((is_num && *op == '.') || (is_string && *op != '.'))) { + semsg(_(e_letwrong), op); + goto end; + } else { + // number or bool + if (!hidden && is_num) { + Integer cur_n = curval.type == kOptValTypeNumber ? curval.data.number : curval.data.boolean; + Integer new_n = newval.type == kOptValTypeNumber ? newval.data.number : newval.data.boolean; + + switch (*op) { + case '+': + new_n = cur_n + new_n; break; + case '-': + new_n = cur_n - new_n; break; + case '*': + new_n = cur_n * new_n; break; + case '/': + new_n = num_divide(cur_n, new_n); break; + case '%': + new_n = num_modulus(cur_n, new_n); break; } - } - } - if (!failed) { - if (opt_type != gov_string || s != NULL) { - const char *err = set_option_value(arg, (long)n, s, scope); - arg_end = p; - if (err != NULL) { - emsg(_(err)); + // clamp boolean values + if (newval.type == kOptValTypeBoolean && (new_n > 1 || new_n < -1)) { + new_n = (new_n > 1) ? 1 : -1; } - } else { - emsg(_(e_stringreq)); + + newval = kOptValTypeNumber ? NUMBER_OPTVAL(new_n) : BOOLEAN_OPTVAL((TriState)new_n); + } else if (!hidden && is_string && curval.data.string.data != NULL + && newval.data.string.data != NULL) { + // string + OptVal newval_old = newval; + newval = CSTR_AS_OPTVAL(concat_str(curval.data.string.data, newval.data.string.data)); + optval_free(newval_old); } } - *p = c1; - xfree(stringval); - xfree(tofree); } + + // If new value is a string and is NULL, show an error if it's not a hidden option. + // For hidden options, just pass the value to `set_option_value` and let it fail silently. + if (hidden || newval.type != kOptValTypeString || newval.data.string.data != NULL) { + const char *err = set_option_value(arg, newval, scope); + arg_end = p; + if (err != NULL) { + emsg(_(err)); + } + } else { + emsg(_(e_stringreq)); + } + +end: + *p = c1; + optval_free(curval); + optval_free(newval); + return arg_end; } @@ -1809,28 +1809,84 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off) get_var_from(varname, rettv, &argvars[off + 2], 'w', tp, win, NULL); } -/// Set option "varname" to the value of "varp" for the current buffer/window. -static void set_option_from_tv(const char *varname, typval_T *varp) +/// Convert typval to option value for a particular option. +/// +/// @param[in] tv typval to convert. +/// @param[in] option Option name. +/// @param[in] scope Option scope. +/// @param[out] error Whether an error occured. +/// +/// @return Typval converted to OptVal. Must be freed by caller. +/// Returns NIL_OPTVAL for invalid option name. +static OptVal tv_to_optval(typval_T *tv, const char *option, int scope, bool *error) { - long numval = 0; - const char *strval; - bool error = false; + OptVal value = NIL_OPTVAL; char nbuf[NUMBUFLEN]; - - if (varp->v_type == VAR_BOOL) { - if (is_string_option(varname)) { + uint32_t flags; + bool err = false; + + OptVal curval = get_option_value(option, &flags, scope, NULL); + + // TODO(famiu): Delegate all of these type-checks to set_option_value() + if (curval.type == kOptValTypeNil) { + // Invalid option name, + value = NIL_OPTVAL; + } else if ((flags & P_FUNC) && tv_is_func(*tv)) { + // If the option can be set to a function reference or a lambda + // and the passed value is a function reference, then convert it to + // the name (string) of the function reference. + char *strval = encode_tv2string(tv, NULL); + err = strval == NULL; + value = CSTR_AS_OPTVAL(strval); + } else if (flags & (P_NUM | P_BOOL)) { + varnumber_T n = tv_get_number_chk(tv, &err); + // This could be either "0" or a string that's not a number. So we need to check if it's + // actually a number. + if (!err && tv->v_type == VAR_STRING && n == 0) { + unsigned idx; + for (idx = 0; tv->vval.v_string[idx] == '0'; idx++) {} + if (tv->vval.v_string[idx] != NUL || idx == 0) { + // There's another character after zeros or the string is empty. + // In both cases, we are trying to set a num option using a string. + semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string); + } + } + value = (flags & P_NUM) ? NUMBER_OPTVAL(n) + : BOOLEAN_OPTVAL(n == 0 ? kFalse : (n >= 1 ? kTrue : kNone)); + } else if (flags & P_STRING || is_tty_option(option)) { + // Avoid setting string option to a boolean. + if (tv->v_type == VAR_BOOL) { + err = true; emsg(_(e_stringreq)); - return; + } else { + const char *strval = tv_get_string_buf_chk(tv, nbuf); + err = strval == NULL; + value = CSTR_TO_OPTVAL(strval); } - numval = (long)varp->vval.v_number; - strval = "0"; // avoid using "false" } else { - numval = (long)tv_get_number_chk(varp, &error); - strval = tv_get_string_buf_chk(varp, nbuf); + abort(); // This should never happen. } - if (!error && strval != NULL) { - set_option_value_give_err(varname, numval, strval, OPT_LOCAL); + + if (error != NULL) { + *error = err; } + optval_free(curval); + return value; +} + +/// Set option "varname" to the value of "varp" for the current buffer/window. +static void set_option_from_tv(const char *varname, typval_T *varp) +{ + bool error = false; + OptVal value = tv_to_optval(varp, varname, OPT_LOCAL, &error); + + if (!error && value.type == kOptValTypeNil) { + semsg(_(e_unknown_option2), varname); + } else if (!error) { + set_option_value_give_err(varname, value, OPT_LOCAL); + } + + optval_free(value); } /// "setwinvar()" and "settabwinvar()" functions -- cgit From 971049f3189d4769db5e9896cd19b555719b3d09 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 7 Jun 2023 09:26:46 +0800 Subject: revert: "refactor: eliminate `autocmd_fname_full` global" This reverts commit 82cd0be2eaf71c0476e15c66ba3e83c76896d407. --- src/nvim/eval/funcs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d465cade3e..788efe1e84 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6552,6 +6552,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) sctx_T save_current_sctx; char *save_autocmd_fname, *save_autocmd_match; + bool save_autocmd_fname_full; int save_autocmd_bufnr; funccal_entry_T funccal_entry; @@ -6561,6 +6562,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) save_current_sctx = current_sctx; save_autocmd_fname = autocmd_fname; save_autocmd_match = autocmd_match; + save_autocmd_fname_full = autocmd_fname_full; save_autocmd_bufnr = autocmd_bufnr; save_funccal(&funccal_entry); @@ -6569,6 +6571,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ((estack_T *)exestack.ga_data)[exestack.ga_len++] = provider_caller_scope.es_entry; autocmd_fname = provider_caller_scope.autocmd_fname; autocmd_match = provider_caller_scope.autocmd_match; + autocmd_fname_full = provider_caller_scope.autocmd_fname_full; autocmd_bufnr = provider_caller_scope.autocmd_bufnr; set_current_funccal((funccall_T *)(provider_caller_scope.funccalp)); } @@ -6586,6 +6589,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) exestack.ga_len--; autocmd_fname = save_autocmd_fname; autocmd_match = save_autocmd_match; + autocmd_fname_full = save_autocmd_fname_full; autocmd_bufnr = save_autocmd_bufnr; restore_funccal(); } -- cgit From 7f8c1e53a6c27ce6957b102d7b1c9ec808f61d60 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Sat, 11 Sep 2021 19:44:11 +0100 Subject: vim-patch:8.2.2948: substitute() accepts a number but not a float expression Problem: Substitute() accepts a number but not a float expression. Solution: Also accept a float. (closes vim/vim#8331) https://github.com/vim/vim/commit/7a2217bedd223df4c8bbebe731bf0b5fe8532533 Vim9script is N/A. No need to port the strict argument and tv_get_string_buf_chk_strict(), as it's only used for Vim9script. Like the patch, use vim_snprintf over snprintf, as the "%g" specifier in snprintf removes the ".0" from integer floats. This means similiar to numbers, floats are (mostly) convertable to strings. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 42e9dc8f03..a392d441cf 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3876,7 +3876,6 @@ static const char *const str_errors[] = { [VAR_FUNC]= N_(FUNC_ERROR), [VAR_LIST]= N_("E730: Using a List as a String"), [VAR_DICT]= N_("E731: Using a Dictionary as a String"), - [VAR_FLOAT]= e_using_float_as_string, [VAR_BLOB]= N_("E976: Using a Blob as a String"), [VAR_UNKNOWN]= e_using_invalid_value_as_string, }; @@ -3899,12 +3898,12 @@ bool tv_check_str(const typval_T *const tv) case VAR_BOOL: case VAR_SPECIAL: case VAR_STRING: + case VAR_FLOAT: return true; case VAR_PARTIAL: case VAR_FUNC: case VAR_LIST: case VAR_DICT: - case VAR_FLOAT: case VAR_BLOB: case VAR_UNKNOWN: emsg(_(str_errors[tv->v_type])); @@ -4275,6 +4274,9 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) case VAR_NUMBER: snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); // -V576 return buf; + case VAR_FLOAT: + vim_snprintf(buf, NUMBUFLEN, "%g", tv->vval.v_float); + return buf; case VAR_STRING: if (tv->vval.v_string != NULL) { return tv->vval.v_string; @@ -4290,7 +4292,6 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) case VAR_FUNC: case VAR_LIST: case VAR_DICT: - case VAR_FLOAT: case VAR_BLOB: case VAR_UNKNOWN: emsg(_(str_errors[tv->v_type])); -- cgit From a0cb53eca7a04326dd857cf33fac1154aff7773a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 12 Jun 2023 15:38:53 +0800 Subject: vim-patch:8.2.2533: Vim9: cannot use a range with :unlet Problem: Vim9: cannot use a range with :unlet. Solution: Implement ISN_UNLETRANGE. https://github.com/vim/vim/commit/5b5ae29bd3d7b832b6f15320430f7f191e0abd1f Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 15 +++++++++++++++ src/nvim/eval/vars.c | 46 ++++++++++++++++++++++++++++------------------ 2 files changed, 43 insertions(+), 18 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a392d441cf..9e697d6144 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1507,6 +1507,21 @@ const char *tv_list_find_str(list_T *const l, const int n) return tv_get_string(TV_LIST_ITEM_TV(li)); } +/// Like tv_list_find() but when a negative index is used that is not found use +/// zero and set "idx" to zero. Used for first index of a range. +listitem_T *tv_list_find_index(list_T *const l, long *const idx) + FUNC_ATTR_WARN_UNUSED_RESULT +{ + listitem_T *li = tv_list_find(l, (int)(*idx)); + if (li == NULL) { + if (*idx < 0) { + *idx = 0; + li = tv_list_find(l, (int)(*idx)); + } + } + return li; +} + /// Locate item in a list and return its index /// /// @param[in] l List to search. diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 0663c3c54c..f988a49e6c 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1056,25 +1056,10 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { - assert(lp->ll_list != NULL); - // Delete a range of List items. - listitem_T *const first_li = lp->ll_li; - listitem_T *last_li = first_li; - while (true) { - listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li); - if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, - lp->ll_name, - lp->ll_name_len)) { - return false; - } - lp->ll_li = li; - lp->ll_n1++; - if (lp->ll_li == NULL || (!lp->ll_empty2 && lp->ll_n2 < lp->ll_n1)) { - break; - } - last_li = lp->ll_li; + if (list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_name, lp->ll_name_len, + lp->ll_n1, !lp->ll_empty2, lp->ll_n2) == FAIL) { + return FAIL; } - tv_list_remove_items(lp->ll_list, first_li, last_li); } else { if (lp->ll_list != NULL) { // unlet a List item. @@ -1107,6 +1092,31 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ return ret; } +/// Unlet one item or a range of items from a list. +/// Return OK or FAIL. +static int list_unlet_range(list_T *const l, listitem_T *const li_first, const char *const name, + const size_t name_len, const long n1_arg, const bool has_n2, + const long n2) +{ + assert(l != NULL); + // Delete a range of List items. + listitem_T *li_last = li_first; + long n1 = n1_arg; + while (true) { + if (value_check_lock(TV_LIST_ITEM_TV(li_last)->v_lock, name, name_len)) { + return FAIL; + } + listitem_T *const li = TV_LIST_ITEM_NEXT(l, li_last); + n1++; + if (li == NULL || (has_n2 && n2 < n1)) { + break; + } + li_last = li; + } + tv_list_remove_items(l, li_first, li_last); + return OK; +} + /// unlet a variable /// /// @param[in] name Variable name to unlet. -- cgit From 4058f95d9dc9a58ab80f982c91b85ec1363c89c8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 12 Jun 2023 16:15:12 +0800 Subject: vim-patch:partial:8.2.3335: Vim9: not enough tests run with Vim9 Problem: Vim9: not enough tests run with Vim9. Solution: Run a few more tests in Vim9 script and :def function. Fix that items(), keys() and values9) return zero for a NULL dict. Make join() return an empty string for a NULL list. Make sort() return an empty list for a NULL list. https://github.com/vim/vim/commit/ef98257593a0abf1300d0f70358dc45a70a62580 Skip f_reverse() change for consistency with other functions. Skip Test_null_list() and Test_null_dict() because of missing patches. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9e697d6144..ec227a6b1a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3019,12 +3019,13 @@ static void tv_dict_list(typval_T *const tv, typval_T *const rettv, const DictLi emsg(_(e_dictreq)); return; } + + tv_list_alloc_ret(rettv, tv_dict_len(tv->vval.v_dict)); if (tv->vval.v_dict == NULL) { + // NULL dict behaves like an empty dict return; } - tv_list_alloc_ret(rettv, tv_dict_len(tv->vval.v_dict)); - TV_DICT_ITER(tv->vval.v_dict, di, { typval_T tv_item = { .v_lock = VAR_UNLOCKED }; -- cgit From aa92a04beeed1fb10a82edd6a245e5783cd771c1 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 12 Jun 2023 20:35:01 +0800 Subject: vim-patch:8.2.3332: Vim9: cannot assign to range in list Problem: Vim9: cannot assign to range in list. Solution: Implement overwriting a list range. https://github.com/vim/vim/commit/4f0884d6e24d1d45ec83fd86b372b403177d3298 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 113 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ec227a6b1a..a891ba1570 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -594,6 +594,119 @@ tv_list_copy_error: return NULL; } +/// Get the list item in "l" with index "n1". "n1" is adjusted if needed. +/// Return NULL if there is no such item. +listitem_T *tv_list_check_range_index_one(list_T *const l, long *const n1, const bool quiet) +{ + listitem_T *li = tv_list_find_index(l, n1); + if (li == NULL) { + if (!quiet) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)n1); + } + return NULL; + } + return li; +} + +/// Check that "n2" can be used as the second index in a range of list "l". +/// If "n1" or "n2" is negative it is changed to the positive index. +/// "li1" is the item for item "n1". +/// Return OK or FAIL. +int tv_list_check_range_index_two(list_T *const l, long *const n1, const listitem_T *const li1, + long *const n2, const bool quiet) +{ + if (*n2 < 0) { + listitem_T *ni = tv_list_find(l, (int)(*n2)); + if (ni == NULL) { + if (!quiet) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n2)); + } + return FAIL; + } + *n2 = tv_list_idx_of_item(l, ni); + } + + // Check that n2 isn't before n1. + if (*n1 < 0) { + *n1 = tv_list_idx_of_item(l, li1); + } + if (*n2 < *n1) { + if (!quiet) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n2)); + } + return FAIL; + } + return OK; +} + +/// Assign values from list "src" into a range of "dest". +/// "idx1_arg" is the index of the first item in "dest" to be replaced. +/// "idx2" is the index of last item to be replaced, but when "empty_idx2" is +/// true then replace all items after "idx1". +/// "op" is the operator, normally "=" but can be "+=" and the like. +/// "varname" is used for error messages. +/// Returns OK or FAIL. +int tv_list_assign_range(list_T *const dest, list_T *const src, const long idx1_arg, + const long idx2, const bool empty_idx2, const char *const op, + const char *const varname) +{ + long idx1 = idx1_arg; + listitem_T *const first_li = tv_list_find_index(dest, &idx1); + listitem_T *src_li; + + // Check whether any of the list items is locked before making any changes. + long idx = idx1; + listitem_T *dest_li = first_li; + for (src_li = tv_list_first(src); src_li != NULL && dest_li != NULL;) { + if (value_check_lock(TV_LIST_ITEM_TV(dest_li)->v_lock, varname, TV_CSTRING)) { + return FAIL; + } + src_li = TV_LIST_ITEM_NEXT(src, src_li); + if (src_li == NULL || (!empty_idx2 && idx2 == idx)) { + break; + } + dest_li = TV_LIST_ITEM_NEXT(dest, dest_li); + idx++; + } + + // Assign the List values to the list items. + idx = idx1; + dest_li = first_li; + for (src_li = tv_list_first(src); src_li != NULL;) { + if (op != NULL && *op != '=') { + eexe_mod_op(TV_LIST_ITEM_TV(dest_li), TV_LIST_ITEM_TV(src_li), op); + } else { + tv_clear(TV_LIST_ITEM_TV(dest_li)); + tv_copy(TV_LIST_ITEM_TV(src_li), TV_LIST_ITEM_TV(dest_li)); + } + src_li = TV_LIST_ITEM_NEXT(src, src_li); + if (src_li == NULL || (!empty_idx2 && idx2 == idx)) { + break; + } + assert(dest_li != NULL); + if (TV_LIST_ITEM_NEXT(dest, dest_li) == NULL) { + // Need to add an empty item. + tv_list_append_number(dest, 0); + // "dest_li" may have become invalid after append, don’t use it. + dest_li = tv_list_last(dest); // Valid again. + } else { + dest_li = TV_LIST_ITEM_NEXT(dest, dest_li); + } + idx++; + } + if (src_li != NULL) { + emsg(_("E710: List value has more items than target")); + return FAIL; + } + if (empty_idx2 + ? (dest_li != NULL && TV_LIST_ITEM_NEXT(dest, dest_li) != NULL) + : idx != idx2) { + emsg(_("E711: List value has not enough items")); + return FAIL; + } + return OK; +} + /// Flatten up to "maxitems" in "list", starting at "first" to depth "maxdepth". /// When "first" is NULL use the first item. /// Does nothing if "maxdepth" is 0. -- cgit From a7e5d4238a00d5bfa5809b2860047eca2d565e62 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 12 Jun 2023 21:58:40 +0800 Subject: vim-patch:8.2.4600: Vim9: not enough test coverage for executing :def function (#24001) Problem: Vim9: not enough test coverage for executing :def function. Solution: Add a few more tests. Fix inconsistencies. https://github.com/vim/vim/commit/6b8c7ba062ca4b50e8f983e0485be7afa4eef691 Cherry-pick a blank line in test_listdict.vim from patch 8.2.3842. Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 56 +++++++++++++++++++++------------------------------- 1 file changed, 23 insertions(+), 33 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index f988a49e6c..7ba751490b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1056,36 +1056,31 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { - if (list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_name, lp->ll_name_len, - lp->ll_n1, !lp->ll_empty2, lp->ll_n2) == FAIL) { - return FAIL; - } + tv_list_unlet_range(lp->ll_list, lp->ll_li, lp->ll_n1, !lp->ll_empty2, lp->ll_n2); + } else if (lp->ll_list != NULL) { + // unlet a List item. + tv_list_item_remove(lp->ll_list, lp->ll_li); } else { - if (lp->ll_list != NULL) { - // unlet a List item. - tv_list_item_remove(lp->ll_list, lp->ll_li); - } else { - // unlet a Dictionary item. - dict_T *d = lp->ll_dict; - assert(d != NULL); - dictitem_T *di = lp->ll_di; - bool watched = tv_dict_is_watched(d); - char *key = NULL; - typval_T oldtv; + // unlet a Dictionary item. + dict_T *d = lp->ll_dict; + assert(d != NULL); + dictitem_T *di = lp->ll_di; + bool watched = tv_dict_is_watched(d); + char *key = NULL; + typval_T oldtv; - if (watched) { - tv_copy(&di->di_tv, &oldtv); - // need to save key because dictitem_remove will free it - key = xstrdup(di->di_key); - } + if (watched) { + tv_copy(&di->di_tv, &oldtv); + // need to save key because dictitem_remove will free it + key = xstrdup(di->di_key); + } - tv_dict_item_remove(d, di); + tv_dict_item_remove(d, di); - if (watched) { - tv_dict_watcher_notify(d, key, NULL, &oldtv); - tv_clear(&oldtv); - xfree(key); - } + if (watched) { + tv_dict_watcher_notify(d, key, NULL, &oldtv); + tv_clear(&oldtv); + xfree(key); } } @@ -1094,18 +1089,14 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ /// Unlet one item or a range of items from a list. /// Return OK or FAIL. -static int list_unlet_range(list_T *const l, listitem_T *const li_first, const char *const name, - const size_t name_len, const long n1_arg, const bool has_n2, - const long n2) +static void tv_list_unlet_range(list_T *const l, listitem_T *const li_first, const long n1_arg, + const bool has_n2, const long n2) { assert(l != NULL); // Delete a range of List items. listitem_T *li_last = li_first; long n1 = n1_arg; while (true) { - if (value_check_lock(TV_LIST_ITEM_TV(li_last)->v_lock, name, name_len)) { - return FAIL; - } listitem_T *const li = TV_LIST_ITEM_NEXT(l, li_last); n1++; if (li == NULL || (has_n2 && n2 < n1)) { @@ -1114,7 +1105,6 @@ static int list_unlet_range(list_T *const l, listitem_T *const li_first, const c li_last = li; } tv_list_remove_items(l, li_first, li_last); - return OK; } /// unlet a variable -- cgit From 78d77c03de579845fcaa761e7339c93fcd74efb2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 15 Jun 2023 08:05:26 +0800 Subject: vim-patch:9.0.1631: passing wrong variable type to option gives multiple errors (#24026) Problem: Passing a wrong variable type to an option gives multiple errors. Solution: Bail out early on failure. (closes vim/vim#12504) https://github.com/vim/vim/commit/4c7cb372c17a84c8a35254d93eb37cb854cd39da --- src/nvim/eval/vars.c | 148 +++++++++++++++++++++++++-------------------------- 1 file changed, 72 insertions(+), 76 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 7ba751490b..35ae558006 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -769,17 +769,28 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, return NULL; } - bool hidden; - bool error; const char c1 = *p; *p = NUL; - OptVal curval = get_option_value(arg, NULL, scope, &hidden); - OptVal newval = tv_to_optval(tv, arg, scope, &error); + uint32_t opt_p_flags; + bool hidden; + OptVal curval = get_option_value(arg, &opt_p_flags, scope, &hidden); + OptVal newval = NIL_OPTVAL; + if (curval.type == kOptValTypeNil && arg[0] != 't' && arg[1] != '_') { + semsg(_(e_unknown_option2), arg); + goto theend; + } + if (op != NULL && *op != '=' + && ((curval.type != kOptValTypeString && *op == '.') + || (curval.type == kOptValTypeString && *op != '.'))) { + semsg(_(e_letwrong), op); + goto theend; + } - // Ignore errors for num types - if (newval.type != kOptValTypeNumber && newval.type != kOptValTypeBoolean && error) { - goto end; + bool error; + newval = tv_to_optval(tv, arg, opt_p_flags, &error); + if (error) { + goto theend; } // Don't assume current and new values are of the same type in order to future-proof the code for @@ -789,61 +800,47 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, const bool is_string = curval.type == kOptValTypeString && newval.type == kOptValTypeString; if (op != NULL && *op != '=') { - if (!hidden && ((is_num && *op == '.') || (is_string && *op != '.'))) { - semsg(_(e_letwrong), op); - goto end; - } else { - // number or bool - if (!hidden && is_num) { - Integer cur_n = curval.type == kOptValTypeNumber ? curval.data.number : curval.data.boolean; - Integer new_n = newval.type == kOptValTypeNumber ? newval.data.number : newval.data.boolean; - - switch (*op) { - case '+': - new_n = cur_n + new_n; break; - case '-': - new_n = cur_n - new_n; break; - case '*': - new_n = cur_n * new_n; break; - case '/': - new_n = num_divide(cur_n, new_n); break; - case '%': - new_n = num_modulus(cur_n, new_n); break; - } - - // clamp boolean values - if (newval.type == kOptValTypeBoolean && (new_n > 1 || new_n < -1)) { - new_n = (new_n > 1) ? 1 : -1; - } + if (!hidden && is_num) { // number or bool + Integer cur_n = curval.type == kOptValTypeNumber ? curval.data.number : curval.data.boolean; + Integer new_n = newval.type == kOptValTypeNumber ? newval.data.number : newval.data.boolean; + + switch (*op) { + case '+': + new_n = cur_n + new_n; break; + case '-': + new_n = cur_n - new_n; break; + case '*': + new_n = cur_n * new_n; break; + case '/': + new_n = num_divide(cur_n, new_n); break; + case '%': + new_n = num_modulus(cur_n, new_n); break; + } - newval = kOptValTypeNumber ? NUMBER_OPTVAL(new_n) : BOOLEAN_OPTVAL((TriState)new_n); - } else if (!hidden && is_string && curval.data.string.data != NULL - && newval.data.string.data != NULL) { - // string - OptVal newval_old = newval; - newval = CSTR_AS_OPTVAL(concat_str(curval.data.string.data, newval.data.string.data)); - optval_free(newval_old); + // clamp boolean values + if (newval.type == kOptValTypeBoolean && (new_n > 1 || new_n < -1)) { + new_n = (new_n > 1) ? 1 : -1; } + + newval = kOptValTypeNumber ? NUMBER_OPTVAL(new_n) : BOOLEAN_OPTVAL((TriState)new_n); + } else if (!hidden && is_string + && curval.data.string.data != NULL && newval.data.string.data != NULL) { // string + OptVal newval_old = newval; + newval = CSTR_AS_OPTVAL(concat_str(curval.data.string.data, newval.data.string.data)); + optval_free(newval_old); } } - // If new value is a string and is NULL, show an error if it's not a hidden option. - // For hidden options, just pass the value to `set_option_value` and let it fail silently. - if (hidden || newval.type != kOptValTypeString || newval.data.string.data != NULL) { - const char *err = set_option_value(arg, newval, scope); - arg_end = p; - if (err != NULL) { - emsg(_(err)); - } - } else { - emsg(_(e_stringreq)); + const char *err = set_option_value(arg, newval, scope); + arg_end = p; + if (err != NULL) { + emsg(_(err)); } -end: +theend: *p = c1; optval_free(curval); optval_free(newval); - return arg_end; } @@ -1813,25 +1810,18 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off) /// /// @param[in] tv typval to convert. /// @param[in] option Option name. -/// @param[in] scope Option scope. +/// @param[in] flags Option flags. /// @param[out] error Whether an error occured. /// /// @return Typval converted to OptVal. Must be freed by caller. /// Returns NIL_OPTVAL for invalid option name. -static OptVal tv_to_optval(typval_T *tv, const char *option, int scope, bool *error) +static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, bool *error) { OptVal value = NIL_OPTVAL; char nbuf[NUMBUFLEN]; - uint32_t flags; bool err = false; - OptVal curval = get_option_value(option, &flags, scope, NULL); - - // TODO(famiu): Delegate all of these type-checks to set_option_value() - if (curval.type == kOptValTypeNil) { - // Invalid option name, - value = NIL_OPTVAL; - } else if ((flags & P_FUNC) && tv_is_func(*tv)) { + if ((flags & P_FUNC) && tv_is_func(*tv)) { // If the option can be set to a function reference or a lambda // and the passed value is a function reference, then convert it to // the name (string) of the function reference. @@ -1839,29 +1829,31 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, int scope, bool *er err = strval == NULL; value = CSTR_AS_OPTVAL(strval); } else if (flags & (P_NUM | P_BOOL)) { - varnumber_T n = tv_get_number_chk(tv, &err); - // This could be either "0" or a string that's not a number. So we need to check if it's - // actually a number. + varnumber_T n = (flags & P_NUM) ? tv_get_number_chk(tv, &err) + : tv_get_bool_chk(tv, &err); + // This could be either "0" or a string that's not a number. + // So we need to check if it's actually a number. if (!err && tv->v_type == VAR_STRING && n == 0) { unsigned idx; for (idx = 0; tv->vval.v_string[idx] == '0'; idx++) {} if (tv->vval.v_string[idx] != NUL || idx == 0) { // There's another character after zeros or the string is empty. // In both cases, we are trying to set a num option using a string. + err = true; semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string); } } value = (flags & P_NUM) ? NUMBER_OPTVAL(n) : BOOLEAN_OPTVAL(n == 0 ? kFalse : (n >= 1 ? kTrue : kNone)); - } else if (flags & P_STRING || is_tty_option(option)) { - // Avoid setting string option to a boolean. - if (tv->v_type == VAR_BOOL) { - err = true; - emsg(_(e_stringreq)); - } else { + } else if ((flags & P_STRING) || is_tty_option(option)) { + // Avoid setting string option to a boolean or a special value. + if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { const char *strval = tv_get_string_buf_chk(tv, nbuf); err = strval == NULL; value = CSTR_TO_OPTVAL(strval); + } else if (flags & P_STRING) { + err = true; + emsg(_(e_stringreq)); } } else { abort(); // This should never happen. @@ -1870,19 +1862,23 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, int scope, bool *er if (error != NULL) { *error = err; } - optval_free(curval); return value; } /// Set option "varname" to the value of "varp" for the current buffer/window. static void set_option_from_tv(const char *varname, typval_T *varp) { + int opt_idx = findoption(varname); + if (opt_idx < 0) { + semsg(_(e_unknown_option2), varname); + return; + } + uint32_t opt_p_flags = get_option(opt_idx)->flags; + bool error = false; - OptVal value = tv_to_optval(varp, varname, OPT_LOCAL, &error); + OptVal value = tv_to_optval(varp, varname, opt_p_flags, &error); - if (!error && value.type == kOptValTypeNil) { - semsg(_(e_unknown_option2), varname); - } else if (!error) { + if (!error) { set_option_value_give_err(varname, value, OPT_LOCAL); } -- cgit From 1f8fb7c00048bc217bb9a2bf29c58630d1810d6e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 15 Jun 2023 12:36:21 +0800 Subject: fix(:let): fix error when applying operator to boolean option (#24030) --- src/nvim/eval/vars.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 35ae558006..9b6427fef7 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -817,12 +817,11 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, new_n = num_modulus(cur_n, new_n); break; } - // clamp boolean values - if (newval.type == kOptValTypeBoolean && (new_n > 1 || new_n < -1)) { - new_n = (new_n > 1) ? 1 : -1; + if (curval.type == kOptValTypeNumber) { + newval = NUMBER_OPTVAL(new_n); + } else { + newval = BOOLEAN_OPTVAL(new_n == 0 ? kFalse : (new_n >= 1 ? kTrue : kNone)); } - - newval = kOptValTypeNumber ? NUMBER_OPTVAL(new_n) : BOOLEAN_OPTVAL((TriState)new_n); } else if (!hidden && is_string && curval.data.string.data != NULL && newval.data.string.data != NULL) { // string OptVal newval_old = newval; -- cgit From 2f17ef1fc4b96cf1106fd95ba090d34a2e4b977b Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Thu, 22 Jun 2023 04:09:14 -0700 Subject: fix(messages): use "Vimscript" instead of "VimL" #24111 followup to #24109 fix #16150 --- src/nvim/eval/decode.c | 6 +++--- src/nvim/eval/encode.c | 2 +- src/nvim/eval/encode.h | 4 ++-- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/funcs.h | 4 ++-- src/nvim/eval/typval.c | 32 ++++++++++++++++---------------- src/nvim/eval/typval.h | 4 ++-- src/nvim/eval/typval_defs.h | 4 ++-- src/nvim/eval/typval_encode.h | 4 ++-- 9 files changed, 31 insertions(+), 31 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index acef37e0e8..70a629ea91 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -227,7 +227,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack /// /// @param[out] ret_tv Address where new special dictionary is saved. /// @param[in] len Expected number of items to be populated before list -/// becomes accessible from VimL. It is still valid to +/// becomes accessible from Vimscript. It is still valid to /// underpopulate a list, value only controls how many elements /// will be allocated in advance. @see ListLenSpecials. /// @@ -645,7 +645,7 @@ parse_json_number_ret: } \ } while (0) -/// Convert JSON string into VimL object +/// Convert JSON string into Vimscript object /// /// @param[in] buf String to convert. UTF-8 encoding is assumed. /// @param[in] buf_len Length of the string. @@ -921,7 +921,7 @@ json_decode_string_ret: #undef DICT_LEN -/// Convert msgpack object to a VimL one +/// Convert msgpack object to a Vimscript one int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index be0cf79e85..fc9904a2d9 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -3,7 +3,7 @@ /// @file encode.c /// -/// File containing functions for encoding and decoding VimL values. +/// File containing functions for encoding and decoding Vimscript values. /// /// Split out from eval.c. diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 41e7614fc0..b589b8b13f 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -12,7 +12,7 @@ #include "nvim/garray.h" #include "nvim/vim.h" -/// Convert VimL value to msgpack string +/// Convert Vimscript value to msgpack string /// /// @param[out] packer Packer to save results in. /// @param[in] tv Dumped value. @@ -21,7 +21,7 @@ /// @return OK in case of success, FAIL otherwise. int encode_vim_to_msgpack(msgpack_packer *packer, typval_T *tv, const char *objname); -/// Convert VimL value to :echo output +/// Convert Vimscript value to :echo output /// /// @param[out] packer Packer to save results in. /// @param[in] tv Dumped value. diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 788efe1e84..33f1ed51e5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8304,7 +8304,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -/// f_system - the VimL system() function +/// f_system - the Vimscript system() function static void f_system(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { get_system_output_as_rettv(argvars, rettv, false); diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 65a95196de..5dab12787b 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -9,14 +9,14 @@ #include "nvim/eval/typval_defs.h" #include "nvim/types.h" -/// Prototype of C function that implements VimL function +/// Prototype of C function that implements Vimscript function typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data); /// 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 +/// Structure holding Vimscript function definition typedef struct { char *name; ///< Name of the function. uint8_t min_argc; ///< Minimal number of arguments. diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a891ba1570..bae9880377 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -170,7 +170,7 @@ void tv_list_watch_fix(list_T *const l, const listitem_T *const item) /// Caller should take care of the reference count. /// /// @param[in] len Expected number of items to be populated before list -/// becomes accessible from VimL. It is still valid to +/// becomes accessible from Vimscript. It is still valid to /// underpopulate a list, value only controls how many elements /// will be allocated in advance. Currently does nothing. /// @see ListLenSpecials. @@ -398,7 +398,7 @@ void tv_list_insert(list_T *const l, listitem_T *const ni, listitem_T *const ite } } -/// Insert VimL value into a list +/// Insert Vimscript value into a list /// /// @param[out] l List to insert to. /// @param[in,out] tv Value to insert. Is copied (@see tv_copy()) to an @@ -434,7 +434,7 @@ void tv_list_append(list_T *const l, listitem_T *const item) item->li_next = NULL; } -/// Append VimL value to the end of list +/// Append Vimscript value to the end of list /// /// @param[out] l List to append to. /// @param[in,out] tv Value to append. Is copied (@see tv_copy()) to an @@ -3086,7 +3086,7 @@ void f_list2blob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// /// @param[out] ret_tv Structure where list is saved. /// @param[in] len Expected number of items to be populated before list -/// becomes accessible from VimL. It is still valid to +/// becomes accessible from Vimscript. It is still valid to /// underpopulate a list, value only controls how many elements /// will be allocated in advance. @see ListLenSpecials. /// @@ -3538,7 +3538,7 @@ void tv_clear(typval_T *const tv) //{{{3 Free -/// Free allocated VimL object and value stored inside +/// Free allocated Vimscript object and value stored inside /// /// @param tv Object to free. void tv_free(typval_T *tv) @@ -3716,7 +3716,7 @@ void tv_item_lock(typval_T *const tv, const int deep, const bool lock, const boo recurse--; } -/// Check whether VimL value is locked itself or refers to a locked container +/// Check whether Vimscript value is locked itself or refers to a locked container /// /// @warning Fixed container is not the same as locked. /// @@ -3815,7 +3815,7 @@ bool value_check_lock(VarLockStatus lock, const char *name, size_t name_len) static int tv_equal_recurse_limit; -/// Compare two VimL values +/// Compare two Vimscript values /// /// Like "==", but strings and numbers are different, as well as floats and /// numbers. @@ -4011,7 +4011,7 @@ static const char *const str_errors[] = { #undef FUNC_ERROR -/// Check that given value is a VimL String or can be "cast" to it. +/// Check that given value is a Vimscript String or can be "cast" to it. /// /// Error messages are compatible with tv_get_string_chk() previously used for /// the same purpose. @@ -4044,7 +4044,7 @@ bool tv_check_str(const typval_T *const tv) //{{{2 Get -/// Get the number value of a VimL object +/// Get the number value of a Vimscript object /// /// @note Use tv_get_number_chk() if you need to determine whether there was an /// error. @@ -4060,7 +4060,7 @@ varnumber_T tv_get_number(const typval_T *const tv) return tv_get_number_chk(tv, &error); } -/// Get the number value of a VimL object +/// Get the number value of a Vimscript object /// /// @param[in] tv Object to get value from. /// @param[out] ret_error If type error occurred then `true` will be written @@ -4119,7 +4119,7 @@ varnumber_T tv_get_bool_chk(const typval_T *const tv, bool *const ret_error) return tv_get_number_chk(tv, ret_error); } -/// Get the line number from VimL object +/// Get the line number from Vimscript object /// /// @param[in] tv Object to get value from. Is expected to be a number or /// a special string like ".", "$", … (works with current buffer @@ -4142,7 +4142,7 @@ linenr_T tv_get_lnum(const typval_T *const tv) return lnum; } -/// Get the floating-point value of a VimL object +/// Get the floating-point value of a Vimscript object /// /// Raises an error if object is not number or floating-point. /// @@ -4385,7 +4385,7 @@ int tv_check_for_list_or_blob_arg(const typval_T *const args, const int idx) return OK; } -/// Get the string value of a "stringish" VimL object. +/// Get the string value of a "stringish" Vimscript object. /// /// @param[in] tv Object to get value of. /// @param buf Buffer used to hold numbers and special variables converted to @@ -4430,7 +4430,7 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) return NULL; } -/// Get the string value of a "stringish" VimL object. +/// Get the string value of a "stringish" Vimscript object. /// /// @warning For number and special values it uses a single, static buffer. It /// may be used only once, next call to tv_get_string may reuse it. Use @@ -4449,7 +4449,7 @@ const char *tv_get_string_chk(const typval_T *const tv) return tv_get_string_buf_chk(tv, mybuf); } -/// Get the string value of a "stringish" VimL object. +/// Get the string value of a "stringish" Vimscript object. /// /// @warning For number and special values it uses a single, static buffer. It /// may be used only once, next call to tv_get_string may reuse it. Use @@ -4471,7 +4471,7 @@ const char *tv_get_string(const typval_T *const tv) return tv_get_string_buf((typval_T *)tv, mybuf); } -/// Get the string value of a "stringish" VimL object. +/// Get the string value of a "stringish" Vimscript object. /// /// @note tv_get_string_chk() and tv_get_string_buf_chk() are similar, but /// return NULL on error. diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index e7b2499346..0b42a473cf 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -312,7 +312,7 @@ static inline void tv_blob_set(blob_T *const blob, int idx, uint8_t c) ((uint8_t *)blob->bv_ga.ga_data)[idx] = c; } -/// Initialize VimL object +/// Initialize Vimscript object /// /// Initializes to unlocked VAR_UNKNOWN object. /// @@ -424,7 +424,7 @@ static inline bool tv_get_float_chk(const typval_T *tv, float_T *ret_f) /// /// Raises an error if object is not number or floating-point. /// -/// @param[in] tv VimL object to get value from. +/// @param[in] tv Vimscript object to get value from. /// @param[out] ret_f Location where resulting float is stored. /// /// @return true in case of success, false if tv is not a number or float. diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 767603ac0e..4099877539 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -10,7 +10,7 @@ #include "nvim/pos.h" #include "nvim/types.h" -/// Type used for VimL VAR_NUMBER values +/// Type used for Vimscript VAR_NUMBER values typedef int64_t varnumber_T; typedef uint64_t uvarnumber_T; @@ -100,7 +100,7 @@ typedef enum { VAR_FIXED = 2, ///< Locked forever. } VarLockStatus; -/// VimL variable types, for use in typval_T.v_type +/// Vimscript variable types, for use in typval_T.v_type typedef enum { VAR_UNKNOWN = 0, ///< Unknown (unspecified) value. VAR_NUMBER, ///< Number, .v_number is used. diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 171b0417d0..cf01926030 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -30,7 +30,7 @@ typedef enum { kMPConvPartialEnd, ///< Already converted everything. } MPConvPartialStage; -/// Structure representing current VimL to messagepack conversion state +/// Structure representing current Vimscript to messagepack conversion state typedef struct { MPConvStackValType type; ///< Type of the stack entry. typval_T *tv; ///< Currently converted typval_T. @@ -60,7 +60,7 @@ typedef struct { } data; ///< Data to convert. } MPConvStackVal; -/// Stack used to convert VimL values to messagepack. +/// Stack used to convert Vimscript values to messagepack. typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack; // Defines for MPConvStack -- cgit From aa362a2af8ce353d7082834a54bcc124ebd2a026 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 29 Jun 2023 15:48:42 +0800 Subject: refactor: remove some casts to char * (#24200) --- src/nvim/eval/funcs.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 33f1ed51e5..99fec3d773 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -873,8 +873,7 @@ static void f_confirm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (!error) { - rettv->vval.v_number = do_dialog(type, NULL, (char *)message, (char *)buttons, def, NULL, - false); + rettv->vval.v_number = do_dialog(type, NULL, message, buttons, def, NULL, false); } } -- cgit From 2493815290c4cb5b1fb97b6d010c10bdf2d47a58 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 30 Jun 2023 21:13:08 +0800 Subject: refactor: fix clang/PVS warnings (#24213) --- src/nvim/eval/typval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index bae9880377..abe31aab75 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -673,6 +673,7 @@ int tv_list_assign_range(list_T *const dest, list_T *const src, const long idx1_ idx = idx1; dest_li = first_li; for (src_li = tv_list_first(src); src_li != NULL;) { + assert(dest_li != NULL); if (op != NULL && *op != '=') { eexe_mod_op(TV_LIST_ITEM_TV(dest_li), TV_LIST_ITEM_TV(src_li), op); } else { @@ -683,7 +684,6 @@ int tv_list_assign_range(list_T *const dest, list_T *const src, const long idx1_ if (src_li == NULL || (!empty_idx2 && idx2 == idx)) { break; } - assert(dest_li != NULL); if (TV_LIST_ITEM_NEXT(dest, dest_li) == NULL) { // Need to add an empty item. tv_list_append_number(dest, 0); @@ -1622,7 +1622,7 @@ const char *tv_list_find_str(list_T *const l, const int n) /// Like tv_list_find() but when a negative index is used that is not found use /// zero and set "idx" to zero. Used for first index of a range. -listitem_T *tv_list_find_index(list_T *const l, long *const idx) +static listitem_T *tv_list_find_index(list_T *const l, long *const idx) FUNC_ATTR_WARN_UNUSED_RESULT { listitem_T *li = tv_list_find(l, (int)(*idx)); -- cgit From a741c7fd0465c949a0016fcbee5f4526b65f8c02 Mon Sep 17 00:00:00 2001 From: Alexandre Teoi Date: Sat, 1 Jul 2023 10:33:51 -0300 Subject: fix(api): nvim_parse_cmd error message in pcall() #23297 Problem: nvim_parse_cmd() in pcall() may show an error message (side-effect): :lua pcall(vim.api.nvim_parse_cmd, vim.fn.getcmdline(), {}) E16: Invalid range Solution: Avoid emsg() in the nvim_parse_cmd() codepath. - refactor(api): add error message output parameter to get_address() - fix: null check emsg() parameter - refactor: remove emsg_off workaround from do_incsearch_highlighting() - refactor: remove emsg_off workaround from cmdpreview_may_show() - refactor: remove remaining calls to emsg() from parse_cmd_address() and get_address() - (refactor): lint set_cmd_dflall_range() - refactor: addr_error() - move output parameter to return value Fix #20339 TODO: These are the functions called by `get_address()`: ``` nvim_parse_cmd() -> parse_cmdline() -> parse_cmd_address() -> get_address() skipwhite() addr_error() qf_get_cur_idx() qf_get_cur_valid_idx() qf_get_size() qf_get_valid_size() mark_get() mark_check() assert() skip_regexp() magic_isset() > do_search() > searchit() ascii_isdigit() getdigits() getdigits_int32() compute_buffer_local_count() hasFolding() ``` From these functions, I found at least two that call emsg directly: - do_search() - seems to be simple to refactor - searchit() - will be more challenging because it may generate multiple error messages, which can't be handled by the current `errormsg` out-parameter. For example, it makes multiple calls to `vim_regexec_multi()` in a loop that possibly generate error messages, and later `searchit()` itself may generate another one: - https://github.com/neovim/neovim/blob/c194acbfc479d8e5839fa629363f93f6550d035c/src/nvim/search.c#L631-L647 - https://github.com/neovim/neovim/blob/c194acbfc479d8e5839fa629363f93f6550d035c/src/nvim/search.c#L939-L954 --------- Co-authored-by: Justin M. Keyes --- src/nvim/eval/funcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 99fec3d773..f53c5fc0c5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1716,7 +1716,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) emsg_off++; } size_t len; - char *errormsg = NULL; + const char *errormsg = NULL; char *result = eval_vars((char *)s, s, &len, NULL, &errormsg, NULL, false); if (p_verbose == 0) { emsg_off--; @@ -1781,7 +1781,7 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// Expand all the special characters in a command string. static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char *errormsg = NULL; + const char *errormsg = NULL; bool emsgoff = true; if (argvars[1].v_type == VAR_DICT -- cgit From fcf3519c65a2d6736de437f686e788684a6c8564 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 17 Apr 2023 22:18:58 +0200 Subject: refactor: remove long long is 32-bits even on 64-bit windows which makes the type suboptimal for a codebase meant to be cross-platform. --- src/nvim/eval/buffer.c | 4 ++-- src/nvim/eval/funcs.c | 19 ++++++++++--------- src/nvim/eval/window.c | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index aad88619b7..0fe3f5444c 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -126,7 +126,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ FUNC_ATTR_NONNULL_ARG(4, 5) { linenr_T lnum = lnum_arg + (append ? 1 : 0); - long added = 0; + int added = 0; // When using the current buffer ml_mfp will be set if needed. Useful when // setline() is used on startup. For other buffers the buffer must be @@ -442,7 +442,7 @@ void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (last > curbuf->b_ml.ml_line_count) { last = curbuf->b_ml.ml_line_count; } - const long count = last - first + 1; + const int count = last - first + 1; // When coming here from Insert mode, sync undo, so that this can be // undone separately from what was previously inserted. diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f53c5fc0c5..f348a61075 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -886,7 +886,7 @@ static void f_copy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "count()" function static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - long n = 0; + varnumber_T n = 0; int ic = 0; bool error = false; @@ -1085,8 +1085,9 @@ static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// Otherwise use the column number as a byte offset. static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) { - long lnum, col; - long coladd = 0; + linenr_T lnum; + colnr_T col; + colnr_T coladd = 0; bool set_curswant = true; rettv->vval.v_number = -1; @@ -1114,12 +1115,12 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) } else if (lnum == 0) { lnum = curwin->w_cursor.lnum; } - col = (long)tv_get_number_chk(&argvars[1], NULL); + col = (colnr_T)tv_get_number_chk(&argvars[1], NULL); if (charcol) { - col = buf_charidx_to_byteidx(curbuf, (linenr_T)lnum, (int)col) + 1; + col = buf_charidx_to_byteidx(curbuf, lnum, (int)col) + 1; } if (argvars[2].v_type != VAR_UNKNOWN) { - coladd = (long)tv_get_number_chk(&argvars[2], NULL); + coladd = (colnr_T)tv_get_number_chk(&argvars[2], NULL); } } else { emsg(_(e_invarg)); @@ -1129,12 +1130,12 @@ static void set_cursorpos(typval_T *argvars, typval_T *rettv, bool charcol) return; // type error; errmsg already given } if (lnum > 0) { - curwin->w_cursor.lnum = (linenr_T)lnum; + curwin->w_cursor.lnum = lnum; } if (col > 0) { - curwin->w_cursor.col = (colnr_T)col - 1; + curwin->w_cursor.col = col - 1; } - curwin->w_cursor.coladd = (colnr_T)coladd; + curwin->w_cursor.coladd = coladd; // Make sure the cursor is in a valid position. check_cursor(); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 30c295de46..26f5414565 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -266,7 +266,7 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } else { // Extract the window count (if specified). e.g. winnr('3j') char *endp; - long count = strtol(arg, &endp, 10); + int count = (int)strtol(arg, &endp, 10); if (count <= 0) { // if count is not specified, default to 1 count = 1; -- cgit From aa4e47f704c53ab1d825260d2bf34e2872e3ca89 Mon Sep 17 00:00:00 2001 From: Sean Dewar Date: Fri, 23 Jun 2023 22:32:07 +0100 Subject: fix(api): disallow some more functions during textlock Problem: nvim_buf_set_text(), nvim_open_term() and termopen() all change buffer text, which is forbidden during textlock. Additionally, nvim_open_term() and termopen() may be used to convert the cmdwin buffer into a terminal buffer, which is weird. Solution: Allow nvim_buf_set_text() and nvim_open_term() in the cmdwin, but disallow nvim_open_term() from converting the cmdwin buffer into a terminal buffer. termopen() is not allowed in the cmdwin (as it always operates on curbuf), so just check text_locked(). Also happens to improve the error in #21055: nvim_buf_set_text() was callable during textlock, but happened to check textlock indirectly via u_save(); however, this caused the error to be overwritten by an unhelpful "Failed to save undo information" message when msg_list == NULL (e.g: an `` mapping invoked outside of do_cmdline()). --- src/nvim/eval/funcs.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f348a61075..7c3c5cc274 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8385,7 +8385,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (check_secure()) { return; } - + if (text_locked()) { + text_locked_msg(); + return; + } if (curbuf->b_changed) { emsg(_("Can only call this function in an unmodified buffer")); return; -- cgit From 559c4cfd52e385c1b9bd5fa66a0eeb7e8d9e018a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 8 Jul 2023 08:27:39 +0800 Subject: fix(startup): run embedded Nvim with real path (#24282) fix(startup): run embedded process with real path --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7c3c5cc274..e823e131b1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4120,7 +4120,7 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) env = create_environment(job_env, clear_env, pty, term_name); - Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, pty, + Channel *chan = channel_job_start(argv, NULL, on_stdout, on_stderr, on_exit, pty, rpc, overlapped, detach, stdin_mode, cwd, width, height, env, &rettv->vval.v_number); if (chan) { @@ -6678,7 +6678,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // The last item of argv must be NULL argv[i] = NULL; - Channel *chan = channel_job_start(argv, CALLBACK_READER_INIT, + Channel *chan = channel_job_start(argv, NULL, CALLBACK_READER_INIT, CALLBACK_READER_INIT, CALLBACK_NONE, false, true, false, false, kChannelStdinPipe, NULL, 0, 0, NULL, @@ -8455,7 +8455,7 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const bool detach = false; ChannelStdinMode stdin_mode = kChannelStdinPipe; uint16_t term_width = (uint16_t)MAX(0, curwin->w_width_inner - win_col_off(curwin)); - Channel *chan = channel_job_start(argv, on_stdout, on_stderr, on_exit, + Channel *chan = channel_job_start(argv, NULL, on_stdout, on_stderr, on_exit, pty, rpc, overlapped, detach, stdin_mode, cwd, term_width, (uint16_t)curwin->w_height_inner, env, &rettv->vval.v_number); -- cgit From b8b77820371978a5f937ccc0db356574ae33371b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 26 Jul 2023 15:18:09 +0800 Subject: vim-patch:partial:8.1.1981: the evalfunc.c file is too big (#24490) Problem: The evalfunc.c file is too big. Solution: Move undo functions to undo.c. Move cmdline functions to ex_getln.c. Move some container functions to list.c. https://github.com/vim/vim/commit/08c308aeb5e7dfa18fa61f261b0bff79517a4883 Undo functions only. Cmdline functions have already been moved. A lot of container functions have been added to eval/funcs.c instead of list.c in previously ported Vim 8.2.x patches, so deal with that later. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e823e131b1..177f64ebba 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -114,7 +114,6 @@ #include "nvim/syntax.h" #include "nvim/tag.h" #include "nvim/ui.h" -#include "nvim/undo.h" #include "nvim/version.h" #include "nvim/vim.h" #include "nvim/window.h" @@ -8629,43 +8628,6 @@ static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = n; } -/// "undofile(name)" function -static void f_undofile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - const char *const fname = tv_get_string(&argvars[0]); - - if (*fname == NUL) { - // If there is no file name there will be no undo file. - rettv->vval.v_string = NULL; - } else { - char *ffname = FullName_save(fname, true); - - if (ffname != NULL) { - rettv->vval.v_string = u_get_undo_file_name(ffname, false); - } - xfree(ffname); - } -} - -/// "undotree()" function -static void f_undotree(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_dict_alloc_ret(rettv); - - dict_T *dict = rettv->vval.v_dict; - - tv_dict_add_nr(dict, S_LEN("synced"), (varnumber_T)curbuf->b_u_synced); - tv_dict_add_nr(dict, S_LEN("seq_last"), (varnumber_T)curbuf->b_u_seq_last); - tv_dict_add_nr(dict, S_LEN("save_last"), - (varnumber_T)curbuf->b_u_save_nr_last); - tv_dict_add_nr(dict, S_LEN("seq_cur"), (varnumber_T)curbuf->b_u_seq_cur); - tv_dict_add_nr(dict, S_LEN("time_cur"), (varnumber_T)curbuf->b_u_time_cur); - tv_dict_add_nr(dict, S_LEN("save_cur"), (varnumber_T)curbuf->b_u_save_nr_cur); - - tv_dict_add_list(dict, S_LEN("entries"), u_eval_tree(curbuf->b_u_oldhead)); -} - /// "virtcol(string, bool)" function static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From 8cbb2477cf70ea29105e3df17308e6d6a067c8e6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 09:43:00 +0800 Subject: vim-patch:8.2.1969: Vim9: map() may change the list or dict item type Problem: Vim9: map() may change the list or dict item type. Solution: Add mapnew(). https://github.com/vim/vim/commit/ea696852e7abcdebaf7f17a7f23dc90df1f5e2ed Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 12 ------------ src/nvim/eval/typval.c | 13 +++++-------- 2 files changed, 5 insertions(+), 20 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 177f64ebba..0506c08b07 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2097,12 +2097,6 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } } -/// "filter()" function -static void f_filter(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - filter_map(argvars, rettv, false); -} - /// "finddir({fname}[, {path}[, {count}]])" function static void f_finddir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -4488,12 +4482,6 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv); } -/// "map()" function -static void f_map(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - filter_map(argvars, rettv, true); -} - static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index abe31aab75..5b977e93c9 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3249,22 +3249,19 @@ void tv_blob_alloc_ret(typval_T *const ret_tv) /// /// @param[in] from Blob object to copy from. /// @param[out] to Blob object to copy to. -void tv_blob_copy(typval_T *const from, typval_T *const to) - FUNC_ATTR_NONNULL_ALL +void tv_blob_copy(blob_T *const from, typval_T *const to) + FUNC_ATTR_NONNULL_ARG(2) { - assert(from->v_type == VAR_BLOB); - to->v_type = VAR_BLOB; to->v_lock = VAR_UNLOCKED; - if (from->vval.v_blob == NULL) { + if (from == NULL) { to->vval.v_blob = NULL; } else { tv_blob_alloc_ret(to); - int len = from->vval.v_blob->bv_ga.ga_len; + int len = from->bv_ga.ga_len; if (len > 0) { - to->vval.v_blob->bv_ga.ga_data - = xmemdup(from->vval.v_blob->bv_ga.ga_data, (size_t)len); + to->vval.v_blob->bv_ga.ga_data = xmemdup(from->bv_ga.ga_data, (size_t)len); } to->vval.v_blob->bv_ga.ga_len = len; to->vval.v_blob->bv_ga.ga_maxlen = len; -- cgit From c5576fcc8003280489c0aa0323a966e6de33e31f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 13:41:43 +0800 Subject: vim-patch:8.2.3848: cannot use reduce() for a string Problem: Cannot use reduce() for a string. Solution: Make reduce() work with a string. (Naruhiko Nishino, closes vim/vim#9366) https://github.com/vim/vim/commit/0ccb5842f5fb103763d106c7aa364d758343c35a Omit tv_get_first_char() as it doesn't really save much code. Co-authored-by: rbtnn --- src/nvim/eval/funcs.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 0506c08b07..bf11fdf029 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -150,8 +150,12 @@ static const char *e_invalwindow = N_("E957: Invalid window number"); static const char e_invalid_submatch_number_nr[] = N_("E935: Invalid submatch number: %d"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); +static const char e_string_list_or_blob_required[] + = N_("E1098: String, List or Blob required"); static const char e_missing_function_argument[] = N_("E1132: Missing function argument"); +static const char e_string_expected_for_argument_nr[] + = N_("E1253: String expected for argument %d"); /// Dummy va_list for passing to vim_snprintf /// @@ -6168,11 +6172,16 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// "reduce(list, { accumulator, element -> value } [, initial])" function +/// "reduce(blob, { accumulator, element -> value } [, initial])" function +/// "reduce(string, { accumulator, element -> value } [, initial])" function static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - if (argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) { - emsg(_(e_listblobreq)); - return; + const int called_emsg_start = called_emsg; + + if (argvars[0].v_type != VAR_STRING + && argvars[0].v_type != VAR_LIST + && argvars[0].v_type != VAR_BLOB) { + emsg(_(e_string_list_or_blob_required)); } const char *func_name; @@ -6217,7 +6226,6 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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)) { @@ -6232,6 +6240,44 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } tv_list_set_lock(l, prev_locked); } + } else if (argvars[0].v_type == VAR_STRING) { + const char *p = tv_get_string(&argvars[0]); + int len; + + if (argvars[2].v_type == VAR_UNKNOWN) { + if (*p == NUL) { + semsg(_(e_reduceempty), "String"); + return; + } + len = utfc_ptr2len(p); + *rettv = (typval_T){ + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrnsave(p, (size_t)len), + }; + p += len; + } else if (argvars[2].v_type != VAR_STRING) { + semsg(_(e_string_expected_for_argument_nr), 3); + return; + } else { + tv_copy(&argvars[2], rettv); + } + + for (; *p != NUL; p += len) { + argv[0] = *rettv; + len = utfc_ptr2len(p); + argv[1] = (typval_T){ + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrnsave(p, (size_t)len), + }; + const int r = call_func(func_name, -1, rettv, 2, argv, &funcexe); + tv_clear(&argv[0]); + tv_clear(&argv[1]); + if (r == FAIL || called_emsg != called_emsg_start) { + break; + } + } } else { const blob_T *const b = argvars[0].vval.v_blob; int i; -- cgit From b193674b4a1dce1b348489fa13dd42254b9a3ebb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 14:12:24 +0800 Subject: vim-patch:partial:8.2.3849: functions implementing reduce and map are too long Problem: Functions implementing reduce and map are too long. Solution: Use a function for each type of value. Add a few more test cases and add to the help. (Yegappan Lakshmanan, closes vim/vim#9370) https://github.com/vim/vim/commit/389b72196e6aaeafe3f907c73d271f2c6b931140 Partial port as this doesn't include handling for non-materialized List. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 241 +++++++++++++++++++++++++++++--------------------- 1 file changed, 138 insertions(+), 103 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index bf11fdf029..d5d9726397 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6171,17 +6171,150 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } +/// reduce() on a List +static void reduce_list(typval_T *argvars, const char *func_name, funcexe_T *funcexe, + typval_T *rettv) +{ + list_T *const l = argvars[0].vval.v_list; + const int called_emsg_start = called_emsg; + + typval_T initial; + const listitem_T *li = NULL; + 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) { + return; + } + + const VarLockStatus prev_locked = tv_list_locked(l); + + tv_list_set_lock(l, VAR_FIXED); // disallow the list changing here + for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { + typval_T argv[3]; + argv[0] = *rettv; + argv[1] = *TV_LIST_ITEM_TV(li); + rettv->v_type = VAR_UNKNOWN; + const int r = call_func(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); +} + +/// reduce() on a String +static void reduce_string(typval_T *argvars, const char *func_name, funcexe_T *funcexe, + typval_T *rettv) +{ + const char *p = tv_get_string(&argvars[0]); + int len; + const int called_emsg_start = called_emsg; + + if (argvars[2].v_type == VAR_UNKNOWN) { + if (*p == NUL) { + semsg(_(e_reduceempty), "String"); + return; + } + len = utfc_ptr2len(p); + *rettv = (typval_T){ + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrnsave(p, (size_t)len), + }; + p += len; + } else if (argvars[2].v_type != VAR_STRING) { + semsg(_(e_string_expected_for_argument_nr), 3); + return; + } else { + tv_copy(&argvars[2], rettv); + } + + for (; *p != NUL; p += len) { + typval_T argv[3]; + argv[0] = *rettv; + len = utfc_ptr2len(p); + argv[1] = (typval_T){ + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval.v_string = xstrnsave(p, (size_t)len), + }; + const int r = call_func(func_name, -1, rettv, 2, argv, funcexe); + tv_clear(&argv[0]); + tv_clear(&argv[1]); + if (r == FAIL || called_emsg != called_emsg_start) { + break; + } + } +} + +/// reduce() on a Blob +static void reduce_blob(typval_T *argvars, const char *func_name, funcexe_T *funcexe, + typval_T *rettv) +{ + const blob_T *const b = argvars[0].vval.v_blob; + const int called_emsg_start = called_emsg; + + typval_T initial; + int i; + if (argvars[2].v_type == VAR_UNKNOWN) { + if (tv_blob_len(b) == 0) { + semsg(_(e_reduceempty), "Blob"); + return; + } + initial = (typval_T){ + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .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++) { + typval_T argv[3]; + argv[0] = *rettv; + argv[1] = (typval_T){ + .v_type = VAR_NUMBER, + .v_lock = VAR_UNLOCKED, + .vval.v_number = tv_blob_get(b, i), + }; + const int r = call_func(func_name, -1, rettv, 2, argv, funcexe); + if (r == FAIL || called_emsg != called_emsg_start) { + return; + } + } +} + /// "reduce(list, { accumulator, element -> value } [, initial])" function /// "reduce(blob, { accumulator, element -> value } [, initial])" function /// "reduce(string, { accumulator, element -> value } [, initial])" function static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - const int called_emsg_start = called_emsg; - if (argvars[0].v_type != VAR_STRING && argvars[0].v_type != VAR_LIST && argvars[0].v_type != VAR_BLOB) { emsg(_(e_string_list_or_blob_required)); + return; } const char *func_name; @@ -6203,110 +6336,12 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) funcexe.fe_evaluate = true; funcexe.fe_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); - - 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(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); - } + reduce_list(argvars, func_name, &funcexe, rettv); } else if (argvars[0].v_type == VAR_STRING) { - const char *p = tv_get_string(&argvars[0]); - int len; - - if (argvars[2].v_type == VAR_UNKNOWN) { - if (*p == NUL) { - semsg(_(e_reduceempty), "String"); - return; - } - len = utfc_ptr2len(p); - *rettv = (typval_T){ - .v_type = VAR_STRING, - .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrnsave(p, (size_t)len), - }; - p += len; - } else if (argvars[2].v_type != VAR_STRING) { - semsg(_(e_string_expected_for_argument_nr), 3); - return; - } else { - tv_copy(&argvars[2], rettv); - } - - for (; *p != NUL; p += len) { - argv[0] = *rettv; - len = utfc_ptr2len(p); - argv[1] = (typval_T){ - .v_type = VAR_STRING, - .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrnsave(p, (size_t)len), - }; - const int r = call_func(func_name, -1, rettv, 2, argv, &funcexe); - tv_clear(&argv[0]); - tv_clear(&argv[1]); - if (r == FAIL || called_emsg != called_emsg_start) { - break; - } - } + reduce_string(argvars, func_name, &funcexe, rettv); } 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(func_name, -1, rettv, 2, argv, &funcexe) == FAIL) { - return; - } - } + reduce_blob(argvars, func_name, &funcexe, rettv); } } -- cgit From 1918e1ea6d0192712e0a03926e2965a7aac0955e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 16:22:11 +0800 Subject: vim-patch:9.0.0359: error message for wrong argument type is not specific Problem: Error message for wrong argument type is not specific. Solution: Include more information in the error. (Yegappan Lakshmanan, closes vim/vim#11037) https://github.com/vim/vim/commit/8deb2b30c77035bb682ccf80b781455ac1d6038b Cherry-pick test_listdict.vim changes from patch 8.2.4809. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d5d9726397..ec55ab512b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -154,8 +154,6 @@ static const char e_string_list_or_blob_required[] = N_("E1098: String, List or Blob required"); static const char e_missing_function_argument[] = N_("E1132: Missing function argument"); -static const char e_string_expected_for_argument_nr[] - = N_("E1253: String expected for argument %d"); /// Dummy va_list for passing to vim_snprintf /// @@ -1187,18 +1185,16 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "deepcopy()" function static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - int noref = 0; + if (tv_check_for_opt_bool_arg(argvars, 1) == FAIL) { + return; + } + varnumber_T noref = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - noref = (int)tv_get_bool_chk(&argvars[1], NULL); - } - if (noref < 0 || noref > 1) { - semsg(_(e_using_number_as_bool_nr), noref); - } else { - var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 - ? get_copyID() - : 0)); + noref = tv_get_bool_chk(&argvars[1], NULL); } + + var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 ? get_copyID() : 0)); } /// "delete()" function @@ -6236,8 +6232,7 @@ static void reduce_string(typval_T *argvars, const char *func_name, funcexe_T *f .vval.v_string = xstrnsave(p, (size_t)len), }; p += len; - } else if (argvars[2].v_type != VAR_STRING) { - semsg(_(e_string_expected_for_argument_nr), 3); + } else if (tv_check_for_string_arg(argvars, 2) == FAIL) { return; } else { tv_copy(&argvars[2], rettv); @@ -6281,8 +6276,7 @@ static void reduce_blob(typval_T *argvars, const char *func_name, funcexe_T *fun .vval.v_number = tv_blob_get(b, 0), }; i = 1; - } else if (argvars[2].v_type != VAR_NUMBER) { - emsg(_(e_number_exp)); + } else if (tv_check_for_number_arg(argvars, 2) == FAIL) { return; } else { initial = argvars[2]; -- cgit From 1ed12a2e10708f0d4ce39e5adb94d189455f4d98 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 16:17:22 +0800 Subject: vim-patch:9.0.0548: reduce() with a compiled lambda could be faster Problem: reduce() with a compiled lambda could be faster. Solution: Call eval_expr_typval() instead of call_func() directly. https://github.com/vim/vim/commit/f1c60d4bf10794265b828afd9c5f7eddacada10b Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ec55ab512b..044dabb058 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6167,9 +6167,10 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -/// reduce() on a List -static void reduce_list(typval_T *argvars, const char *func_name, funcexe_T *funcexe, - typval_T *rettv) +/// Implementation of reduce() for list "argvars[0]", using the function "expr" +/// starting with the optional initial value argvars[2] and return the result in +/// "rettv". +static void reduce_list(typval_T *argvars, typval_T *expr, typval_T *rettv) { list_T *const l = argvars[0].vval.v_list; const int called_emsg_start = called_emsg; @@ -6203,7 +6204,9 @@ static void reduce_list(typval_T *argvars, const char *func_name, funcexe_T *fun argv[0] = *rettv; argv[1] = *TV_LIST_ITEM_TV(li); rettv->v_type = VAR_UNKNOWN; - const int r = call_func(func_name, -1, rettv, 2, argv, funcexe); + + const int r = eval_expr_typval(expr, argv, 2, rettv); + tv_clear(&argv[0]); if (r == FAIL || called_emsg != called_emsg_start) { break; @@ -6212,9 +6215,10 @@ static void reduce_list(typval_T *argvars, const char *func_name, funcexe_T *fun tv_list_set_lock(l, prev_locked); } -/// reduce() on a String -static void reduce_string(typval_T *argvars, const char *func_name, funcexe_T *funcexe, - typval_T *rettv) +/// Implementation of reduce() for String "argvars[0]" using the function "expr" +/// starting with the optional initial value "argvars[2]" and return the result +/// in "rettv". +static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) { const char *p = tv_get_string(&argvars[0]); int len; @@ -6247,7 +6251,9 @@ static void reduce_string(typval_T *argvars, const char *func_name, funcexe_T *f .v_lock = VAR_UNLOCKED, .vval.v_string = xstrnsave(p, (size_t)len), }; - const int r = call_func(func_name, -1, rettv, 2, argv, funcexe); + + const int r = eval_expr_typval(expr, argv, 2, rettv); + tv_clear(&argv[0]); tv_clear(&argv[1]); if (r == FAIL || called_emsg != called_emsg_start) { @@ -6256,9 +6262,10 @@ static void reduce_string(typval_T *argvars, const char *func_name, funcexe_T *f } } -/// reduce() on a Blob -static void reduce_blob(typval_T *argvars, const char *func_name, funcexe_T *funcexe, - typval_T *rettv) +/// Implementaion of reduce() for Blob "argvars[0]" using the function "expr" +/// starting with the optional initial value "argvars[2]" and return the result +/// in "rettv". +static void reduce_blob(typval_T *argvars, typval_T *expr, typval_T *rettv) { const blob_T *const b = argvars[0].vval.v_blob; const int called_emsg_start = called_emsg; @@ -6292,7 +6299,9 @@ static void reduce_blob(typval_T *argvars, const char *func_name, funcexe_T *fun .v_lock = VAR_UNLOCKED, .vval.v_number = tv_blob_get(b, i), }; - const int r = call_func(func_name, -1, rettv, 2, argv, funcexe); + + const int r = eval_expr_typval(expr, argv, 2, rettv); + if (r == FAIL || called_emsg != called_emsg_start) { return; } @@ -6312,12 +6321,10 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } 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); + func_name = partial_name(argvars[1].vval.v_partial); } else { func_name = tv_get_string(&argvars[1]); } @@ -6326,16 +6333,12 @@ static void f_reduce(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - funcexe_T funcexe = FUNCEXE_INIT; - funcexe.fe_evaluate = true; - funcexe.fe_partial = partial; - if (argvars[0].v_type == VAR_LIST) { - reduce_list(argvars, func_name, &funcexe, rettv); + reduce_list(argvars, &argvars[1], rettv); } else if (argvars[0].v_type == VAR_STRING) { - reduce_string(argvars, func_name, &funcexe, rettv); + reduce_string(argvars, &argvars[1], rettv); } else { - reduce_blob(argvars, func_name, &funcexe, rettv); + reduce_blob(argvars, &argvars[1], rettv); } } -- cgit From de6b58f65913931c4f18267cdbb9bfef3ceec3a9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 17 Aug 2023 21:56:03 +0800 Subject: vim-patch:8.2.3867: implementation of some list functions too complicated (#24757) Problem: Implementation of some list functions too complicated. Solution: Refactor do_sort_uniq(), f_count() and extend() (Yegappan Lakshmanan, closes vim/vim#9378) https://github.com/vim/vim/commit/d92813a59877c707e4b64bea6d786aad152acb45 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 338 ++++++++++++++++++++++++++++-------------------- src/nvim/eval/typval.c | 345 +++++++++++++++++++++++++------------------------ 2 files changed, 368 insertions(+), 315 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 044dabb058..b0e0fffe5c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -884,6 +884,86 @@ static void f_copy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) var_item_copy(NULL, &argvars[0], rettv, false, 0); } +/// Count the number of times "needle" occurs in string "haystack". +/// +/// @param ic ignore case +static varnumber_T count_string(const char *haystack, const char *needle, bool ic) +{ + varnumber_T n = 0; + const char *p = haystack; + + if (p == NULL || needle == NULL || *needle == NUL) { + return 0; + } + + if (ic) { + const size_t len = strlen(needle); + + while (*p != NUL) { + if (mb_strnicmp(p, needle, len) == 0) { + n++; + p += len; + } else { + MB_PTR_ADV(p); + } + } + } else { + const char *next; + while ((next = strstr(p, needle)) != NULL) { + n++; + p = next + strlen(needle); + } + } + + return n; +} + +/// Count the number of times item "needle" occurs in List "l" starting at index "idx". +/// +/// @param ic ignore case +static varnumber_T count_list(list_T *l, typval_T *needle, int64_t idx, bool ic) +{ + if (tv_list_len(l) == 0) { + return 0; + } + + listitem_T *li = tv_list_find(l, (int)idx); + if (li == NULL) { + semsg(_(e_list_index_out_of_range_nr), idx); + return 0; + } + + varnumber_T n = 0; + + for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { + if (tv_equal(TV_LIST_ITEM_TV(li), needle, ic, false)) { + n++; + } + } + + return n; +} + +/// Count the number of times item "needle" occurs in Dict "d". +/// +/// @param ic ignore case +static varnumber_T count_dict(dict_T *d, typval_T *needle, bool ic) +{ + if (d == NULL) { + return 0; + } + + varnumber_T n = 0; + + TV_DICT_ITER(d, di, { + if (tv_equal(&di->di_tv, needle, ic, false)) { + n++; + } + }); + + return n; +} + /// "count()" function static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -895,74 +975,26 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ic = (int)tv_get_number_chk(&argvars[2], &error); } - if (argvars[0].v_type == VAR_STRING) { - const char *expr = tv_get_string_chk(&argvars[1]); - const char *p = argvars[0].vval.v_string; - - if (!error && expr != NULL && *expr != NUL && p != NULL) { - if (ic) { - const size_t len = strlen(expr); - - while (*p != NUL) { - if (mb_strnicmp(p, expr, len) == 0) { - n++; - p += len; - } else { - MB_PTR_ADV(p); - } - } - } else { - char *next; - while ((next = strstr(p, expr)) != NULL) { - n++; - p = next + strlen(expr); - } - } + if (!error && argvars[0].v_type == VAR_STRING) { + n = count_string(argvars[0].vval.v_string, tv_get_string_chk(&argvars[1]), ic); + } else if (!error && argvars[0].v_type == VAR_LIST) { + int64_t idx = 0; + if (argvars[2].v_type != VAR_UNKNOWN + && argvars[3].v_type != VAR_UNKNOWN) { + idx = (long)tv_get_number_chk(&argvars[3], &error); } - } else if (argvars[0].v_type == VAR_LIST) { - list_T *l = argvars[0].vval.v_list; - - if (l != NULL) { - listitem_T *li = tv_list_first(l); - if (argvars[2].v_type != VAR_UNKNOWN) { - if (argvars[3].v_type != VAR_UNKNOWN) { - int64_t idx = tv_get_number_chk(&argvars[3], &error); - if (!error) { - li = tv_list_find(l, (int)idx); - if (li == NULL) { - semsg(_(e_list_index_out_of_range_nr), idx); - } - } - } - if (error) { - li = NULL; - } - } - - for (; li != NULL; li = TV_LIST_ITEM_NEXT(l, li)) { - if (tv_equal(TV_LIST_ITEM_TV(li), &argvars[1], ic, false)) { - n++; - } - } + if (!error) { + n = count_list(argvars[0].vval.v_list, &argvars[1], idx, ic); } - } else if (argvars[0].v_type == VAR_DICT) { + } else if (!error && argvars[0].v_type == VAR_DICT) { dict_T *d = argvars[0].vval.v_dict; if (d != NULL) { - if (argvars[2].v_type != VAR_UNKNOWN) { - if (argvars[3].v_type != VAR_UNKNOWN) { - emsg(_(e_invarg)); - } - } - - int todo = error ? 0 : (int)d->dv_hashtab.ht_used; - for (hashitem_T *hi = d->dv_hashtab.ht_array; todo > 0; hi++) { - if (!HASHITEM_EMPTY(hi)) { - todo--; - if (tv_equal(&TV_DICT_HI2DI(hi)->di_tv, &argvars[1], ic, false)) { - n++; - } - } + if (argvars[2].v_type != VAR_UNKNOWN + && argvars[3].v_type != VAR_UNKNOWN) { + emsg(_(e_invarg)); + } else { + n = count_dict(argvars[0].vval.v_dict, &argvars[1], ic); } } } else { @@ -1875,104 +1907,124 @@ static void f_flattennew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) flatten_common(argvars, rettv, true); } -/// "extend()" or "extendnew()" function. "is_new" is true for extendnew(). -static void extend(typval_T *argvars, typval_T *rettv, char *arg_errmsg, bool is_new) +/// extend() a List. Append List argvars[1] to List argvars[0] before index +/// argvars[3] and return the resulting list in "rettv". +/// +/// @param is_new true for extendnew() +static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new, typval_T *rettv) { - if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { - bool error = false; + bool error = false; - list_T *l1 = argvars[0].vval.v_list; - list_T *const l2 = argvars[1].vval.v_list; - if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { - if (is_new) { - l1 = tv_list_copy(NULL, l1, false, get_copyID()); - if (l1 == NULL) { - return; - } + list_T *l1 = argvars[0].vval.v_list; + list_T *const l2 = argvars[1].vval.v_list; + if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + l1 = tv_list_copy(NULL, l1, false, get_copyID()); + if (l1 == NULL) { + return; } + } - listitem_T *item; - if (argvars[2].v_type != VAR_UNKNOWN) { - long before = (long)tv_get_number_chk(&argvars[2], &error); - if (error) { - return; // Type error; errmsg already given. - } - - if (before == tv_list_len(l1)) { - item = NULL; - } else { - item = tv_list_find(l1, (int)before); - if (item == NULL) { - semsg(_(e_list_index_out_of_range_nr), (int64_t)before); - return; - } - } - } else { - item = NULL; + listitem_T *item; + if (argvars[2].v_type != VAR_UNKNOWN) { + long before = (long)tv_get_number_chk(&argvars[2], &error); + if (error) { + return; // Type error; errmsg already given. } - tv_list_extend(l1, l2, item); - if (is_new) { - *rettv = (typval_T){ - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval.v_list = l1, - }; + if (before == tv_list_len(l1)) { + item = NULL; } else { - tv_copy(&argvars[0], rettv); + item = tv_list_find(l1, (int)before); + if (item == NULL) { + semsg(_(e_list_index_out_of_range_nr), (int64_t)before); + return; + } } + } else { + item = NULL; } - } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { - dict_T *d1 = argvars[0].vval.v_dict; - dict_T *const d2 = argvars[1].vval.v_dict; - if (d1 == NULL) { - const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); - (void)locked; - assert(locked == true); - } else if (d2 == NULL) { - // Do nothing + tv_list_extend(l1, l2, item); + + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval.v_list = l1, + }; + } else { tv_copy(&argvars[0], rettv); - } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { - if (is_new) { - d1 = tv_dict_copy(NULL, d1, false, get_copyID()); - if (d1 == NULL) { - return; - } + } + } +} + +/// extend() a Dict. Append Dict argvars[1] to Dict argvars[0] and return the +/// resulting Dict in "rettv". +/// +/// @param is_new true for extendnew() +static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new, typval_T *rettv) +{ + dict_T *d1 = argvars[0].vval.v_dict; + dict_T *const d2 = argvars[1].vval.v_dict; + if (d1 == NULL) { + const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + (void)locked; + assert(locked == true); + } else if (d2 == NULL) { + // Do nothing + tv_copy(&argvars[0], rettv); + } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + if (is_new) { + d1 = tv_dict_copy(NULL, d1, false, get_copyID()); + if (d1 == NULL) { + return; } + } - const char *action = "force"; - // Check the third argument. - if (argvars[2].v_type != VAR_UNKNOWN) { - const char *const av[] = { "keep", "force", "error" }; + const char *action = "force"; + // Check the third argument. + if (argvars[2].v_type != VAR_UNKNOWN) { + const char *const av[] = { "keep", "force", "error" }; - action = tv_get_string_chk(&argvars[2]); - if (action == NULL) { - return; // Type error; error message already given. - } - size_t i; - for (i = 0; i < ARRAY_SIZE(av); i++) { - if (strcmp(action, av[i]) == 0) { - break; - } - } - if (i == 3) { - semsg(_(e_invarg2), action); - return; + action = tv_get_string_chk(&argvars[2]); + if (action == NULL) { + return; // Type error; error message already given. + } + size_t i; + for (i = 0; i < ARRAY_SIZE(av); i++) { + if (strcmp(action, av[i]) == 0) { + break; } } + if (i == 3) { + semsg(_(e_invarg2), action); + return; + } + } - tv_dict_extend(d1, d2, action); + tv_dict_extend(d1, d2, action); - if (is_new) { - *rettv = (typval_T){ - .v_type = VAR_DICT, - .v_lock = VAR_UNLOCKED, - .vval.v_dict = d1, - }; - } else { - tv_copy(&argvars[0], rettv); - } + if (is_new) { + *rettv = (typval_T){ + .v_type = VAR_DICT, + .v_lock = VAR_UNLOCKED, + .vval.v_dict = d1, + }; + } else { + tv_copy(&argvars[0], rettv); } + } +} + +/// "extend()" or "extendnew()" function. +/// +/// @param is_new true for extendnew() +static void extend(typval_T *argvars, typval_T *rettv, char *arg_errmsg, bool is_new) +{ + if (argvars[0].v_type == VAR_LIST && argvars[1].v_type == VAR_LIST) { + extend_list(argvars, arg_errmsg, is_new, rettv); + } else if (argvars[0].v_type == VAR_DICT && argvars[1].v_type == VAR_DICT) { + extend_dict(argvars, arg_errmsg, is_new, rettv); } else { semsg(_(e_listdictarg), is_new ? "extendnew()" : "extend()"); } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5b977e93c9..5f7bd98298 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -36,6 +36,19 @@ #include "nvim/types.h" #include "nvim/vim.h" +/// struct storing information about current sort +typedef struct { + int item_compare_ic; + bool item_compare_lc; + bool item_compare_numeric; + bool item_compare_numbers; + bool item_compare_float; + const char *item_compare_func; + partial_T *item_compare_partial; + dict_T *item_compare_selfdict; + bool item_compare_func_err; +} sortinfo_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/typval.c.generated.h" #endif @@ -1065,18 +1078,6 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } } -/// struct storing information about current sort -typedef struct { - int item_compare_ic; - bool item_compare_lc; - bool item_compare_numeric; - bool item_compare_numbers; - bool item_compare_float; - const char *item_compare_func; - partial_T *item_compare_partial; - dict_T *item_compare_selfdict; - bool item_compare_func_err; -} sortinfo_T; static sortinfo_T *sortinfo = NULL; #define ITEM_COMPARE_FAIL 999 @@ -1252,148 +1253,188 @@ static int item_compare2_not_keeping_zero(const void *s1, const void *s2) return item_compare2(s1, s2, false); } -/// "sort({list})" function -static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) +/// sort() List "l" +static void do_sort(list_T *l, sortinfo_T *info) { - ListSortItem *ptrs; - long len; - int i; + const int len = tv_list_len(l); - // Pointer to current info struct used in compare function. Save and restore - // the current one for nested calls. - sortinfo_T info; - sortinfo_T *old_sortinfo = sortinfo; - sortinfo = &info; + // Make an array with each entry pointing to an item in the List. + ListSortItem *ptrs = xmalloc((size_t)((unsigned)len * sizeof(ListSortItem))); - const char *const arg_errmsg = (sort - ? N_("sort() argument") - : N_("uniq() argument")); + // f_sort(): ptrs will be the list to sort + int i = 0; + TV_LIST_ITER(l, li, { + ptrs[i].item = li; + ptrs[i].idx = i; + i++; + }); - if (argvars[0].v_type != VAR_LIST) { - semsg(_(e_listarg), sort ? "sort()" : "uniq()"); - } else { - list_T *const l = argvars[0].vval.v_list; - if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { - goto theend; - } - tv_list_set_ret(rettv, l); + info->item_compare_func_err = false; + ListSorter item_compare_func = ((info->item_compare_func == NULL + && info->item_compare_partial == NULL) + ? item_compare_not_keeping_zero + : item_compare2_not_keeping_zero); - len = tv_list_len(l); - if (len <= 1) { - goto theend; // short list sorts pretty quickly + // Sort the array with item pointers. + qsort(ptrs, (size_t)len, sizeof(ListSortItem), item_compare_func); + if (!info->item_compare_func_err) { + // Clear the list and append the items in the sorted order. + l->lv_first = NULL; + l->lv_last = NULL; + l->lv_idx_item = NULL; + l->lv_len = 0; + for (i = 0; i < len; i++) { + tv_list_append(l, ptrs[i].item); } + } + if (info->item_compare_func_err) { + emsg(_("E702: Sort compare function failed")); + } - info.item_compare_ic = false; - info.item_compare_lc = false; - info.item_compare_numeric = false; - info.item_compare_numbers = false; - info.item_compare_float = false; - info.item_compare_func = NULL; - info.item_compare_partial = NULL; - info.item_compare_selfdict = NULL; - - if (argvars[1].v_type != VAR_UNKNOWN) { - // optional second argument: {func} - if (argvars[1].v_type == VAR_FUNC) { - info.item_compare_func = argvars[1].vval.v_string; - } else if (argvars[1].v_type == VAR_PARTIAL) { - info.item_compare_partial = argvars[1].vval.v_partial; - } else { - bool error = false; + xfree(ptrs); +} - i = (int)tv_get_number_chk(&argvars[1], &error); - if (error) { - goto theend; // type error; errmsg already given - } - if (i == 1) { - info.item_compare_ic = true; - } else if (argvars[1].v_type != VAR_NUMBER) { - info.item_compare_func = tv_get_string(&argvars[1]); - } else if (i != 0) { - emsg(_(e_invarg)); - goto theend; - } - if (info.item_compare_func != NULL) { - if (*info.item_compare_func == NUL) { - // empty string means default sort - info.item_compare_func = NULL; - } else if (strcmp(info.item_compare_func, "n") == 0) { - info.item_compare_func = NULL; - info.item_compare_numeric = true; - } else if (strcmp(info.item_compare_func, "N") == 0) { - info.item_compare_func = NULL; - info.item_compare_numbers = true; - } else if (strcmp(info.item_compare_func, "f") == 0) { - info.item_compare_func = NULL; - info.item_compare_float = true; - } else if (strcmp(info.item_compare_func, "i") == 0) { - info.item_compare_func = NULL; - info.item_compare_ic = true; - } else if (strcmp(info.item_compare_func, "l") == 0) { - info.item_compare_func = NULL; - info.item_compare_lc = true; - } - } - } +/// uniq() List "l" +static void do_uniq(list_T *l, sortinfo_T *info) +{ + const int len = tv_list_len(l); - if (argvars[2].v_type != VAR_UNKNOWN) { - // optional third argument: {dict} - if (tv_check_for_dict_arg(argvars, 2) == FAIL) { - goto theend; - } - info.item_compare_selfdict = argvars[2].vval.v_dict; - } - } + // Make an array with each entry pointing to an item in the List. + ListSortItem *ptrs = xmalloc((size_t)((unsigned)len * sizeof(ListSortItem))); - // Make an array with each entry pointing to an item in the List. - ptrs = xmalloc((size_t)((unsigned)len * sizeof(ListSortItem))); - - if (sort) { - info.item_compare_func_err = false; - tv_list_item_sort(l, ptrs, - ((info.item_compare_func == NULL - && info.item_compare_partial == NULL) - ? item_compare_not_keeping_zero - : item_compare2_not_keeping_zero), - &info.item_compare_func_err); - if (info.item_compare_func_err) { - emsg(_("E702: Sort compare function failed")); - } + // f_uniq(): ptrs will be a stack of items to remove. + + info->item_compare_func_err = false; + ListSorter item_compare_func = ((info->item_compare_func == NULL + && info->item_compare_partial == NULL) + ? item_compare_keeping_zero + : item_compare2_keeping_zero); + + for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l)); li != NULL;) { + listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); + if (item_compare_func(&prev_li, &li) == 0) { + li = tv_list_item_remove(l, li); } else { - ListSorter item_compare_func_ptr; + li = TV_LIST_ITEM_NEXT(l, li); + } + if (info->item_compare_func_err) { + emsg(_("E882: Uniq compare function failed")); + break; + } + } - // f_uniq(): ptrs will be a stack of items to remove. - info.item_compare_func_err = false; - if (info.item_compare_func != NULL - || info.item_compare_partial != NULL) { - item_compare_func_ptr = item_compare2_keeping_zero; - } else { - item_compare_func_ptr = item_compare_keeping_zero; - } + xfree(ptrs); +} - for (listitem_T *li = TV_LIST_ITEM_NEXT(l, tv_list_first(l)) - ; li != NULL;) { - listitem_T *const prev_li = TV_LIST_ITEM_PREV(l, li); - if (item_compare_func_ptr(&prev_li, &li) == 0) { - li = tv_list_item_remove(l, li); - } else { - li = TV_LIST_ITEM_NEXT(l, li); - } - if (info.item_compare_func_err) { - emsg(_("E882: Uniq compare function failed")); - break; - } +/// Parse the optional arguments to sort() and uniq() and return the values in "info". +static int parse_sort_uniq_args(typval_T *argvars, sortinfo_T *info) +{ + info->item_compare_ic = false; + info->item_compare_lc = false; + info->item_compare_numeric = false; + info->item_compare_numbers = false; + info->item_compare_float = false; + info->item_compare_func = NULL; + info->item_compare_partial = NULL; + info->item_compare_selfdict = NULL; + + if (argvars[1].v_type == VAR_UNKNOWN) { + return OK; + } + + // optional second argument: {func} + if (argvars[1].v_type == VAR_FUNC) { + info->item_compare_func = argvars[1].vval.v_string; + } else if (argvars[1].v_type == VAR_PARTIAL) { + info->item_compare_partial = argvars[1].vval.v_partial; + } else { + bool error = false; + int nr = (int)tv_get_number_chk(&argvars[1], &error); + if (error) { + return FAIL; // type error; errmsg already given + } + if (nr == 1) { + info->item_compare_ic = true; + } else if (argvars[1].v_type != VAR_NUMBER) { + info->item_compare_func = tv_get_string(&argvars[1]); + } else if (nr != 0) { + emsg(_(e_invarg)); + return FAIL; + } + if (info->item_compare_func != NULL) { + if (*info->item_compare_func == NUL) { + // empty string means default sort + info->item_compare_func = NULL; + } else if (strcmp(info->item_compare_func, "n") == 0) { + info->item_compare_func = NULL; + info->item_compare_numeric = true; + } else if (strcmp(info->item_compare_func, "N") == 0) { + info->item_compare_func = NULL; + info->item_compare_numbers = true; + } else if (strcmp(info->item_compare_func, "f") == 0) { + info->item_compare_func = NULL; + info->item_compare_float = true; + } else if (strcmp(info->item_compare_func, "i") == 0) { + info->item_compare_func = NULL; + info->item_compare_ic = true; + } else if (strcmp(info->item_compare_func, "l") == 0) { + info->item_compare_func = NULL; + info->item_compare_lc = true; } } + } + + if (argvars[2].v_type != VAR_UNKNOWN) { + // optional third argument: {dict} + if (tv_check_for_dict_arg(argvars, 2) == FAIL) { + return FAIL; + } + info->item_compare_selfdict = argvars[2].vval.v_dict; + } - xfree(ptrs); + return OK; +} + +/// "sort()" or "uniq()" function +static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) +{ + if (argvars[0].v_type != VAR_LIST) { + semsg(_(e_listarg), sort ? "sort()" : "uniq()"); + return; + } + + // Pointer to current info struct used in compare function. Save and restore + // the current one for nested calls. + sortinfo_T info; + sortinfo_T *old_sortinfo = sortinfo; + sortinfo = &info; + + const char *const arg_errmsg = (sort ? N_("sort() argument") : N_("uniq() argument")); + list_T *const l = argvars[0].vval.v_list; + if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { + goto theend; + } + tv_list_set_ret(rettv, l); + + const int len = tv_list_len(l); + if (len <= 1) { + goto theend; // short list sorts pretty quickly + } + if (parse_sort_uniq_args(argvars, &info) == FAIL) { + goto theend; + } + + if (sort) { + do_sort(l, &info); + } else { + do_uniq(l, &info); } theend: sortinfo = old_sortinfo; } -/// "sort"({list})" function +/// "sort({list})" function void f_sort(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { do_sort_uniq(argvars, rettv, true); @@ -1469,46 +1510,6 @@ void tv_list_reverse(list_T *const l) l->lv_idx = l->lv_len - l->lv_idx - 1; } -// FIXME Add unit tests for tv_list_item_sort(). - -/// Sort list using libc qsort -/// -/// @param[in,out] l List to sort, will be sorted in-place. -/// @param ptrs Preallocated array of items to sort, must have at least -/// tv_list_len(l) entries. Should not be initialized. -/// @param[in] item_compare_func Function used to compare list items. -/// @param errp Location where information about whether error occurred is -/// saved by item_compare_func. If boolean there appears to be -/// true list will not be modified. Must be initialized to false -/// by the caller. -void tv_list_item_sort(list_T *const l, ListSortItem *const ptrs, - const ListSorter item_compare_func, const bool *errp) - FUNC_ATTR_NONNULL_ARG(3, 4) -{ - const int len = tv_list_len(l); - if (len <= 1) { - return; - } - int i = 0; - TV_LIST_ITER(l, li, { - ptrs[i].item = li; - ptrs[i].idx = i; - i++; - }); - // Sort the array with item pointers. - qsort(ptrs, (size_t)len, sizeof(ListSortItem), item_compare_func); - if (!(*errp)) { - // Clear the list and append the items in the sorted order. - l->lv_first = NULL; - l->lv_last = NULL; - l->lv_idx_item = NULL; - l->lv_len = 0; - for (i = 0; i < len; i++) { - tv_list_append(l, ptrs[i].item); - } - } -} - //{{{2 Indexing/searching /// Locate item with a given index in a list and return it -- cgit From ffb87f4dd992ff23ff66f888dbe1bcc54bd0b012 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 18 Aug 2023 05:07:48 +0800 Subject: vim-patch:9.0.1722: wrong error messages when passing wrong types to count() Problem: wrong error messages when passing wrong types to count() Solution: fix it This fixes two problems: 1. When passing wrong type to {ic} argument of count(), two error messages are given, the second of which is misleading. 2. When passing wrong type to {comp} argument of count(), the error message doesn't mention that {comp} may be a String. closes: vim/vim#12825 https://github.com/vim/vim/commit/4f389e7c0fe7dfeccfa512a72fa36f9028d57159 --- src/nvim/eval/funcs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b0e0fffe5c..a9f87b5008 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -147,6 +147,8 @@ PRAGMA_DIAG_POP static const char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static const char *e_invalwindow = N_("E957: Invalid window number"); +static const char e_argument_of_str_must_be_list_string_or_dictionary[] + = N_("E706: Argument of %s must be a List, String or Dictionary"); static const char e_invalid_submatch_number_nr[] = N_("E935: Invalid submatch number: %d"); static const char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); @@ -997,8 +999,8 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) n = count_dict(argvars[0].vval.v_dict, &argvars[1], ic); } } - } else { - semsg(_(e_listdictarg), "count()"); + } else if (!error) { + semsg(_(e_argument_of_str_must_be_list_string_or_dictionary), "count()"); } rettv->vval.v_number = n; } -- cgit From bb29ef40084e1cea1f35cbbcbac794f41f46d5f8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 18 Aug 2023 05:09:24 +0800 Subject: vim-patch:9.0.1723: Fix regression in {func} argument of reduce() Problem: Fix regression in {func} argument of reduce() Solution: pass function name as string again Before patch 9.0.0548, passing a string as {func} argument of reduce() is treated as a function name, but after patch 9.0.0548 it is treated as an expression instead, which is useless as reduce() doesn't set any v: variables. This PR restores the behavior of {func} before that patch. Also correct an emsg() call, as e_string_list_or_blob_required doesn't contain format specifiers. closes: vim/vim#12824 https://github.com/vim/vim/commit/ad0c442f1fcc6fe9c433777ee3e5b9e6addc6d69 --- src/nvim/eval/funcs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index a9f87b5008..e8224671dc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2953,7 +2953,7 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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 + eval_expr_typval(&expr, false, &argv, 0, &exprval) != OK || tv_get_number_chk(&exprval, &error) || called_emsg > called_emsg_before || error || got_int); @@ -3515,7 +3515,7 @@ static varnumber_T indexof_eval_expr(typval_T *expr) typval_T newtv; newtv.v_type = VAR_UNKNOWN; - if (eval_expr_typval(expr, argv, 2, &newtv) == FAIL) { + if (eval_expr_typval(expr, false, argv, 2, &newtv) == FAIL) { return false; } @@ -5537,7 +5537,7 @@ static varnumber_T readdir_checkitem(void *context, const char *name) argv[0].vval.v_string = (char *)name; typval_T rettv; - if (eval_expr_typval(expr, argv, 1, &rettv) == FAIL) { + if (eval_expr_typval(expr, false, argv, 1, &rettv) == FAIL) { goto theend; } @@ -6259,7 +6259,7 @@ static void reduce_list(typval_T *argvars, typval_T *expr, typval_T *rettv) argv[1] = *TV_LIST_ITEM_TV(li); rettv->v_type = VAR_UNKNOWN; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); tv_clear(&argv[0]); if (r == FAIL || called_emsg != called_emsg_start) { @@ -6306,7 +6306,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) .vval.v_string = xstrnsave(p, (size_t)len), }; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); tv_clear(&argv[0]); tv_clear(&argv[1]); @@ -6354,7 +6354,7 @@ static void reduce_blob(typval_T *argvars, typval_T *expr, typval_T *rettv) .vval.v_number = tv_blob_get(b, i), }; - const int r = eval_expr_typval(expr, argv, 2, rettv); + const int r = eval_expr_typval(expr, true, argv, 2, rettv); if (r == FAIL || called_emsg != called_emsg_start) { return; -- cgit From f8afa8023ee032dfb2aa9a6489f51484fb276732 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 18 Aug 2023 08:42:45 +0800 Subject: vim-patch:9.0.1728: missing winid argument for virtcol() (#24770) Problem: missing winid argument for virtcol() Solution: Add a {winid} argument to virtcol() Other functions col(), charcol() and virtcol2col() support a {winid} argument, so it makes sense for virtcol() to also support than. Also add test for virtcol2col() with 'showbreak' and {winid}. closes: vim/vim#12633 https://github.com/vim/vim/commit/825cf813fa0fddf085fcbd3194781e875320ff63 --- src/nvim/eval/funcs.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e8224671dc..9926530d58 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8748,13 +8748,31 @@ static void f_type(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = n; } -/// "virtcol(string, bool)" function +/// "virtcol({expr}, [, {list} [, {winid}]])" function static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { colnr_T vcol_start = 0; colnr_T vcol_end = 0; - int fnum = curbuf->b_fnum; + switchwin_T switchwin; + bool winchanged = false; + + if (argvars[1].v_type != VAR_UNKNOWN && argvars[2].v_type != VAR_UNKNOWN) { + // use the window specified in the third argument + tabpage_T *tp; + win_T *wp = win_id2wp_tp((int)tv_get_number(&argvars[2]), &tp); + if (wp == NULL || tp == NULL) { + goto theend; + } + if (switch_win_noblock(&switchwin, wp, tp, true) != OK) { + goto theend; + } + + check_cursor(); + winchanged = true; + } + + int fnum = curbuf->b_fnum; pos_T *fp = var2fpos(&argvars[0], false, &fnum, false); if (fp != NULL && fp->lnum <= curbuf->b_ml.ml_line_count && fnum == curbuf->b_fnum) { @@ -8772,6 +8790,7 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) vcol_end++; } +theend: if (argvars[1].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[1])) { tv_list_alloc_ret(rettv, 2); tv_list_append_number(rettv->vval.v_list, vcol_start); @@ -8779,6 +8798,10 @@ static void f_virtcol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else { rettv->vval.v_number = vcol_end; } + + if (winchanged) { + restore_win_noblock(&switchwin, true); + } } /// "visualmode()" function -- cgit From 4c7df98e4eeed20f8a9c461729935b79743d7752 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 19 Aug 2023 17:44:19 +0800 Subject: vim-patch:9.0.1515: reverse() does not work for a String Problem: reverse() does not work for a String. Solution: Implement reverse() for a String. (Yegappan Lakshmanan, closes vim/vim#12179) https://github.com/vim/vim/commit/03ff1c2dde7f15eca5c9baa6dafbda9b49bedc3b vim-patch:9.0.1738: Duplicate code to reverse a string Problem: Duplicate code to reverse a string Solution: Move reverse_text() to strings.c and remove string_reverse(). closes: vim/vim#12847 https://github.com/vim/vim/commit/4dd266cb66d901cf5324f09405cfea3f004bd29f Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 9926530d58..b97e19131e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6209,6 +6209,13 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_blob_set(b, len - i - 1, tmp); } tv_blob_set_ret(rettv, b); + } else if (argvars[0].v_type == VAR_STRING) { + rettv->v_type = VAR_STRING; + if (argvars[0].vval.v_string != NULL) { + rettv->vval.v_string = reverse_text(argvars[0].vval.v_string); + } else { + rettv->vval.v_string = NULL; + } } else if (argvars[0].v_type != VAR_LIST) { semsg(_(e_listblobarg), "reverse()"); } else { -- cgit From fcd729f22c658826024467801ae4ba0a92a8fabc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 19 Aug 2023 17:57:09 +0800 Subject: vim-patch:9.0.1540: reverse() on string doesn't work in compiled function Problem: reverse() on string doesn't work in compiled function. Solution: Accept string in argument type check. (Yegappan Lakshmanan, closes vim/vim#12377) https://github.com/vim/vim/commit/f9dc278946d52235a0025fd347bd9ff571258470 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 8 +++++--- src/nvim/eval/typval.c | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b97e19131e..250b5c5556 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6199,6 +6199,10 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "reverse({list})" function static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + if (tv_check_for_string_or_list_or_blob_arg(argvars, 0) == FAIL) { + return; + } + if (argvars[0].v_type == VAR_BLOB) { blob_T *const b = argvars[0].vval.v_blob; const int len = tv_blob_len(b); @@ -6216,9 +6220,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } else { rettv->vval.v_string = NULL; } - } else if (argvars[0].v_type != VAR_LIST) { - semsg(_(e_listblobarg), "reverse()"); - } else { + } else if (argvars[0].v_type == VAR_LIST) { list_T *const l = argvars[0].vval.v_list; if (!value_check_lock(tv_list_locked(l), N_("reverse() argument"), TV_TRANSLATE)) { diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5f7bd98298..ba2c23ffe8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -81,6 +81,8 @@ static const char e_blob_required_for_argument_nr[] = N_("E1238: Blob required for argument %d"); static const char e_invalid_value_for_blob_nr[] = N_("E1239: Invalid value for blob: %d"); +static const char e_string_list_or_blob_required_for_argument_nr[] + = N_("E1252: String, List or Blob required for argument %d"); static const char e_string_or_function_required_for_argument_nr[] = N_("E1256: String or function required for argument %d"); static const char e_non_null_dict_required_for_argument_nr[] @@ -4350,7 +4352,20 @@ int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx) return OK; } -/// Check for an optional string or list argument at 'idx' +/// Give an error and return FAIL unless "args[idx]" is a string, a list or a blob. +int tv_check_for_string_or_list_or_blob_arg(const typval_T *const args, const int idx) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE +{ + if (args[idx].v_type != VAR_STRING + && args[idx].v_type != VAR_LIST + && args[idx].v_type != VAR_BLOB) { + semsg(_(e_string_list_or_blob_required_for_argument_nr), idx + 1); + return FAIL; + } + return OK; +} + +/// Check for an optional string or list argument at "idx" int tv_check_for_opt_string_or_list_arg(const typval_T *const args, const int idx) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { -- cgit From 64ccfdaafef56b451e3a5eed94367fad93978ec8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Aug 2023 11:22:25 +0800 Subject: vim-patch:8.1.2047: cannot check the current state Problem: Cannot check the current state. Solution: Add the state() function. https://github.com/vim/vim/commit/0e57dd859ecb1e8a3b91509d2f4343e839340eb8 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 250b5c5556..c47fd4cfcb 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4925,6 +4925,47 @@ static void f_mode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->v_type = VAR_STRING; } +static void may_add_state_char(garray_T *gap, const char *include, uint8_t c) +{ + if (include == NULL || vim_strchr(include, c) != NULL) { + ga_append(gap, c); + } +} + +/// "state()" function +static void f_state(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + garray_T ga; + ga_init(&ga, 1, 20); + const char *include = NULL; + + if (argvars[0].v_type != VAR_UNKNOWN) { + include = tv_get_string(&argvars[0]); + } + + if (!(stuff_empty() && typebuf.tb_len == 0 && !using_script())) { + may_add_state_char(&ga, include, 'm'); + } + if (op_pending()) { + may_add_state_char(&ga, include, 'o'); + } + if (autocmd_busy) { + may_add_state_char(&ga, include, 'x'); + } + if (!ctrl_x_mode_none()) { + may_add_state_char(&ga, include, 'a'); + } + for (int i = 0; i < get_callback_depth() && i < 3; i++) { + may_add_state_char(&ga, include, 'c'); + } + if (msg_scrolled > 0) { + may_add_state_char(&ga, include, 's'); + } + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = ga.ga_data; +} + /// "msgpackdump()" function static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) FUNC_ATTR_NONNULL_ALL -- cgit From 7ce2acd59be89e5e6d2ac778ad074a9ae42951cd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Aug 2023 12:16:33 +0800 Subject: vim-patch:8.1.2053: SafeStateAgain not triggered if callback uses feedkeys() Problem: SafeStateAgain not triggered if callback uses feedkeys(). Solution: Check for safe state in the input loop. Make log messages easier to find. Add 'S' flag to state(). https://github.com/vim/vim/commit/d103ee78432f9036d243b18dd5aac1263d3b7dc9 Include misc1.c change from patch 8.1.2062. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c47fd4cfcb..8c07623369 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4955,6 +4955,9 @@ static void f_state(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!ctrl_x_mode_none()) { may_add_state_char(&ga, include, 'a'); } + if (!get_was_safe_state()) { + may_add_state_char(&ga, include, 'S'); + } for (int i = 0; i < get_callback_depth() && i < 3; i++) { may_add_state_char(&ga, include, 'c'); } -- cgit From 6bf5b2428b146330688922d66438357c0568725d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Aug 2023 12:26:02 +0800 Subject: vim-patch:8.1.2066: no tests for state() Problem: No tests for state(). Solution: Add tests. Clean up some feature checks. Make "a" flag work. https://github.com/vim/vim/commit/c2585490321854ca3df115efcf0b40986901d96c Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8c07623369..3c232a7163 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4952,7 +4952,7 @@ static void f_state(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (autocmd_busy) { may_add_state_char(&ga, include, 'x'); } - if (!ctrl_x_mode_none()) { + if (ins_compl_active()) { may_add_state_char(&ga, include, 'a'); } if (!get_was_safe_state()) { -- cgit From cc35352f65f823259675f84a915ee03d2423913e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 21 Aug 2023 15:23:32 +0800 Subject: vim-patch:8.1.2062: the mouse code is spread out (#24817) Problem: The mouse code is spread out. Solution: Move all the mouse code to mouse.c. (Yegappan Lakshmanan, closes vim/vim#4959) https://github.com/vim/vim/commit/b20b9e14ddd8db111e886ad0494e15b955159426 Also move getmousepos() there. N/A patches for version.c: vim-patch:8.1.2070: mouse code is spread out Problem: Mouse code is spread out. Solution: Move mouse terminal code parsing to mouse.c. (Yegappan Lakshmanan, closes vim/vim#4966) https://github.com/vim/vim/commit/b8ff5c271ee5dcef6f63436b77e228e062ff9a0e Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 41 ----------------------------------------- 1 file changed, 41 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 3c232a7163..755df761e7 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2750,47 +2750,6 @@ static void f_getmarklist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) get_buf_local_marks(buf, rettv->vval.v_list); } -/// "getmousepos()" function -static void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int row = mouse_row; - int col = mouse_col; - int grid = mouse_grid; - varnumber_T winid = 0; - varnumber_T winrow = 0; - varnumber_T wincol = 0; - linenr_T lnum = 0; - varnumber_T column = 0; - - tv_dict_alloc_ret(rettv); - dict_T *d = rettv->vval.v_dict; - - tv_dict_add_nr(d, S_LEN("screenrow"), (varnumber_T)mouse_row + 1); - tv_dict_add_nr(d, S_LEN("screencol"), (varnumber_T)mouse_col + 1); - - win_T *wp = mouse_find_win(&grid, &row, &col); - if (wp != NULL) { - 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_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) { - (void)mouse_comp_pos(wp, &row, &col, &lnum); - col = vcol2col(wp, lnum, col); - column = col + 1; - } - } - } - 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)lnum); - tv_dict_add_nr(d, S_LEN("column"), column); -} - /// "getpid()" function static void f_getpid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From 0fd8eb8aae101815c699048a4dbc6ac7c5e35a9d Mon Sep 17 00:00:00 2001 From: Gregory Anders <8965202+gpanders@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:55:51 -0500 Subject: fix(terminal): set $COLORTERM unconditionally in :terminal (#24763) $COLORTERM is set in the terminal emulator based on the value of 'termguicolors' ("truecolor" if &tgc is set, 256 otherwise), but ONLY if $COLORTERM is also set in the parent terminal emulator. This is an unnecessary restriction that can cause issues in some cases. For instance, $COLORTERM is stripped by default by OpenSSH, so is not present in an SSH session. The terminal emulator still supports 24 bit color, so the lack of $COLORTERM is not a reliable indicator. When an application runs in Nvim's :terminal it thus has no way to know whether or not true color is supported. Instead, setting it unconditionally based on 'termguicolors' uses the user's own preferences to infer if 24-bit color is supported, rather than depending on the (unreliable) presence of $COLORTERM. If 'termguicolors' is set in a terminal that does not support true color then the colors in Nvim will already look bad. Enabling them for applications in the terminal emulator will not make it any worse. If 'termguicolors' is not set then the value of $COLORTERM from the parent terminal (if any) is forwarded to Nvim's :terminal. Fixes: https://github.com/neovim/neovim/issues/24717 --- src/nvim/eval/funcs.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 755df761e7..cf8525e66a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3943,12 +3943,13 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en } } #ifndef MSWIN - // Set COLORTERM to "truecolor" if termguicolors is set and 256 - // otherwise, but only if it was set in the parent terminal at all - dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM")); - if (dv) { - tv_dict_item_remove(env, dv); - tv_dict_add_str(env, S_LEN("COLORTERM"), p_tgc ? "truecolor" : "256"); + // Set COLORTERM to "truecolor" if termguicolors is set + if (p_tgc) { + dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM")); + if (dv) { + tv_dict_item_remove(env, dv); + } + tv_dict_add_str(env, S_LEN("COLORTERM"), "truecolor"); } #endif } -- cgit From 09910d5b35f2432a22374e59560a1bbd08907d57 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 22 Aug 2023 18:21:15 +0800 Subject: vim-patch:9.0.0837: append() reports failure when not appending anything Problem: append() reports failure when not appending anything. Solution: Only report failure when appending something. (closes vim/vim#11498) https://github.com/vim/vim/commit/cd9c8d400c1eb9cbb4ff6a33be02f91a30ab13b2 Co-authored-by: Bram Moolenaar --- src/nvim/eval/buffer.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 0fe3f5444c..256adfd44f 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -160,10 +160,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ if (lines->v_type == VAR_LIST) { l = lines->vval.v_list; if (l == NULL || tv_list_len(l) == 0) { - // set proper return code - if (lnum > curbuf->b_ml.ml_line_count) { - rettv->vval.v_number = 1; // FAIL - } + // not appending anything always succeeds goto cleanup; } li = tv_list_first(l); -- cgit From cefd774fac76b91f5368833555818c80c992c3b1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 24 Aug 2023 15:14:23 +0200 Subject: refactor(memline): distinguish mutating uses of ml_get_buf() ml_get_buf() takes a third parameters to indicate whether the caller wants to mutate the memline data in place. However the vast majority of the call sites is using this function just to specify a buffer but without any mutation. This makes it harder to grep for the places which actually perform mutation. Solution: Remove the bool param from ml_get_buf(). it now works like ml_get() except for a non-current buffer. Add a new ml_get_buf_mut() function for the mutating use-case, which can be grepped along with the other ml_replace() etc functions which can modify the memline. --- src/nvim/eval/buffer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 256adfd44f..4dbfcd2938 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -604,12 +604,12 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli } tv_list_alloc_ret(rettv, end - start + 1); while (start <= end) { - tv_list_append_string(rettv->vval.v_list, ml_get_buf(buf, start++, false), -1); + tv_list_append_string(rettv->vval.v_list, ml_get_buf(buf, start++), -1); } } else { rettv->v_type = VAR_STRING; rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count) - ? xstrdup(ml_get_buf(buf, start, false)) : NULL); + ? xstrdup(ml_get_buf(buf, start)) : NULL); } } -- cgit From 008154954791001efcc46c28146e21403f3a698b Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 21 Aug 2023 14:52:17 +0200 Subject: refactor(change): do API changes to buffer without curbuf switch Most of the messy things when changing a non-current buffer is not about the buffer, it is about windows. In particular, it is about `curwin`. When editing a non-current buffer which is displayed in some other window in the current tabpage, one such window will be "borrowed" as the curwin. But this means if two or more non-current windows displayed the buffers, one of them will be treated differenty. this is not desirable. In particular, with nvim_buf_set_text, cursor _column_ position was only corrected for one single window. Two new tests are added: the test with just one non-current window passes, but the one with two didn't. Two corresponding such tests were also added for nvim_buf_set_lines. This already worked correctly on master, but make sure this is well-tested for future refactors. Also, nvim_create_buf no longer invokes autocmds just because you happened to use `scratch=true`. No option value was changed, therefore OptionSet must not be fired. --- src/nvim/eval/buffer.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 4dbfcd2938..b480d25367 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -301,7 +301,8 @@ void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) buf_T *buf = get_buf_arg(&argvars[0]); if (buf != NULL) { - buffer_ensure_loaded(buf); + swap_exists_action = SEA_NONE; + buf_ensure_loaded(buf); } } -- cgit From 01fe6b9e6a84338d4752c93a286262d79120f163 Mon Sep 17 00:00:00 2001 From: Alisue Date: Sun, 6 Aug 2023 23:19:29 +0900 Subject: feat(msgpack_rpc): support out-of-order responses on `msgpack-rpc` Added to support MessagePack-RPC fully compliant clients that do not return responses in request order. Although it is currently not an efficient implementation for full compliance and full compliance cannot be guaranteed, the addition of the new client type `msgpack-rpc` creates a situation where "if the client type is `msgpack-rpc`, then backward compatibility is ignored and full compliance with MessagePack- RPC compliance is justified even if backward compatibility is ignored if the client type is `msgpack-rpc`. --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index cf8525e66a..1ed0994222 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6730,7 +6730,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *name = NULL; Channel *chan = find_channel(chan_id); if (chan) { - name = rpc_client_name(chan); + name = get_client_info(chan, "name"); } msg_ext_set_kind("rpc_error"); if (name) { -- cgit From a1bec02c1e105eb9f49d577e04bdbeadd5a05e38 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sun, 13 Aug 2023 10:29:43 +0100 Subject: fix: use snprintf instead of sprintf Clang 14 now reports sprintf as deprecated. --- src/nvim/eval/userfunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a52b8d3f18..a5d7ed2758 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2702,7 +2702,7 @@ void ex_function(exarg_T *eap) // Give the function a sequential number. Can only be used with a // Funcref! xfree(name); - sprintf(numbuf, "%d", ++func_nr); // NOLINT(runtime/printf) + snprintf(numbuf, sizeof(numbuf), "%d", ++func_nr); name = xstrdup(numbuf); } -- cgit From a6e74c1f0a2bbf03f5b99c167b549018f4c8fb0d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 14 Sep 2023 06:05:27 +0200 Subject: docs: fix typos and other small fixes (#25005) Co-authored-by: nuid64 Co-authored-by: Mike Smith <10135646+mikesmithgh@users.noreply.github.com> Co-authored-by: XTY Co-authored-by: Empa Co-authored-by: kyu08 <49891479+kyu08@users.noreply.github.com> --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/vars.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1ed0994222..93075cf0e2 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6329,7 +6329,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) } } -/// Implementaion of reduce() for Blob "argvars[0]" using the function "expr" +/// Implementation of reduce() for Blob "argvars[0]" using the function "expr" /// starting with the optional initial value "argvars[2]" and return the result /// in "rettv". static void reduce_blob(typval_T *argvars, typval_T *expr, typval_T *rettv) diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9b6427fef7..e5b1b88eef 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1810,7 +1810,7 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off) /// @param[in] tv typval to convert. /// @param[in] option Option name. /// @param[in] flags Option flags. -/// @param[out] error Whether an error occured. +/// @param[out] error Whether an error occurred. /// /// @return Typval converted to OptVal. Must be freed by caller. /// Returns NIL_OPTVAL for invalid option name. -- cgit From 4d3a38ac074fff7e2a4bede4cee7699bdd55ffdc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 24 Sep 2023 10:57:09 +0800 Subject: fix(api, lua): handle setting v: variables properly (#25325) --- src/nvim/eval/vars.c | 145 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 88 insertions(+), 57 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index e5b1b88eef..5d1da956ee 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -52,8 +52,8 @@ static const char *e_letunexp = N_("E18: Unexpected characters in :let"); static const char *e_lock_unlock = N_("E940: Cannot lock or unlock variable %s"); -static const char e_setting_str_to_value_with_wrong_type[] - = N_("E963: Setting %s to value with wrong type"); +static const char e_setting_v_str_to_value_with_wrong_type[] + = N_("E963: Setting v:%s to value with wrong type"); static const char e_cannot_use_heredoc_here[] = N_("E991: Cannot use =<< here"); @@ -1389,6 +1389,62 @@ static void list_one_var_a(const char *prefix, const char *name, const ptrdiff_t } } +/// Additional handling for setting a v: variable. +/// +/// @return true if the variable should be set normally, +/// false if nothing else needs to be done. +bool before_set_vvar(const char *const varname, dictitem_T *const di, typval_T *const tv, + const bool copy, const bool watched, bool *const type_error) +{ + if (di->di_tv.v_type == VAR_STRING) { + typval_T oldtv = TV_INITIAL_VALUE; + if (watched) { + tv_copy(&di->di_tv, &oldtv); + } + XFREE_CLEAR(di->di_tv.vval.v_string); + if (copy || tv->v_type != VAR_STRING) { + const char *const val = tv_get_string(tv); + // Careful: when assigning to v:errmsg and tv_get_string() + // causes an error message the variable will already be set. + if (di->di_tv.vval.v_string == NULL) { + di->di_tv.vval.v_string = xstrdup(val); + } + } else { + // Take over the string to avoid an extra alloc/free. + di->di_tv.vval.v_string = tv->vval.v_string; + tv->vval.v_string = NULL; + } + // Notify watchers + if (watched) { + tv_dict_watcher_notify(&vimvardict, varname, &di->di_tv, &oldtv); + tv_clear(&oldtv); + } + return false; + } else if (di->di_tv.v_type == VAR_NUMBER) { + typval_T oldtv = TV_INITIAL_VALUE; + if (watched) { + tv_copy(&di->di_tv, &oldtv); + } + di->di_tv.vval.v_number = tv_get_number(tv); + if (strcmp(varname, "searchforward") == 0) { + set_search_direction(di->di_tv.vval.v_number ? '/' : '?'); + } else if (strcmp(varname, "hlsearch") == 0) { + no_hlsearch = !di->di_tv.vval.v_number; + redraw_all_later(UPD_SOME_VALID); + } + // Notify watchers + if (watched) { + tv_dict_watcher_notify(&vimvardict, varname, &di->di_tv, &oldtv); + tv_clear(&oldtv); + } + return false; + } else if (di->di_tv.v_type != tv->v_type) { + *type_error = true; + return false; + } + return true; +} + /// Set variable to the given value /// /// If the variable already exists, the value is updated. Otherwise the variable @@ -1418,31 +1474,29 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, const bool is_const) FUNC_ATTR_NONNULL_ALL { - dictitem_T *v; - hashtab_T *ht; - dict_T *dict; - const char *varname; - ht = find_var_ht_dict(name, name_len, &varname, &dict); + dict_T *dict; + hashtab_T *ht = find_var_ht_dict(name, name_len, &varname, &dict); const bool watched = tv_dict_is_watched(dict); if (ht == NULL || *varname == NUL) { semsg(_(e_illvar), name); return; } - v = find_var_in_ht(ht, 0, varname, name_len - (size_t)(varname - name), true); + const size_t varname_len = name_len - (size_t)(varname - name); + dictitem_T *di = find_var_in_ht(ht, 0, varname, varname_len, true); // Search in parent scope which is possible to reference from lambda - if (v == NULL) { - v = find_var_in_scoped_ht(name, name_len, true); + if (di == NULL) { + di = find_var_in_scoped_ht(name, name_len, true); } - if (tv_is_func(*tv) && var_wrong_func_name(name, v == NULL)) { + if (tv_is_func(*tv) && var_wrong_func_name(name, di == NULL)) { return; } typval_T oldtv = TV_INITIAL_VALUE; - if (v != NULL) { + if (di != NULL) { if (is_const) { emsg(_(e_cannot_mod)); return; @@ -1452,9 +1506,9 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // - Whether the variable is read-only // - Whether the variable value is locked // - Whether the variable is locked - if (var_check_ro(v->di_flags, name, name_len) - || value_check_lock(v->di_tv.v_lock, name, name_len) - || var_check_lock(v->di_flags, name, name_len)) { + if (var_check_ro(di->di_flags, name, name_len) + || value_check_lock(di->di_tv.v_lock, name, name_len) + || var_check_lock(di->di_flags, name, name_len)) { return; } @@ -1462,42 +1516,19 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // Handle setting internal v: variables separately where needed to // prevent changing the type. - if (is_vimvarht(ht)) { - if (v->di_tv.v_type == VAR_STRING) { - XFREE_CLEAR(v->di_tv.vval.v_string); - if (copy || tv->v_type != VAR_STRING) { - const char *const val = tv_get_string(tv); - - // Careful: when assigning to v:errmsg and tv_get_string() - // causes an error message the variable will already be set. - if (v->di_tv.vval.v_string == NULL) { - v->di_tv.vval.v_string = xstrdup(val); - } - } else { - // Take over the string to avoid an extra alloc/free. - v->di_tv.vval.v_string = tv->vval.v_string; - tv->vval.v_string = NULL; - } - return; - } else if (v->di_tv.v_type == VAR_NUMBER) { - v->di_tv.vval.v_number = tv_get_number(tv); - if (strcmp(varname, "searchforward") == 0) { - set_search_direction(v->di_tv.vval.v_number ? '/' : '?'); - } else if (strcmp(varname, "hlsearch") == 0) { - no_hlsearch = !v->di_tv.vval.v_number; - redraw_all_later(UPD_SOME_VALID); - } - return; - } else if (v->di_tv.v_type != tv->v_type) { - semsg(_(e_setting_str_to_value_with_wrong_type), name); - return; + bool type_error = false; + if (is_vimvarht(ht) + && !before_set_vvar(varname, di, tv, copy, watched, &type_error)) { + if (type_error) { + semsg(_(e_setting_v_str_to_value_with_wrong_type), varname); } + return; } if (watched) { - tv_copy(&v->di_tv, &oldtv); + tv_copy(&di->di_tv, &oldtv); } - tv_clear(&v->di_tv); + tv_clear(&di->di_tv); } else { // Add a new variable. // Can't add "v:" or "a:" variable. if (is_vimvarht(ht) || ht == get_funccal_args_ht()) { @@ -1513,28 +1544,28 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // Make sure dict is valid assert(dict != NULL); - v = xmalloc(offsetof(dictitem_T, di_key) + strlen(varname) + 1); - STRCPY(v->di_key, varname); - if (hash_add(ht, v->di_key) == FAIL) { - xfree(v); + di = xmalloc(offsetof(dictitem_T, di_key) + varname_len + 1); + memcpy(di->di_key, varname, varname_len + 1); + if (hash_add(ht, di->di_key) == FAIL) { + xfree(di); return; } - v->di_flags = DI_FLAGS_ALLOC; + di->di_flags = DI_FLAGS_ALLOC; if (is_const) { - v->di_flags |= DI_FLAGS_LOCK; + di->di_flags |= DI_FLAGS_LOCK; } } if (copy || tv->v_type == VAR_NUMBER || tv->v_type == VAR_FLOAT) { - tv_copy(tv, &v->di_tv); + tv_copy(tv, &di->di_tv); } else { - v->di_tv = *tv; - v->di_tv.v_lock = VAR_UNLOCKED; + di->di_tv = *tv; + di->di_tv.v_lock = VAR_UNLOCKED; tv_init(tv); } if (watched) { - tv_dict_watcher_notify(dict, v->di_key, &v->di_tv, &oldtv); + tv_dict_watcher_notify(dict, di->di_key, &di->di_tv, &oldtv); tv_clear(&oldtv); } @@ -1542,7 +1573,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, // Like :lockvar! name: lock the value and what it contains, but only // if the reference count is up to one. That locks only literal // values. - tv_item_lock(&v->di_tv, DICT_MAXNEST, true, true); + tv_item_lock(&di->di_tv, DICT_MAXNEST, true, true); } } -- cgit From f91cd31d7d9d70006e0000592637d5d997eab52c Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 27 Sep 2023 21:46:39 +0200 Subject: refactor(messages): fold msg_outtrans_attr into msg_outtrans problem: there are too many different functions in message.c solution: fold some of the functions into themselves --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 5d1da956ee..60cf0f8054 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1378,7 +1378,7 @@ static void list_one_var_a(const char *prefix, const char *name, const ptrdiff_t msg_putchar(' '); } - msg_outtrans(string); + msg_outtrans(string, 0); if (type == VAR_FUNC || type == VAR_PARTIAL) { msg_puts("()"); -- cgit From b85f1dafc7c0a19704135617454f1c66f41202c1 Mon Sep 17 00:00:00 2001 From: bfredl Date: Wed, 27 Sep 2023 22:21:17 +0200 Subject: refactor(messages): fold msg_attr into msg problem: there are too many different functions in message.c solution: fold some of the functions into themselves --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 60cf0f8054..8273e8434d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1352,7 +1352,7 @@ static void list_one_var(dictitem_T *v, const char *prefix, int *first) static void list_one_var_a(const char *prefix, const char *name, const ptrdiff_t name_len, const VarType type, const char *string, int *first) { - // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" + // don't use msg() to avoid overwriting "v:statusmsg" msg_start(); msg_puts(prefix); if (name != NULL) { // "a:" vars don't have a name stored -- cgit From af7d317f3ff31d5ac5d8724b5057a422e1451b54 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 26 Sep 2023 22:36:08 +0200 Subject: refactor: remove long long is 32-bits even on 64-bit windows which makes the type suboptimal for a codebase meant to be cross-platform. --- src/nvim/eval/vars.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 8273e8434d..880836cc9f 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -801,8 +801,8 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, if (op != NULL && *op != '=') { if (!hidden && is_num) { // number or bool - Integer cur_n = curval.type == kOptValTypeNumber ? curval.data.number : curval.data.boolean; - Integer new_n = newval.type == kOptValTypeNumber ? newval.data.number : newval.data.boolean; + OptInt cur_n = curval.type == kOptValTypeNumber ? curval.data.number : curval.data.boolean; + OptInt new_n = newval.type == kOptValTypeNumber ? newval.data.number : newval.data.boolean; switch (*op) { case '+': @@ -1873,7 +1873,7 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string); } } - value = (flags & P_NUM) ? NUMBER_OPTVAL(n) + value = (flags & P_NUM) ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(n == 0 ? kFalse : (n >= 1 ? kTrue : kNone)); } else if ((flags & P_STRING) || is_tty_option(option)) { // Avoid setting string option to a boolean or a special value. -- cgit From 8e11c18d4962c5367a0549bdb2288323545852b6 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 29 Sep 2023 16:10:28 +0200 Subject: refactor(message): msg_puts_attr_len -> msg_puts_len --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 880836cc9f..64ba37eaac 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1356,7 +1356,7 @@ static void list_one_var_a(const char *prefix, const char *name, const ptrdiff_t msg_start(); msg_puts(prefix); if (name != NULL) { // "a:" vars don't have a name stored - msg_puts_attr_len(name, name_len, 0); + msg_puts_len(name, name_len, 0); } msg_putchar(' '); msg_advance(22); -- cgit From bc13bc154aa574e0bb58a50f2e0ca4570efa57c3 Mon Sep 17 00:00:00 2001 From: bfredl Date: Fri, 29 Sep 2023 16:10:54 +0200 Subject: refactor(message): smsg_attr -> smsg --- src/nvim/eval/userfunc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a5d7ed2758..0fe2396f8a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1117,7 +1117,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett no_wait_return++; verbose_enter_scroll(); - smsg(_("calling %s"), SOURCING_NAME); + smsg(0, _("calling %s"), SOURCING_NAME); if (p_verbose >= 14) { msg_puts("("); for (int i = 0; i < argcount; i++) { @@ -1235,9 +1235,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett verbose_enter_scroll(); if (aborting()) { - smsg(_("%s aborted"), SOURCING_NAME); + smsg(0, _("%s aborted"), SOURCING_NAME); } else if (fc->fc_rettv->v_type == VAR_NUMBER) { - smsg(_("%s returning #%" PRId64 ""), + smsg(0, _("%s returning #%" PRId64 ""), SOURCING_NAME, (int64_t)fc->fc_rettv->vval.v_number); } else { char buf[MSG_BUF_LEN]; @@ -1254,7 +1254,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); s = buf; } - smsg(_("%s returning %s"), SOURCING_NAME, s); + smsg(0, _("%s returning %s"), SOURCING_NAME, s); xfree(tofree); } } @@ -1277,7 +1277,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett no_wait_return++; verbose_enter_scroll(); - smsg(_("continuing in %s"), SOURCING_NAME); + smsg(0, _("continuing in %s"), SOURCING_NAME); msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); -- cgit From cf8b2c0e74fd5e723b0c15c2ce84e6900fd322d3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 12:05:28 +0800 Subject: build(iwyu): add a few more _defs.h mappings (#25435) --- src/nvim/eval/decode.c | 1 - src/nvim/eval/funcs.c | 4 +--- src/nvim/eval/typval.c | 1 + src/nvim/eval/userfunc.c | 4 ++-- src/nvim/eval/vars.c | 3 ++- src/nvim/eval/window.c | 1 - 6 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 70a629ea91..9c47e06f69 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -19,7 +19,6 @@ #include "nvim/eval/typval_defs.h" #include "nvim/garray.h" #include "nvim/gettext.h" -#include "nvim/hashtab.h" #include "nvim/macros.h" #include "nvim/mbyte.h" #include "nvim/memory.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 93075cf0e2..61f3793f4d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -63,12 +63,12 @@ #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/grid.h" -#include "nvim/hashtab.h" #include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/input.h" +#include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" @@ -76,12 +76,10 @@ #include "nvim/mark.h" #include "nvim/math.h" #include "nvim/mbyte.h" -#include "nvim/memfile_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/menu.h" #include "nvim/message.h" -#include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/msgpack_rpc/channel.h" #include "nvim/msgpack_rpc/channel_defs.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ba2c23ffe8..a392fc8a03 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -33,6 +33,7 @@ #include "nvim/message.h" #include "nvim/os/input.h" #include "nvim/pos.h" +#include "nvim/strings.h" #include "nvim/types.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 0fe2396f8a..f525bcbd45 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -13,7 +13,6 @@ #include "lauxlib.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" -#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/debugger.h" #include "nvim/eval.h" @@ -26,15 +25,16 @@ #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" +#include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" +#include "nvim/hashtab.h" #include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/mbyte.h" -#include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/option_defs.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 64ba37eaac..44b987b36e 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "nvim/ascii.h" @@ -19,7 +20,6 @@ #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" @@ -27,6 +27,7 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" +#include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/hashtab.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 26f5414565..6364128cfc 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -22,7 +22,6 @@ #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/macros.h" -#include "nvim/memline_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" -- cgit From dc6d0d2daf69e2fdadda81feb97906dbc962a239 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 14:41:34 +0800 Subject: refactor: reorganize option header files (#25437) - Move vimoption_T to option.h - option_defs.h is for option-related types - option_vars.h corresponds to Vim's option.h - option_defs.h and option_vars.h don't include each other --- src/nvim/eval/funcs.c | 1 + src/nvim/eval/typval.c | 8 ++++++++ src/nvim/eval/typval_defs.h | 14 ++++++-------- src/nvim/eval/userfunc.c | 2 +- src/nvim/eval/vars.c | 1 + src/nvim/eval/window.c | 1 - src/nvim/eval/window.h | 1 + 7 files changed, 18 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 61f3793f4d..710d9c73a5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -87,6 +87,7 @@ #include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/optionstr.h" #include "nvim/os/dl.h" #include "nvim/os/fileio.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a392fc8a03..1ff90dd201 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -50,6 +50,14 @@ typedef struct { bool item_compare_func_err; } sortinfo_T; +/// Structure representing one list item, used for sort array. +typedef struct { + listitem_T *item; ///< Sorted list item. + int idx; ///< Sorted list item index. +} ListSortItem; + +typedef int (*ListSorter)(const void *, const void *); + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/typval.c.generated.h" #endif diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 4099877539..d5e8cb0109 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -273,6 +273,12 @@ typedef struct { linenr_T sc_lnum; ///< line number } sctx_T; +/// Stores an identifier of a script or channel that last set an option. +typedef struct { + sctx_T script_ctx; /// script context where the option was last set + uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT. +} LastSet; + /// Maximum number of function arguments enum { MAX_FUNC_ARGS = 20, }; /// Short variable name length @@ -367,12 +373,4 @@ typedef struct list_stack_S { struct list_stack_S *prev; } list_stack_T; -/// Structure representing one list item, used for sort array. -typedef struct { - listitem_T *item; ///< Sorted list item. - int idx; ///< Sorted list item index. -} ListSortItem; - -typedef int (*ListSorter)(const void *, const void *); - #endif // NVIM_EVAL_TYPVAL_DEFS_H diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f525bcbd45..8d85c55e15 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -37,7 +37,7 @@ #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/os/input.h" #include "nvim/path.h" #include "nvim/profile.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 44b987b36e..f9dcfb3d9d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -36,6 +36,7 @@ #include "nvim/message.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_vars.h" #include "nvim/os/os.h" #include "nvim/search.h" #include "nvim/strings.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 6364128cfc..f64809f2ef 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -25,7 +25,6 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" -#include "nvim/option_defs.h" #include "nvim/pos.h" #include "nvim/types.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 995f0a55a9..671c8fbf79 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -11,6 +11,7 @@ #include "nvim/globals.h" #include "nvim/mark.h" #include "nvim/option_defs.h" +#include "nvim/option_vars.h" #include "nvim/os/os.h" #include "nvim/pos.h" #include "nvim/vim.h" -- cgit From f6e72c3dfed83b02483976eaedb27819df9a878d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 30 Sep 2023 19:14:24 +0800 Subject: vim-patch:9.0.1962: No support for writing extended attributes Problem: No support for writing extended attributes Solution: Add extended attribute support for linux It's been a long standing issue, that if you write a file with extended attributes and backupcopy is set to no, the file will loose the extended attributes. So this patch adds support for retrieving the extended attributes and copying it to the new file. It currently only works on linux, mainly because I don't know the different APIs for other systems (BSD, MacOSX and Solaris). On linux, this should be supported since Kernel 2.4 or something, so this should be pretty safe to use now. Enable the extended attribute support with normal builds. I also added it explicitly to the :version output as well as make it able to check using `:echo has("xattr")`, to have users easily check that this is available. In contrast to the similar support for SELINUX and SMACK support (which also internally uses extended attributes), I have made this a FEAT_XATTR define, instead of the similar HAVE_XATTR. Add a test and change CI to include relevant packages so that CI can test that extended attributes are correctly written. closes: vim/vim#306 closes: vim/vim#13203 https://github.com/vim/vim/commit/e085dfda5d8dde064b0332464040959479696d1c Co-authored-by: Christian Brabandt --- src/nvim/eval/funcs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 710d9c73a5..5bfce7c272 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3171,6 +3171,9 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "windows", "winaltkeys", "writebackup", +#ifdef HAVE_XATTR + "xattr", +#endif "nvim", }; -- cgit From 09a17f91d0d362c6e58bfdbe3ccdeacffb0b44b9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 2 Oct 2023 10:45:33 +0800 Subject: refactor: move cmdline completion types to cmdexpand_defs.h (#25465) --- src/nvim/eval/funcs.c | 1 + src/nvim/eval/funcs.h | 1 + src/nvim/eval/typval_defs.h | 13 +++++++++++++ src/nvim/eval/userfunc.c | 1 + src/nvim/eval/userfunc.h | 1 + 5 files changed, 17 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5bfce7c272..ee70731c7c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -33,6 +33,7 @@ #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/context.h" #include "nvim/cursor.h" #include "nvim/diff.h" diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 5dab12787b..5f6132f68c 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -6,6 +6,7 @@ #include "nvim/api/private/dispatch.h" #include "nvim/buffer_defs.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" #include "nvim/types.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index d5e8cb0109..c0b5416a05 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -115,6 +115,19 @@ typedef enum { VAR_BLOB, ///< Blob, .v_blob is used. } VarType; +/// Type values for type(). +enum { + VAR_TYPE_NUMBER = 0, + VAR_TYPE_STRING = 1, + VAR_TYPE_FUNC = 2, + VAR_TYPE_LIST = 3, + VAR_TYPE_DICT = 4, + VAR_TYPE_FLOAT = 5, + VAR_TYPE_BOOL = 6, + VAR_TYPE_SPECIAL = 7, + VAR_TYPE_BLOB = 10, +}; + /// Structure that holds an internal variable value typedef struct { VarType v_type; ///< Variable type. diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 8d85c55e15..6b9801b805 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -14,6 +14,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/charset.h" +#include "nvim/cmdexpand_defs.h" #include "nvim/debugger.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 562c549b4b..c3fe56d30c 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -4,6 +4,7 @@ #include #include +#include "nvim/cmdexpand_defs.h" #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" -- cgit From e72b546354cd90bf0cd8ee6dd045538d713009ad Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 29 Sep 2023 14:58:48 +0200 Subject: refactor: the long goodbye long is 32 bits on windows, while it is 64 bits on other architectures. This makes the type suboptimal for a codebase meant to be cross-platform. Replace it with more appropriate integer types. --- src/nvim/eval/userfunc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 6b9801b805..e4adf9f340 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1126,7 +1126,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett msg_puts(", "); } if (argvars[i].v_type == VAR_NUMBER) { - msg_outnum((long)argvars[i].vval.v_number); + msg_outnum((int)argvars[i].vval.v_number); } else { // Do not want errors such as E724 here. emsg_off++; @@ -2263,7 +2263,7 @@ void ex_function(exarg_T *eap) } msg_putchar('\n'); if (!eap->forceit) { - msg_outnum((long)j + 1); + msg_outnum(j + 1); if (j < 9) { msg_putchar(' '); } -- cgit From 29fe883aa9166bdbcae3f935523c75a8aa56fe45 Mon Sep 17 00:00:00 2001 From: "Justin M. Keyes" Date: Wed, 4 Oct 2023 06:31:25 -0700 Subject: feat: ignore swapfile for running Nvim processes #25336 Problem: The swapfile "E325: ATTENTION" dialog is displayed when editing a file already open in another (running) Nvim. Usually this behavior is annoying and irrelevant: - "Recover" and the other options ("Open readonly", "Quit", "Abort") are almost never wanted. - swapfiles are less relevant for "multi-Nvim" since 'autoread' is enabled by default. - Even less relevant if user enables 'autowrite'. Solution: Define a default SwapExists handler which does the following: 1. If the swapfile is owned by a running Nvim process, automatically chooses "(E)dit anyway" (caveat: this creates a new, extra swapfile, which is mostly harmless and ignored except by `:recover` or `nvim -r`. 2. Shows a 1-line "ignoring swapfile..." message. 3. Users can disable the default SwapExists handler via `autocmd! nvim_swapfile`. --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/userfunc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ee70731c7c..4dd3f193e6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8236,7 +8236,7 @@ static void f_swapfilelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr static void f_swapinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_dict_alloc_ret(rettv); - get_b0_dict(tv_get_string(argvars), rettv->vval.v_dict); + swapfile_dict(tv_get_string(argvars), rettv->vval.v_dict); } /// "swapname(expr)" function diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e4adf9f340..ca98aad6bc 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2491,7 +2491,7 @@ void ex_function(exarg_T *eap) } else if (line_arg != NULL && *skipwhite(line_arg) != NUL) { nextcmd = line_arg; } else if (*p != NUL && *p != '"' && p_verbose > 0) { - give_warning2(_("W22: Text found after :endfunction: %s"), p, true); + swmsg(true, _("W22: Text found after :endfunction: %s"), p); } if (nextcmd != NULL) { // Another command follows. If the line came from "eap" we -- cgit From a58bb215449cee65b965b9094e9e996ddfe78315 Mon Sep 17 00:00:00 2001 From: bfredl Date: Thu, 5 Oct 2023 14:44:13 +0200 Subject: refactor(grid): get rid of unbatched grid_puts and grid_putchar This finalizes the long running refactor from the old TUI-focused grid implementation where text-drawing cursor was not separated from the visible cursor. Still, the pattern of setting cursor position together with updating a line was convenient. Introduce grid_line_cursor_goto() to still allow this but now being explicit about it. Only having batched drawing functions makes code involving drawing a bit longer. But it is better to be explicit, and this highlights cases where multiple small redraws can be grouped together. This was the case for most of the changed places (messages, lastline, and :intro) --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4dd3f193e6..eb2e2fb1e2 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6885,7 +6885,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) c = -1; } else { char buf[MB_MAXBYTES + 1]; - grid_getbytes(grid, row, col, buf, NULL); + schar_get(buf, grid_getchar(grid, row, col, NULL)); c = utf_ptr2char(buf); } rettv->vval.v_number = c; @@ -6906,7 +6906,7 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } char buf[MB_MAXBYTES + 1]; - grid_getbytes(grid, row, col, buf, NULL); + schar_get(buf, grid_getchar(grid, row, col, NULL)); int pcc[MAX_MCO]; int c = utfc_ptr2char(buf, pcc); int composing_len = 0; @@ -6951,7 +6951,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr } char buf[MB_MAXBYTES + 1]; - grid_getbytes(grid, row, col, buf, NULL); + schar_get(buf, grid_getchar(grid, row, col, NULL)); rettv->vval.v_string = xstrdup(buf); } -- cgit From 8e932480f61d6101bf8bea1abc07ed93826221fd Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 29 Sep 2023 14:58:48 +0200 Subject: refactor: the long goodbye long is 32 bits on windows, while it is 64 bits on other architectures. This makes the type suboptimal for a codebase meant to be cross-platform. Replace it with more appropriate integer types. --- src/nvim/eval/encode.c | 6 +++--- src/nvim/eval/funcs.c | 5 ++--- src/nvim/eval/typval.c | 23 +++++++++++------------ 3 files changed, 16 insertions(+), 18 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index fc9904a2d9..4a0c4ca19a 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -152,9 +152,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, ? 0 : (v.data.l.li == NULL ? tv_list_len(v.data.l.list) - 1 - : (int)tv_list_idx_of_item(v.data.l.list, - TV_LIST_ITEM_PREV(v.data.l.list, - v.data.l.li)))); + : tv_list_idx_of_item(v.data.l.list, + TV_LIST_ITEM_PREV(v.data.l.list, + v.data.l.li)))); const listitem_T *const li = (v.data.l.li == NULL ? tv_list_last(v.data.l.list) : TV_LIST_ITEM_PREV(v.data.l.list, diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index eb2e2fb1e2..782687e6b6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -526,7 +526,7 @@ buf_T *get_buf_arg(typval_T *arg) /// "byte2line(byte)" function static void f_byte2line(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - long boff = (long)tv_get_number(&argvars[0]) - 1; + int boff = (int)tv_get_number(&argvars[0]) - 1; if (boff < 0) { rettv->vval.v_number = -1; } else { @@ -8708,8 +8708,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (!callback_from_typval(&callback, &argvars[1])) { return; } - rettv->vval.v_number = (varnumber_T)timer_start((const long)tv_get_number(&argvars[0]), repeat, - &callback); + rettv->vval.v_number = (varnumber_T)timer_start(tv_get_number(&argvars[0]), repeat, &callback); } /// "timer_stop(timerid)" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 1ff90dd201..ea118e4bc6 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -620,7 +620,7 @@ tv_list_copy_error: /// Get the list item in "l" with index "n1". "n1" is adjusted if needed. /// Return NULL if there is no such item. -listitem_T *tv_list_check_range_index_one(list_T *const l, long *const n1, const bool quiet) +listitem_T *tv_list_check_range_index_one(list_T *const l, int *const n1, const bool quiet) { listitem_T *li = tv_list_find_index(l, n1); if (li == NULL) { @@ -636,11 +636,11 @@ listitem_T *tv_list_check_range_index_one(list_T *const l, long *const n1, const /// If "n1" or "n2" is negative it is changed to the positive index. /// "li1" is the item for item "n1". /// Return OK or FAIL. -int tv_list_check_range_index_two(list_T *const l, long *const n1, const listitem_T *const li1, - long *const n2, const bool quiet) +int tv_list_check_range_index_two(list_T *const l, int *const n1, const listitem_T *const li1, + int *const n2, const bool quiet) { if (*n2 < 0) { - listitem_T *ni = tv_list_find(l, (int)(*n2)); + listitem_T *ni = tv_list_find(l, *n2); if (ni == NULL) { if (!quiet) { semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n2)); @@ -670,11 +670,10 @@ int tv_list_check_range_index_two(list_T *const l, long *const n1, const listite /// "op" is the operator, normally "=" but can be "+=" and the like. /// "varname" is used for error messages. /// Returns OK or FAIL. -int tv_list_assign_range(list_T *const dest, list_T *const src, const long idx1_arg, - const long idx2, const bool empty_idx2, const char *const op, - const char *const varname) +int tv_list_assign_range(list_T *const dest, list_T *const src, const int idx1_arg, const int idx2, + const bool empty_idx2, const char *const op, const char *const varname) { - long idx1 = idx1_arg; + int idx1 = idx1_arg; listitem_T *const first_li = tv_list_find_index(dest, &idx1); listitem_T *src_li; @@ -1634,14 +1633,14 @@ const char *tv_list_find_str(list_T *const l, const int n) /// Like tv_list_find() but when a negative index is used that is not found use /// zero and set "idx" to zero. Used for first index of a range. -static listitem_T *tv_list_find_index(list_T *const l, long *const idx) +static listitem_T *tv_list_find_index(list_T *const l, int *const idx) FUNC_ATTR_WARN_UNUSED_RESULT { - listitem_T *li = tv_list_find(l, (int)(*idx)); + listitem_T *li = tv_list_find(l, *idx); if (li == NULL) { if (*idx < 0) { *idx = 0; - li = tv_list_find(l, (int)(*idx)); + li = tv_list_find(l, *idx); } } return li; @@ -1653,7 +1652,7 @@ static listitem_T *tv_list_find_index(list_T *const l, long *const idx) /// @param[in] item Item to search for. /// /// @return Index of an item or -1 if item is not in the list. -long tv_list_idx_of_item(const list_T *const l, const listitem_T *const item) +int tv_list_idx_of_item(const list_T *const l, const listitem_T *const item) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE { if (l == NULL) { -- cgit From 9ff6f73f838a1f90d09922448c434033ba5e094e Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Mon, 9 Oct 2023 00:36:48 +0600 Subject: refactor: allow not having a `default` case for enum Problem: The style guide states that all switch statements that are not conditional on an enum must have a `default` case, but does not give any explicit guideline for switch statements that are conditional on enums. As a result, a `default` case is added in many enum switch statements, even when the switch statement is exhaustive. This is not ideal because it removes the ability to have compiler errors to easily detect unchanged switch statements when a new possible value for an enum is added. Solution: Add explicit guidelines for switch statements that are conditional on an enum, clarifying that a `default` case is not necessary if the switch statement is exhaustive. Also refactor pre-existing code with unnecessary `default` cases. --- src/nvim/eval/funcs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 782687e6b6..b9d124532e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4990,9 +4990,10 @@ static int msgpackparse_convert_item(const msgpack_object data, const msgpack_un tv_list_append_owned_tv(ret_list, tv); return OK; } - default: + case MSGPACK_UNPACK_EXTRA_BYTES: abort(); } + UNREACHABLE; } static void msgpackparse_unpack_list(const list_T *const list, list_T *const ret_list) -- cgit From 3cbb02ce77087a820decd1a724a6e8b666e0ca36 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 12 Oct 2023 07:38:56 +0800 Subject: vim-patch:8.2.3064: Vim9: in script cannot set item in uninitialized list (#25605) Problem: Vim9: in script cannot set item in uninitialized list. Solution: When a list is NULL allocate an empty one. (closes vim/vim#8461) https://github.com/vim/vim/commit/e65081d1b591f16dc6e380a830d87565c5eb7b03 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index ea118e4bc6..9fca4adcf7 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -625,7 +625,7 @@ listitem_T *tv_list_check_range_index_one(list_T *const l, int *const n1, const listitem_T *li = tv_list_find_index(l, n1); if (li == NULL) { if (!quiet) { - semsg(_(e_list_index_out_of_range_nr), (int64_t)n1); + semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1)); } return NULL; } -- cgit From 0892c1cd94672e0dffe3b97fc4a85ea517b05598 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 16 Oct 2023 16:41:17 +0800 Subject: vim-patch:9.0.2033: gcc overflow-warning for f_resolve (#25666) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: gcc overflow-warning for f_resolve Solution: use pointer p instead of pointer q[-1] Suppress the following warning: ``` filepath.c: In function ‘f_resolve’: filepath.c:2162:27: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 2162 | q[-1] = NUL; ``` Closes: vim/vim#13352 closes: vim/vim#13353 https://github.com/vim/vim/commit/215c3261a25f7a99e8711a3b3c6158119c6aea9e Co-authored-by: Ken Takata --- src/nvim/eval/funcs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b9d124532e..0979087c79 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6098,13 +6098,13 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } // Ensure that the result will have a trailing path separator - // if the argument has one. */ + // if the argument has one. if (remain == NULL && has_trailing_pathsep) { add_pathsep(buf); } // Separate the first path component in the link value and - // concatenate the remainders. */ + // concatenate the remainders. q = (char *)path_next_component(vim_ispathsep(*buf) ? buf + 1 : buf); if (*q != NUL) { cpy = remain; @@ -6118,7 +6118,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) q = path_tail(p); if (q > p && *q == NUL) { // Ignore trailing path separator. - q[-1] = NUL; + p[q - p - 1] = NUL; q = path_tail(p); } if (q > p && !path_is_absolute(buf)) { -- cgit From 93b9c889465ee6a55e71c1fd681c1c6b1d5ed060 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Wed, 27 Sep 2023 23:30:17 +0600 Subject: refactor(options): unify set_num_option and set_bool_option --- src/nvim/eval/vars.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index f9dcfb3d9d..4b314ca338 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -822,7 +822,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const, if (curval.type == kOptValTypeNumber) { newval = NUMBER_OPTVAL(new_n); } else { - newval = BOOLEAN_OPTVAL(new_n == 0 ? kFalse : (new_n >= 1 ? kTrue : kNone)); + newval = BOOLEAN_OPTVAL(TRISTATE_FROM_INT(new_n)); } } else if (!hidden && is_string && curval.data.string.data != NULL && newval.data.string.data != NULL) { // string @@ -1875,8 +1875,7 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string); } } - value = (flags & P_NUM) ? NUMBER_OPTVAL((OptInt)n) - : BOOLEAN_OPTVAL(n == 0 ? kFalse : (n >= 1 ? kTrue : kNone)); + value = (flags & P_NUM) ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(TRISTATE_FROM_INT(n)); } else if ((flags & P_STRING) || is_tty_option(option)) { // Avoid setting string option to a boolean or a special value. if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { -- cgit From 5df4fdf253f9c9cc35f9f5f16c6d0ba9d87b4c71 Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Sun, 8 Oct 2023 22:13:15 +0600 Subject: refactor(options)!: make OptionSet `v:` values use typval BREAKING CHANGE: This breaks the OptionSet autocommand, as the `v:` values associated with it (`v:option_new`, `v:option_old`, `v:option_oldlocal` and `v:option_oldglobal`) are now the same type as the option, instead of all option values being converted to strings. --- src/nvim/eval/vars.c | 40 ++++++++++++++++++++++++++++++++++++++++ src/nvim/eval/vars.h | 1 + 2 files changed, 41 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 4b314ca338..ed400b2ee9 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -20,6 +20,7 @@ #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" @@ -1896,6 +1897,45 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo return value; } +/// Convert an option value to typval. +/// +/// @param[in] value Option value to convert. +/// +/// @return OptVal converted to typval. +typval_T optval_as_tv(OptVal value) +{ + typval_T rettv = { .v_type = VAR_SPECIAL, .vval = { .v_special = kSpecialVarNull } }; + + switch (value.type) { + case kOptValTypeNil: + break; + case kOptValTypeBoolean: + switch (value.data.boolean) { + case kTrue: + rettv.v_type = VAR_BOOL; + rettv.vval.v_bool = kBoolVarTrue; + break; + case kFalse: + rettv.v_type = VAR_BOOL; + rettv.vval.v_bool = kBoolVarFalse; + break; + case kNone: + break; // return v:null for None boolean value + } + break; + case kOptValTypeNumber: + rettv.v_type = VAR_NUMBER; + rettv.vval.v_number = value.data.number; + break; + case kOptValTypeString: + rettv.v_type = VAR_STRING; + rettv.vval.v_string = value.data.string.data; + break; + } + + return rettv; +} + /// Set option "varname" to the value of "varp" for the current buffer/window. static void set_option_from_tv(const char *varname, typval_T *varp) { diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index b87c9d62cb..12ff5b11cb 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -2,6 +2,7 @@ #define NVIM_EVAL_VARS_H #include "nvim/ex_cmds_defs.h" +#include "nvim/option_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" -- cgit From af010e23f38a23bb74ea5b61e1b1a05e76410b5f Mon Sep 17 00:00:00 2001 From: Famiu Haque Date: Fri, 13 Oct 2023 20:16:15 +0600 Subject: refactor(options): rename `empty_option` to `empty_string_option` --- src/nvim/eval/funcs.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 0979087c79..8e5bf68be1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -482,7 +482,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) int save_magic = p_magic; p_magic = true; char *save_cpo = p_cpo; - p_cpo = empty_option; + p_cpo = empty_string_option; buf_T *buf = buflist_findnr(buflist_findpat(name, name + strlen(name), true, false, curtab_only)); @@ -1733,7 +1733,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char *p_csl_save = p_csl; // avoid using 'completeslash' here - p_csl = empty_option; + p_csl = empty_string_option; #endif rettv->v_type = VAR_STRING; @@ -4516,7 +4516,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. char *save_cpo = p_cpo; - p_cpo = empty_option; + p_cpo = empty_string_option; rettv->vval.v_number = -1; switch (type) { @@ -7108,7 +7108,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. char *save_cpo = p_cpo; - p_cpo = empty_option; + p_cpo = empty_string_option; // Set the time limit, if there is one. proftime_T tm = profile_setlimit(time_limit); @@ -7234,7 +7234,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir xfree(pat2); xfree(pat3); - if (p_cpo == empty_option) { + if (p_cpo == empty_string_option) { p_cpo = save_cpo; } else { // Darn, evaluating the {skip} expression changed the value. @@ -7966,7 +7966,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; - p_cpo = empty_option; + p_cpo = empty_string_option; const char *str = tv_get_string(&argvars[0]); const char *pat = NULL; -- cgit From 9e3640a7797bcc5f6015548842572a6ce951a861 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 18 Oct 2023 18:27:50 +0800 Subject: vim-patch:9.0.2044: Vim9: exceptions confuse defered functions Problem: Vim9: exceptions confuse defered functions Solution: save and restore exception state when calling defered functions closes: vim/vim#13364 closes: vim/vim#13372 https://github.com/vim/vim/commit/0672595fd50e9ae668676a40e28ebf66d7f52392 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ca98aad6bc..f789c53870 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3296,8 +3296,23 @@ static void handle_defer_one(funccall_T *funccal) char *name = dr->dr_name; dr->dr_name = NULL; + // If the deferred function is called after an exception, then only the + // first statement in the function will be executed. Save and restore + // the try/catch/throw exception state. + const int save_trylevel = trylevel; + const bool save_did_throw = did_throw; + const bool save_need_rethrow = need_rethrow; + + trylevel = 0; + did_throw = false; + need_rethrow = false; + call_func(name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe); + trylevel = save_trylevel; + did_throw = save_did_throw; + need_rethrow = save_need_rethrow; + tv_clear(&rettv); xfree(name); for (int i = dr->dr_argcount - 1; i >= 0; i--) { -- cgit From a0961659770ca41edcb5a6dcf28e7c7492eb60f0 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 19 Oct 2023 18:34:48 +0800 Subject: vim-patch:9.0.2050: Vim9: crash with deferred function call and exception (#25715) Problem: Vim9: crash with deferred function call and exception Solution: Save and restore exception state Crash when a deferred function is called after an exception and another exception is thrown closes: vim/vim#13376 closes: vim/vim#13377 https://github.com/vim/vim/commit/c59c1e0d88651a71ece7366e418f1253abbe2a28 The change in check_due_timer() is N/A as Nvim calls timer callbacks on the main loop. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f789c53870..ff86f74338 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3297,21 +3297,16 @@ static void handle_defer_one(funccall_T *funccal) dr->dr_name = NULL; // If the deferred function is called after an exception, then only the - // first statement in the function will be executed. Save and restore - // the try/catch/throw exception state. - const int save_trylevel = trylevel; - const bool save_did_throw = did_throw; - const bool save_need_rethrow = need_rethrow; - - trylevel = 0; - did_throw = false; - need_rethrow = false; + // first statement in the function will be executed (because of the + // exception). So save and restore the try/catch/throw exception + // state. + exception_state_T estate; + exception_state_save(&estate); + exception_state_clear(); call_func(name, -1, &rettv, dr->dr_argcount, dr->dr_argvars, &funcexe); - trylevel = save_trylevel; - did_throw = save_did_throw; - need_rethrow = save_need_rethrow; + exception_state_restore(&estate); tv_clear(&rettv); xfree(name); -- cgit From 5f03a1eaabfc8de2b3a9c666fcd604763f41e152 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 20 Oct 2023 15:10:33 +0200 Subject: build(lint): remove unnecessary clint.py rules Uncrustify is the source of truth where possible. Remove any redundant checks from clint.py. --- src/nvim/eval/funcs.c | 14 +++++++------- src/nvim/eval/typval.c | 26 +++++++++++++------------- src/nvim/eval/typval.h | 4 ++-- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8e5bf68be1..4759b4ebe3 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2502,7 +2502,7 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) [kCdScopeTabpage] = 0, // Number of tab to look at. }; - char *cwd = NULL; // Current working directory to print + 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. @@ -3281,7 +3281,7 @@ static void f_haslocaldir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) [kCdScopeTabpage] = 0, // Number of tab to look at. }; - tabpage_T *tp = curtab; // The tabpage to look at. + tabpage_T *tp = curtab; // The tabpage to look at. win_T *win = curwin; // The window to look at. rettv->v_type = VAR_NUMBER; @@ -5258,7 +5258,7 @@ static void f_prompt_setinterrupt(typval_T *argvars, typval_T *rettv, EvalFuncDa } callback_free(&buf->b_prompt_interrupt); - buf->b_prompt_interrupt= interrupt_callback; + buf->b_prompt_interrupt = interrupt_callback; } /// "prompt_getprompt({buffer})" function @@ -5589,9 +5589,9 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl char buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1 int io_size = sizeof(buf); char *prev = NULL; // previously read bytes, if any - ptrdiff_t prevlen = 0; // length of data in prev + ptrdiff_t prevlen = 0; // length of data in prev ptrdiff_t prevsize = 0; // size of prev buffer - int64_t maxline = MAXLNUM; + int64_t maxline = MAXLNUM; off_T offset = 0; off_T size = -1; @@ -5651,7 +5651,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); p++) { if (readlen <= 0 || *p == '\n') { - char *s = NULL; + char *s = NULL; size_t len = (size_t)(p - start); // Finished a line. Remove CRs before NL. @@ -5754,7 +5754,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl prevsize = p - start; } else { ptrdiff_t grow50pc = (prevsize * 3) / 2; - ptrdiff_t growmin = (p - start) * 2 + prevlen; + ptrdiff_t growmin = (p - start) * 2 + prevlen; prevsize = grow50pc > growmin ? grow50pc : growmin; } prev = xrealloc(prev, (size_t)prevsize); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9fca4adcf7..badb948584 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3964,13 +3964,13 @@ bool tv_check_str_or_nr(const typval_T *const tv) #define FUNC_ERROR "E703: Using a Funcref as a Number" static const char *const num_errors[] = { - [VAR_PARTIAL]= N_(FUNC_ERROR), - [VAR_FUNC]= N_(FUNC_ERROR), - [VAR_LIST]= N_("E745: Using a List as a Number"), - [VAR_DICT]= N_("E728: Using a Dictionary as a Number"), - [VAR_FLOAT]= N_("E805: Using a Float as a Number"), - [VAR_BLOB]= N_("E974: Using a Blob as a Number"), - [VAR_UNKNOWN]= N_("E685: using an invalid value as a Number"), + [VAR_PARTIAL] = N_(FUNC_ERROR), + [VAR_FUNC] = N_(FUNC_ERROR), + [VAR_LIST] = N_("E745: Using a List as a Number"), + [VAR_DICT] = N_("E728: Using a Dictionary as a Number"), + [VAR_FLOAT] = N_("E805: Using a Float as a Number"), + [VAR_BLOB] = N_("E974: Using a Blob as a Number"), + [VAR_UNKNOWN] = N_("E685: using an invalid value as a Number"), }; #undef FUNC_ERROR @@ -4009,12 +4009,12 @@ bool tv_check_num(const typval_T *const tv) #define FUNC_ERROR "E729: Using a Funcref as a String" static const char *const str_errors[] = { - [VAR_PARTIAL]= N_(FUNC_ERROR), - [VAR_FUNC]= N_(FUNC_ERROR), - [VAR_LIST]= N_("E730: Using a List as a String"), - [VAR_DICT]= N_("E731: Using a Dictionary as a String"), - [VAR_BLOB]= N_("E976: Using a Blob as a String"), - [VAR_UNKNOWN]= e_using_invalid_value_as_string, + [VAR_PARTIAL] = N_(FUNC_ERROR), + [VAR_FUNC] = N_(FUNC_ERROR), + [VAR_LIST] = N_("E730: Using a List as a String"), + [VAR_DICT] = N_("E731: Using a Dictionary as a String"), + [VAR_BLOB] = N_("E976: Using a Blob as a String"), + [VAR_UNKNOWN] = e_using_invalid_value_as_string, }; #undef FUNC_ERROR diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 0b42a473cf..7a168ba183 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -485,8 +485,8 @@ static inline bool tv_is_func(const typval_T tv) #ifdef UNIT_TESTING // Do not use enum constants, see commit message. -EXTERN const size_t kTVCstring INIT(= TV_CSTRING); -EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE); +EXTERN const size_t kTVCstring INIT( = TV_CSTRING); +EXTERN const size_t kTVTranslate INIT( = TV_TRANSLATE); #endif #ifdef INCLUDE_GENERATED_DECLARATIONS -- cgit From 684e93054b82c6b5b215db7d3ecbad803eb81f0e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 25 Oct 2023 09:59:02 +0800 Subject: fix(terminal): assign channel to terminal earlier (#25771) --- src/nvim/eval/funcs.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4759b4ebe3..aae544f28d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8637,8 +8637,10 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) INTEGER_OBJ(pid), false, false, &err); api_clear_error(&err); + channel_incref(chan); channel_terminal_open(curbuf, chan); channel_create_event(chan, NULL); + channel_decref(chan); } /// "timer_info([timer])" function -- cgit From f97248db757ee300b7808c3dd67858d489b604fd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 28 Oct 2023 10:06:43 +0800 Subject: vim-patch:9.0.2070: [security] disallow setting env in restricted mode (#25807) Problem: [security] disallow setting env in restricted mode Solution: Setting environment variables in restricted mode could potentially be used to execute shell commands. Disallow this. restricted mode: disable allow setting of environment variables Setting environment variables in restricted mode, may have some unwanted consequences. So, for example by setting $GCONV_PATH in restricted mode and then calling the iconv() function, one may be able to execute some unwanted payload, because the `iconv_open()` function internally uses the `$GCONV_PATH` variable to find its conversion data. So let's disable setting environment variables, even so this is no complete protection, since we are not clearing the existing environment. I tried a few ways but wasn't successful :( One could also argue to disable the iconv() function completely in restricted mode, but who knows what other API functions can be influenced by setting some other unrelated environment variables. So let's leave it as it is currently. closes: vim/vim#13394 See: https://huntr.com/bounties/b0a2eda1-459c-4e36-98e6-0cc7d7faccfe/ https://github.com/vim/vim/commit/6b89dd6a7257a1e2e9c7ea070b407bc4674a5118 Co-authored-by: Christian Brabandt --- src/nvim/eval/funcs.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index aae544f28d..c12fd9fd31 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7436,6 +7436,13 @@ static void f_setenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char valbuf[NUMBUFLEN]; const char *name = tv_get_string_buf(&argvars[0], namebuf); + // seting an environment variable may be dangerous, e.g. you could + // setenv GCONV_PATH=/tmp and then have iconv() unexpectedly call + // a shell command using some shared library: + if (check_secure()) { + return; + } + if (argvars[1].v_type == VAR_SPECIAL && argvars[1].vval.v_special == kSpecialVarNull) { vim_unsetenv_ext(name); -- cgit From acc646ad8fc3ef11fcc63b69f3d8484e4a91accd Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 29 Sep 2023 14:58:48 +0200 Subject: refactor: the long goodbye long is 32 bits on windows, while it is 64 bits on other architectures. This makes the type suboptimal for a codebase meant to be cross-platform. Replace it with more appropriate integer types. --- src/nvim/eval/funcs.c | 62 ++++++++++++++++++++++++------------------------ src/nvim/eval/typval.c | 4 ++-- src/nvim/eval/typval.h | 2 +- src/nvim/eval/userfunc.c | 2 +- src/nvim/eval/vars.c | 6 ++--- 5 files changed, 38 insertions(+), 38 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c12fd9fd31..505a91813a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -983,7 +983,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int64_t idx = 0; if (argvars[2].v_type != VAR_UNKNOWN && argvars[3].v_type != VAR_UNKNOWN) { - idx = (long)tv_get_number_chk(&argvars[3], &error); + idx = (int64_t)tv_get_number_chk(&argvars[3], &error); } if (!error) { n = count_list(argvars[0].vval.v_list, &argvars[1], idx, ic); @@ -1860,11 +1860,11 @@ static void flatten_common(typval_T *argvars, typval_T *rettv, bool make_copy) return; } - long maxdepth; + int maxdepth; if (argvars[1].v_type == VAR_UNKNOWN) { maxdepth = 999999; } else { - maxdepth = (long)tv_get_number_chk(&argvars[1], &error); + maxdepth = (int)tv_get_number_chk(&argvars[1], &error); if (error) { return; } @@ -1929,7 +1929,7 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new, listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { - long before = (long)tv_get_number_chk(&argvars[2], &error); + int before = (int)tv_get_number_chk(&argvars[2], &error); if (error) { return; // Type error; errmsg already given. } @@ -1937,7 +1937,7 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new, if (before == tv_list_len(l1)) { item = NULL; } else { - item = tv_list_find(l1, (int)before); + item = tv_list_find(l1, before); if (item == NULL) { semsg(_(e_list_index_out_of_range_nr), (int64_t)before); return; @@ -3394,7 +3394,7 @@ static void f_indent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "index()" function static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - long idx = 0; + int idx = 0; bool ic = false; rettv->vval.v_number = -1; @@ -3421,7 +3421,7 @@ static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) for (idx = start; idx < tv_blob_len(b); idx++) { typval_T tv; tv.v_type = VAR_NUMBER; - tv.vval.v_number = tv_blob_get(b, (int)idx); + tv.vval.v_number = tv_blob_get(b, idx); if (tv_equal(&tv, &argvars[1], ic, false)) { rettv->vval.v_number = idx; return; @@ -3447,7 +3447,7 @@ static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (error || idx == -1) { item = NULL; } else { - item = tv_list_find(l, (int)idx); + item = tv_list_find(l, idx); assert(item != NULL); } if (argvars[3].v_type != VAR_UNKNOWN) { @@ -3690,11 +3690,11 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - long before = 0; + int before = 0; const int len = tv_blob_len(b); if (argvars[2].v_type != VAR_UNKNOWN) { - before = (long)tv_get_number_chk(&argvars[2], &error); + before = (int)tv_get_number_chk(&argvars[2], &error); if (error) { return; // type error; errmsg already given } @@ -4511,7 +4511,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, colnr_T startcol = 0; bool match = false; list_T *l = NULL; - long idx = 0; + int idx = 0; char *tofree = NULL; // Make 'cpoptions' empty, the 'l' flag should not be used here. @@ -4550,7 +4550,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, li = tv_list_first(l); } else { expr = str = (char *)tv_get_string(&argvars[0]); - len = (long)strlen(str); + len = (int64_t)strlen(str); } char patbuf[NUMBUFLEN]; @@ -4571,7 +4571,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, if (idx == -1) { goto theend; } - li = tv_list_find(l, (int)idx); + li = tv_list_find(l, idx); } else { if (start < 0) { start = 0; @@ -5414,10 +5414,10 @@ static void f_rand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) 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)); + typval_T *const tvx = TV_LIST_ITEM_TV(tv_list_find(l, 0)); + typval_T *const tvy = TV_LIST_ITEM_TV(tv_list_find(l, 1)); + typval_T *const tvz = TV_LIST_ITEM_TV(tv_list_find(l, 2)); + typval_T *const tvw = TV_LIST_ITEM_TV(tv_list_find(l, 3)); if (tvx->v_type != VAR_NUMBER) { goto theend; } @@ -5861,8 +5861,8 @@ static int list2proftime(typval_T *arg, proftime_T *tm) FUNC_ATTR_NONNULL_ALL } bool error = false; - varnumber_T n1 = tv_list_find_nr(arg->vval.v_list, 0L, &error); - varnumber_T n2 = tv_list_find_nr(arg->vval.v_list, 1L, &error); + varnumber_T n1 = tv_list_find_nr(arg->vval.v_list, 0, &error); + varnumber_T n2 = tv_list_find_nr(arg->vval.v_list, 1, &error); if (error) { return FAIL; } @@ -7050,8 +7050,8 @@ static int searchpair_cmn(typval_T *argvars, pos_T *match_pos) } } - retval = (int)do_searchpair(spat, mpat, epat, dir, skip, - flags, match_pos, lnum_stop, time_limit); + retval = do_searchpair(spat, mpat, epat, dir, skip, + flags, match_pos, lnum_stop, time_limit); theend: p_ws = save_p_ws; @@ -7096,12 +7096,12 @@ static void f_searchpairpos(typval_T *argvars, typval_T *rettv, EvalFuncData fpt /// @param time_limit stop after this many msec /// /// @returns 0 or -1 for no match, -long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir, - const typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, - int64_t time_limit) +int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir, + const typval_T *skip, int flags, pos_T *match_pos, linenr_T lnum_stop, + int64_t time_limit) FUNC_ATTR_NONNULL_ARG(1, 2, 3) { - long retval = 0; + int retval = 0; int nest = 1; bool use_skip = false; int options = SEARCH_KEEP; @@ -7147,7 +7147,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir .sa_tm = &tm, }; - int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L, + int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1, options, RE_SEARCH, &sia); if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) { // didn't find it or found the first match again: FAIL @@ -7489,7 +7489,7 @@ static void f_setpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } /// Translate a register type string to the yank type and block length -static int get_yank_type(char **const pp, MotionType *const yank_type, long *const block_len) +static int get_yank_type(char **const pp, MotionType *const yank_type, int *const block_len) FUNC_ATTR_NONNULL_ALL { char *stropt = *pp; @@ -7507,7 +7507,7 @@ static int get_yank_type(char **const pp, MotionType *const yank_type, long *con *yank_type = kMTBlockWise; if (ascii_isdigit(stropt[1])) { stropt++; - *block_len = getdigits_long(&stropt, false, 0) - 1; + *block_len = getdigits_int(&stropt, false, 0) - 1; stropt--; } break; @@ -7523,7 +7523,7 @@ static void f_setreg(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { bool append = false; - long block_len = -1; + int block_len = -1; MotionType yank_type = kMTUnknown; rettv->vval.v_number = 1; // FAIL is default. @@ -7735,11 +7735,11 @@ static void f_shiftwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = 0; if (argvars[0].v_type != VAR_UNKNOWN) { - long col = (long)tv_get_number_chk(argvars, NULL); + colnr_T col = (colnr_T)tv_get_number_chk(argvars, NULL); if (col < 0) { return; // type error; errmsg already given } - rettv->vval.v_number = get_sw_value_col(curbuf, (colnr_T)col); + rettv->vval.v_number = get_sw_value_col(curbuf, col); return; } rettv->vval.v_number = get_sw_value(curbuf); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index badb948584..3657e182af 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -678,7 +678,7 @@ int tv_list_assign_range(list_T *const dest, list_T *const src, const int idx1_a listitem_T *src_li; // Check whether any of the list items is locked before making any changes. - long idx = idx1; + int idx = idx1; listitem_T *dest_li = first_li; for (src_li = tv_list_first(src); src_li != NULL && dest_li != NULL;) { if (value_check_lock(TV_LIST_ITEM_TV(dest_li)->v_lock, varname, TV_CSTRING)) { @@ -738,7 +738,7 @@ int tv_list_assign_range(list_T *const dest, list_T *const src, const int idx1_a /// @param[in] maxdepth Maximum depth that will be flattened /// /// @return OK or FAIL -void tv_list_flatten(list_T *list, listitem_T *first, long maxitems, long maxdepth) +void tv_list_flatten(list_T *list, listitem_T *first, int64_t maxitems, int64_t maxdepth) FUNC_ATTR_NONNULL_ARG(1) { listitem_T *item; diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 7a168ba183..d2baabb424 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -235,7 +235,7 @@ static inline long tv_dict_len(const dict_T *d) static inline long tv_dict_len(const dict_T *const d) { if (d == NULL) { - return 0L; + return 0; } return (long)d->dv_hashtab.ht_used; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ff86f74338..6e7b1e4d67 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2422,7 +2422,7 @@ void ex_function(exarg_T *eap) } else { xfree(line_to_free); if (eap->getline == NULL) { - theline = getcmdline(':', 0L, indent, do_concat); + theline = getcmdline(':', 0, indent, do_concat); } else { theline = eap->getline(':', eap->cookie, indent, do_concat); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ed400b2ee9..33256b78e1 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1088,13 +1088,13 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ /// Unlet one item or a range of items from a list. /// Return OK or FAIL. -static void tv_list_unlet_range(list_T *const l, listitem_T *const li_first, const long n1_arg, - const bool has_n2, const long n2) +static void tv_list_unlet_range(list_T *const l, listitem_T *const li_first, const int n1_arg, + const bool has_n2, const int n2) { assert(l != NULL); // Delete a range of List items. listitem_T *li_last = li_first; - long n1 = n1_arg; + int n1 = n1_arg; while (true) { listitem_T *const li = TV_LIST_ITEM_NEXT(l, li_last); n1++; -- cgit From 1c71c32b29100b3e2989447da9d94b97b2c9959e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 8 Nov 2023 06:29:58 +0800 Subject: fix(job-control): make jobwait() flush UI after hiding cursor (#25927) --- src/nvim/eval/funcs.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 505a91813a..550d296093 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4187,6 +4187,7 @@ static void f_jobwait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } ui_busy_start(); + ui_flush(); list_T *args = argvars[0].vval.v_list; Channel **jobs = xcalloc((size_t)tv_list_len(args), sizeof(*jobs)); MultiQueue *waiting_jobs = multiqueue_new_parent(loop_on_put, &main_loop); -- cgit From cd63a9addd6e1114c3524fa041ece560550cfe7b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 10 Nov 2023 08:39:21 +0800 Subject: refactor: change some xstrndup() and xstrnsave() to xmemdupz() (#25959) When the given length is exactly the number of bytes to copy, xmemdupz() makes the intention clearer. --- src/nvim/eval/funcs.c | 6 +++--- src/nvim/eval/userfunc.c | 12 ++++++------ src/nvim/eval/vars.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 550d296093..36d368a913 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5669,7 +5669,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl } if (prevlen == 0) { assert(len < INT_MAX); - s = xstrnsave(start, len); + s = xmemdupz(start, len); } else { // Change "prev" buffer to be the right size. This way // the bytes are only copied once, and very long lines are @@ -6305,7 +6305,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) *rettv = (typval_T){ .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrnsave(p, (size_t)len), + .vval.v_string = xmemdupz(p, (size_t)len), }; p += len; } else if (tv_check_for_string_arg(argvars, 2) == FAIL) { @@ -6321,7 +6321,7 @@ static void reduce_string(typval_T *argvars, typval_T *expr, typval_T *rettv) argv[1] = (typval_T){ .v_type = VAR_STRING, .v_lock = VAR_UNLOCKED, - .vval.v_string = xstrnsave(p, (size_t)len), + .vval.v_string = xmemdupz(p, (size_t)len), }; const int r = eval_expr_typval(expr, true, argv, 2, rettv); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 6e7b1e4d67..4b50710649 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1625,7 +1625,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t if (fp == NULL) { // Make a copy of the name, if it comes from a funcref variable it could // be changed or deleted in the called function. - name = xstrnsave(funcname, (size_t)len); + name = xmemdupz(funcname, (size_t)len); fname = fname_trans_sid(name, fname_buf, &tofree, &error); } @@ -2089,7 +2089,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) if (strncmp(p, "", 8) == 0) { p += 8; (void)getdigits(&p, false, 0); - saved = xstrndup(*name, (size_t)(p - *name)); + saved = xmemdupz(*name, (size_t)(p - *name)); if (fudi != NULL) { CLEAR_POINTER(fudi); } @@ -2573,12 +2573,12 @@ void ex_function(exarg_T *eap) if (strncmp(p, "trim", 4) == 0) { // Ignore leading white space. p = skipwhite(p + 4); - heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); + heredoc_trimmed = xmemdupz(theline, (size_t)(skipwhite(theline) - theline)); } if (*p == NUL) { skip_until = xstrdup("."); } else { - skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p)); + skip_until = xmemdupz(p, (size_t)(skiptowhite(p) - p)); } do_concat = false; is_heredoc = true; @@ -2598,7 +2598,7 @@ void ex_function(exarg_T *eap) if (strncmp(p, "trim", 4) == 0) { // Ignore leading white space. p = skipwhite(p + 4); - heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); + heredoc_trimmed = xmemdupz(theline, (size_t)(skipwhite(theline) - theline)); continue; } if (strncmp(p, "eval", 4) == 0) { @@ -2608,7 +2608,7 @@ void ex_function(exarg_T *eap) } break; } - skip_until = xstrnsave(p, (size_t)(skiptowhite(p) - p)); + skip_until = xmemdupz(p, (size_t)(skiptowhite(p) - p)); do_concat = false; is_heredoc = true; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 33256b78e1..ed79d8a681 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -274,7 +274,7 @@ list_T *heredoc_get(exarg_T *eap, char *cmd, bool script_get) p++; text_indent_len++; } - text_indent = xstrnsave(theline, (size_t)text_indent_len); + text_indent = xmemdupz(theline, (size_t)text_indent_len); } // with "trim": skip the indent matching the first line if (text_indent != NULL) { -- cgit From d5a85d737aa2a5c3a64ef0aa5b01672b7ed49c09 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 10 Nov 2023 15:24:36 +0800 Subject: fix(f_wait): flush UI before blocking (#25962) --- src/nvim/eval/funcs.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 36d368a913..2d8ad458f1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2911,6 +2911,9 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool error = false; const int called_emsg_before = called_emsg; + // Flush screen updates before blocking. + ui_flush(); + LOOP_PROCESS_EVENTS_UNTIL(&main_loop, main_loop.events, timeout, eval_expr_typval(&expr, false, &argv, 0, &exprval) != OK || tv_get_number_chk(&exprval, &error) -- cgit From e9b9a86cd5a555943b87f0ba40c4527561c3c124 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 11 Nov 2023 10:21:14 +0800 Subject: fix(context): don't crash on invalid arg to nvim_get_context (#25977) Note: The crash happens in the second test case when using uninitialized memory, and therefore doesn't happen with ASAN. --- src/nvim/eval/funcs.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 2d8ad458f1..6efd9733e5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -358,6 +358,7 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (!object_to_vim(result, rettv, &err)) { + assert(ERROR_SET(&err)); semsg(_("Error converting the call result: %s"), err.msg); } @@ -1024,7 +1025,7 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) Dictionary ctx_dict = ctx_to_dict(ctx); Error err = ERROR_INIT; - object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err); + (void)object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err); api_free_dictionary(ctx_dict); api_clear_error(&err); } @@ -1090,14 +1091,16 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - int save_did_emsg = did_emsg; + const int save_did_emsg = did_emsg; did_emsg = false; Dictionary dict = vim_to_object(&argvars[0]).data.dictionary; Context tmp = CONTEXT_INIT; - ctx_from_dict(dict, &tmp); + Error err = ERROR_INIT; + ctx_from_dict(dict, &tmp, &err); - if (did_emsg) { + if (ERROR_SET(&err)) { + semsg("%s", err.msg); ctx_free(&tmp); } else { ctx_free(ctx); @@ -1105,6 +1108,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } api_free_dictionary(dict); + api_clear_error(&err); did_emsg = save_did_emsg; } @@ -6753,6 +6757,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (!object_to_vim(result, rettv, &err)) { + assert(ERROR_SET(&err)); semsg(_("Error converting the call result: %s"), err.msg); } -- cgit From 8e58d37f2e15ac8540377148e55ed08a039aadb6 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 11 Nov 2023 11:20:08 +0100 Subject: refactor: remove redundant casts --- src/nvim/eval/userfunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4b50710649..aff4f1de62 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -963,7 +963,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett funccall_T *fc = create_funccal(fp, rettv); fc->fc_level = ex_nesting_level; // Check if this function has a breakpoint. - fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, (linenr_T)0); + fc->fc_breakpoint = dbg_find_breakpoint(false, fp->uf_name, 0); fc->fc_dbg_tick = debug_tick; // Set up fields for closure. ga_init(&fc->fc_ufuncs, sizeof(ufunc_T *), 1); -- cgit From 353a4be7e84fdc101318215bdcc8a7e780d737fe Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 12 Nov 2023 13:13:58 +0100 Subject: build: remove PVS We already have an extensive suite of static analysis tools we use, which causes a fair bit of redundancy as we get duplicate warnings. PVS is also prone to give false warnings which creates a lot of work to identify and disable. --- src/nvim/eval/buffer.c | 3 --- src/nvim/eval/decode.c | 5 +---- src/nvim/eval/encode.c | 3 --- src/nvim/eval/executor.c | 3 --- src/nvim/eval/funcs.c | 9 +++------ src/nvim/eval/gc.c | 3 --- src/nvim/eval/typval.c | 5 +---- src/nvim/eval/typval_encode.c.h | 17 +++++++---------- src/nvim/eval/userfunc.c | 7 ++----- src/nvim/eval/vars.c | 3 --- src/nvim/eval/window.c | 3 --- 11 files changed, 14 insertions(+), 47 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index b480d25367..a26ba54ca3 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // eval/buffer.c: Buffer related builtin functions #include diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 9c47e06f69..c090d1c9fe 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include #include @@ -964,7 +961,7 @@ int msgpack_to_vim(const msgpack_object mobj, typval_T *const rettv) } break; case MSGPACK_OBJECT_NEGATIVE_INTEGER: - if (mobj.via.i64 >= VARNUMBER_MIN) { // -V547 + if (mobj.via.i64 >= VARNUMBER_MIN) { *rettv = (typval_T) { .v_type = VAR_NUMBER, .v_lock = VAR_UNLOCKED, diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 4a0c4ca19a..709733564e 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - /// @file encode.c /// /// File containing functions for encoding and decoding Vimscript values. diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 7668fb129f..62c59db932 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6efd9733e5..c6909245af 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include #include @@ -4810,7 +4807,7 @@ static void f_min(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "mkdir()" function static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - int prot = 0755; // -V536 + int prot = 0755; rettv->vval.v_number = FAIL; if (check_secure()) { @@ -5732,9 +5729,9 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl // have to shuffle buf to close gap int adjust_prevlen = 0; - if (dest < buf) { // -V782 + if (dest < buf) { // adjust_prevlen must be 1 or 2. - adjust_prevlen = (int)(buf - dest); // -V782 + adjust_prevlen = (int)(buf - dest); dest = buf; } if (readlen > p - buf + 1) { diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c index 6a54c4ddc1..bcebd87f71 100644 --- a/src/nvim/eval/gc.c +++ b/src/nvim/eval/gc.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include "nvim/eval/gc.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 3657e182af..8a38315706 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - #include #include #include @@ -4422,7 +4419,7 @@ const char *tv_get_string_buf_chk(const typval_T *const tv, char *const buf) { switch (tv->v_type) { case VAR_NUMBER: - snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); // -V576 + snprintf(buf, NUMBUFLEN, "%" PRIdVARNUMBER, tv->vval.v_number); return buf; case VAR_FLOAT: vim_snprintf(buf, NUMBUFLEN, "%g", tv->vval.v_float); diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 6d29286a58..b958239223 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -252,8 +252,6 @@ #include "nvim/func_attr.h" #include "klib/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 @@ -347,8 +345,8 @@ 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(tv, (pt == NULL ? NULL : partial_name(pt))); // -V547 - _mp_push(*mpstack, ((MPConvStackVal) { // -V779 + TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); + _mp_push(*mpstack, ((MPConvStackVal) { .type = kMPConvPartial, .tv = tv, .saved_copyID = copyID - 1, @@ -396,7 +394,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_SPECIAL: switch (tv->vval.v_special) { case kSpecialVarNull: - TYPVAL_ENCODE_CONV_NIL(tv); // -V1037 + TYPVAL_ENCODE_CONV_NIL(tv); break; } break; @@ -509,7 +507,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } if (is_string) { TYPVAL_ENCODE_CONV_STR_STRING(tv, buf, len); - } else { // -V523 + } else { TYPVAL_ENCODE_CONV_STRING(tv, buf, len); } xfree(buf); @@ -544,8 +542,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } list_T *const val_list = val_di->di_tv.vval.v_list; if (val_list == NULL || tv_list_len(val_list) == 0) { - TYPVAL_ENCODE_CONV_EMPTY_DICT( // -V501 - tv, TYPVAL_ENCODE_NODICT_VAR); + TYPVAL_ENCODE_CONV_EMPTY_DICT(tv, TYPVAL_ENCODE_NODICT_VAR); break; } TV_LIST_ITER_CONST(val_list, li, { @@ -632,7 +629,7 @@ _convert_one_value_regular_dict: {} typval_encode_stop_converting_one_item: return OK; // Prevent “unused label” warnings. - goto typval_encode_stop_converting_one_item; // -V779 + goto typval_encode_stop_converting_one_item; } TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( @@ -835,5 +832,5 @@ encode_vim_to__error_ret: _mp_destroy(mpstack); return FAIL; // Prevent “unused label” warnings. - goto typval_encode_stop_converting_one_item; // -V779 + goto typval_encode_stop_converting_one_item; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index aff4f1de62..959dabafb5 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // User defined function support #include @@ -1214,7 +1211,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett if (func_or_func_caller_profiling) { call_start = profile_end(call_start); - call_start = profile_sub_wait(wait_start, call_start); // -V614 + call_start = profile_sub_wait(wait_start, call_start); fp->uf_tm_total = profile_add(fp->uf_tm_total, call_start); fp->uf_tm_self = profile_self(fp->uf_tm_self, call_start, fp->uf_tm_children); @@ -1400,7 +1397,7 @@ void free_all_functions(void) // Clean up the current_funccal chain and the funccal stack. while (current_funccal != NULL) { tv_clear(current_funccal->fc_rettv); - cleanup_function_call(current_funccal); // -V595 + cleanup_function_call(current_funccal); if (current_funccal == NULL && funccal_stack != NULL) { restore_funccal(); } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ed79d8a681..8cc3903f7a 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // eval/vars.c: functions for dealing with variables #include diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index f64809f2ef..c0607a4a34 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -1,6 +1,3 @@ -// This is an open source non-commercial project. Dear PVS-Studio, please check -// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com - // eval/window.c: Window related builtin functions #include -- cgit From 4f8941c1a5f1ef6caa410feeb52e343db22763ce Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 10 Nov 2023 12:23:42 +0100 Subject: refactor: replace manual header guards with #pragma once It is less error-prone than manually defining header guards. Pretty much all compilers support it even if it's not part of the C standard. --- src/nvim/eval/buffer.h | 4 +--- src/nvim/eval/decode.h | 4 +--- src/nvim/eval/encode.h | 4 +--- src/nvim/eval/executor.h | 4 +--- src/nvim/eval/funcs.h | 4 +--- src/nvim/eval/gc.h | 4 +--- src/nvim/eval/typval.h | 5 +---- src/nvim/eval/typval_defs.h | 5 +---- src/nvim/eval/typval_encode.h | 5 +---- src/nvim/eval/userfunc.h | 4 +--- src/nvim/eval/vars.h | 4 +--- src/nvim/eval/window.h | 4 +--- 12 files changed, 12 insertions(+), 39 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.h b/src/nvim/eval/buffer.h index 4a2f8f9e94..fdd146885a 100644 --- a/src/nvim/eval/buffer.h +++ b/src/nvim/eval/buffer.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_BUFFER_H -#define NVIM_EVAL_BUFFER_H +#pragma once #include "nvim/buffer_defs.h" #include "nvim/eval/typval_defs.h" @@ -7,4 +6,3 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/buffer.h.generated.h" #endif -#endif // NVIM_EVAL_BUFFER_H diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index 7455130221..3000cd3211 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_DECODE_H -#define NVIM_EVAL_DECODE_H +#pragma once #include #include @@ -10,4 +9,3 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" #endif -#endif // NVIM_EVAL_DECODE_H diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index b589b8b13f..a30016e724 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_ENCODE_H -#define NVIM_EVAL_ENCODE_H +#pragma once #include #include @@ -74,4 +73,3 @@ extern const char *const encode_special_var_names[]; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/encode.h.generated.h" #endif -#endif // NVIM_EVAL_ENCODE_H diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h index e8bf147245..58edf7216b 100644 --- a/src/nvim/eval/executor.h +++ b/src/nvim/eval/executor.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_EXECUTOR_H -#define NVIM_EVAL_EXECUTOR_H +#pragma once #include "nvim/eval/typval_defs.h" @@ -8,4 +7,3 @@ extern char *e_list_index_out_of_range_nr; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/executor.h.generated.h" #endif -#endif // NVIM_EVAL_EXECUTOR_H diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 5f6132f68c..858da53e13 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_FUNCS_H -#define NVIM_EVAL_FUNCS_H +#pragma once #include #include @@ -31,4 +30,3 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/funcs.h.generated.h" #endif -#endif // NVIM_EVAL_FUNCS_H diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h index 66e959ced5..ea91952fff 100644 --- a/src/nvim/eval/gc.h +++ b/src/nvim/eval/gc.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_GC_H -#define NVIM_EVAL_GC_H +#pragma once #include "nvim/eval/typval_defs.h" @@ -9,4 +8,3 @@ extern list_T *gc_first_list; #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/gc.h.generated.h" #endif -#endif // NVIM_EVAL_GC_H diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index d2baabb424..751b9646b3 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_TYPVAL_H -#define NVIM_EVAL_TYPVAL_H +#pragma once #include #include @@ -492,5 +491,3 @@ EXTERN const size_t kTVTranslate INIT( = TV_TRANSLATE); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/typval.h.generated.h" #endif - -#endif // NVIM_EVAL_TYPVAL_H diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index c0b5416a05..996dac20bc 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_TYPVAL_DEFS_H -#define NVIM_EVAL_TYPVAL_DEFS_H +#pragma once #include #include @@ -385,5 +384,3 @@ typedef struct list_stack_S { list_T *list; struct list_stack_S *prev; } list_stack_T; - -#endif // NVIM_EVAL_TYPVAL_DEFS_H diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index cf01926030..743acd8800 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -2,8 +2,7 @@ /// /// Contains common definitions for eval/typval_encode.c.h. Most of time should /// not be included directly. -#ifndef NVIM_EVAL_TYPVAL_ENCODE_H -#define NVIM_EVAL_TYPVAL_ENCODE_H +#pragma once #include #include @@ -140,5 +139,3 @@ static inline size_t tv_strlen(const typval_T *const tv) /// Name of the dummy const dict_T *const variable #define TYPVAL_ENCODE_NODICT_VAR \ _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var) - -#endif // NVIM_EVAL_TYPVAL_ENCODE_H diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index c3fe56d30c..7f77b55f27 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_USERFUNC_H -#define NVIM_EVAL_USERFUNC_H +#pragma once #include #include @@ -97,4 +96,3 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/userfunc.h.generated.h" #endif -#endif // NVIM_EVAL_USERFUNC_H diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 12ff5b11cb..124d73825b 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_VARS_H -#define NVIM_EVAL_VARS_H +#pragma once #include "nvim/ex_cmds_defs.h" #include "nvim/option_defs.h" @@ -7,4 +6,3 @@ #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" #endif -#endif // NVIM_EVAL_VARS_H diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 671c8fbf79..8502978ac1 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -1,5 +1,4 @@ -#ifndef NVIM_EVAL_WINDOW_H -#define NVIM_EVAL_WINDOW_H +#pragma once #include #include @@ -76,4 +75,3 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/window.h.generated.h" #endif -#endif // NVIM_EVAL_WINDOW_H -- cgit From e9bfbe99cd7154912ef00fb1144411ee5d173b28 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 13 Nov 2023 18:18:04 +0800 Subject: fix(textformat): remove unnecessary changed_bytes() (#26027) This was removed from Vim in patch 8.1.0681. --- src/nvim/eval/userfunc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 7f77b55f27..61ada9dd73 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -16,7 +16,7 @@ struct funccal_entry; // From user function to hashitem and back. #define UF2HIKEY(fp) ((fp)->uf_name) -#define HIKEY2UF(p) ((ufunc_T *)(p - offsetof(ufunc_T, uf_name))) +#define HIKEY2UF(p) ((ufunc_T *)((p) - offsetof(ufunc_T, uf_name))) #define HI2UF(hi) HIKEY2UF((hi)->hi_key) // flags used in uf_flags -- cgit From 326d46f690b383846f136f2a25523cffe2882f27 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 16 Nov 2023 09:54:47 +0800 Subject: refactor: move some functions to winfloat.c (#26020) --- src/nvim/eval/window.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index c0607a4a34..bcc29dfeed 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -26,6 +26,7 @@ #include "nvim/types.h" #include "nvim/vim.h" #include "nvim/window.h" +#include "nvim/winfloat.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/window.c.generated.h" @@ -635,7 +636,7 @@ void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (wp == NULL || targetwin == NULL || wp == targetwin || !win_valid(wp) || !win_valid(targetwin) - || win_valid_floating(wp) || win_valid_floating(targetwin)) { + || win_float_valid(wp) || win_float_valid(targetwin)) { emsg(_(e_invalwindow)); rettv->vval.v_number = -1; return; -- cgit From bb4b4576e384c71890b4df4fa4f1ae76fad3a59d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 16 Nov 2023 10:55:54 +0800 Subject: refactor: iwyu (#26062) --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 8cc3903f7a..3fd33720c9 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -17,7 +17,6 @@ #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" -#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/eval/window.h" @@ -34,6 +33,7 @@ #include "nvim/message.h" #include "nvim/ops.h" #include "nvim/option.h" +#include "nvim/option_defs.h" #include "nvim/option_vars.h" #include "nvim/os/os.h" #include "nvim/search.h" -- cgit From b522cb1ac3fbdf6e68eed5d0b6e1cbeaf3ac2254 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 6 Nov 2023 14:52:27 +0100 Subject: refactor(grid): make screen rendering more multibyte than ever before Problem: buffer text with composing chars are converted from UTF-8 to an array of up to seven UTF-32 values and then converted back to UTF-8 strings. Solution: Convert buffer text directly to UTF-8 based schar_T values. The limit of the text size is now in schar_T bytes, which is currently 31+1 but easily could be raised as it no longer multiplies the size of the entire screen grid when not used, the full size is only required for temporary scratch buffers. Also does some general cleanup to win_line text handling, which was unnecessarily complicated due to multibyte rendering being an "opt-in" feature long ago. Nowadays, a char is just a char, regardless if it consists of one ASCII byte or multiple bytes. --- src/nvim/eval/funcs.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c6909245af..8ef208f291 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5134,7 +5134,7 @@ static void f_nr2char(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - char buf[MB_MAXBYTES]; + char buf[MB_MAXCHAR]; const int len = utf_char2bytes((int)num, buf); rettv->v_type = VAR_STRING; @@ -6891,7 +6891,7 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { c = -1; } else { - char buf[MB_MAXBYTES + 1]; + char buf[MAX_SCHAR_SIZE + 1]; schar_get(buf, grid_getchar(grid, row, col, NULL)); c = utf_ptr2char(buf); } @@ -6907,24 +6907,22 @@ static void f_screenchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ScreenGrid *grid; screenchar_adjust(&grid, &row, &col); + tv_list_alloc_ret(rettv, kListLenMayKnow); if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) { - tv_list_alloc_ret(rettv, 0); return; } - char buf[MB_MAXBYTES + 1]; + char buf[MAX_SCHAR_SIZE + 1]; schar_get(buf, grid_getchar(grid, row, col, NULL)); - int pcc[MAX_MCO]; - int c = utfc_ptr2char(buf, pcc); - int composing_len = 0; - while (composing_len < MAX_MCO && pcc[composing_len] != 0) { - composing_len++; - } - tv_list_alloc_ret(rettv, composing_len + 1); - tv_list_append_number(rettv->vval.v_list, c); - for (int i = 0; i < composing_len; i++) { - tv_list_append_number(rettv->vval.v_list, pcc[i]); - } + + // schar values are already processed chars which are always NUL-terminated. + // A single [0] is expected when char is NUL. + size_t i = 0; + do { + int c = utf_ptr2char(buf + i); + tv_list_append_number(rettv->vval.v_list, c); + i += (size_t)utf_ptr2len(buf + i); + } while (buf[i] != NUL); } /// "screencol()" function @@ -6957,7 +6955,7 @@ static void f_screenstring(typval_T *argvars, typval_T *rettv, EvalFuncData fptr return; } - char buf[MB_MAXBYTES + 1]; + char buf[MAX_SCHAR_SIZE + 1]; schar_get(buf, grid_getchar(grid, row, col, NULL)); rettv->vval.v_string = xstrdup(buf); } @@ -7413,8 +7411,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt char *const csearch = tv_dict_get_string(d, "char", false); if (csearch != NULL) { - int pcc[MAX_MCO]; - const int c = utfc_ptr2char(csearch, pcc); + int c = utf_ptr2char(csearch); set_last_csearch(c, csearch, utfc_ptr2len(csearch)); } -- cgit From c4afb9788c4f139eb2e3b7aa4d6a6a20b67ba156 Mon Sep 17 00:00:00 2001 From: Luuk van Baal Date: Sat, 11 Nov 2023 00:52:50 +0100 Subject: refactor(sign): move legacy signs to extmarks Problem: The legacy signlist data structures and associated functions are redundant since the introduction of extmark signs. Solution: Store signs defined through the legacy commands in a hashmap, placed signs in the extmark tree. Replace signlist associated functions. Usage of the legacy sign commands should yield no change in behavior with the exception of: - "orphaned signs" are now always removed when the line it is placed on is deleted. This used to depend on the value of 'signcolumn'. - It is no longer possible to place multiple signs with the same identifier in a single group on multiple lines. This will now move the sign instead. Moreover, both signs placed through the legacy sign commands and through |nvim_buf_set_extmark()|: - Will show up in both |sign-place| and |nvim_buf_get_extmarks()|. - Are displayed by increasing sign identifier, left to right. Extmark signs used to be ordered decreasingly as opposed to legacy signs. --- src/nvim/eval/buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index a26ba54ca3..616c1e06fc 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -504,7 +504,7 @@ static dict_T *get_buffer_info(buf_T *buf) } tv_dict_add_list(dict, S_LEN("windows"), windows); - if (buf->b_signlist != NULL) { + if (buf->b_signs) { // List of signs placed in this buffer tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf)); } -- cgit From ac1113ded5f8f09dd99a9894d7a7e795626fb728 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 13 Nov 2023 23:40:37 +0100 Subject: refactor: follow style guide - reduce variable scope - prefer initialization over declaration and assignment --- src/nvim/eval/typval.c | 13 +++--- src/nvim/eval/userfunc.c | 107 ++++++++++++++++------------------------------- 2 files changed, 40 insertions(+), 80 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 8a38315706..74bde0147d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1155,9 +1155,8 @@ static int item_compare(const void *s1, const void *s2, bool keep_zero) res = sortinfo->item_compare_ic ? STRICMP(p1, p2) : strcmp(p1, p2); } } else { - double n1, n2; - n1 = strtod(p1, &p1); - n2 = strtod(p2, &p2); + double n1 = strtod(p1, &p1); + double n2 = strtod(p2, &p2); res = n1 == n2 ? 0 : n1 > n2 ? 1 : -1; } @@ -1187,8 +1186,6 @@ static int item_compare_not_keeping_zero(const void *s1, const void *s2) static int item_compare2(const void *s1, const void *s2, bool keep_zero) { - ListSortItem *si1, *si2; - int res; typval_T rettv; typval_T argv[3]; const char *func_name; @@ -1199,8 +1196,8 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) return 0; } - si1 = (ListSortItem *)s1; - si2 = (ListSortItem *)s2; + ListSortItem *si1 = (ListSortItem *)s1; + ListSortItem *si2 = (ListSortItem *)s2; if (partial == NULL) { func_name = sortinfo->item_compare_func; @@ -1218,7 +1215,7 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = sortinfo->item_compare_selfdict; - res = call_func(func_name, -1, &rettv, 2, argv, &funcexe); + int res = call_func(func_name, -1, &rettv, 2, argv, &funcexe); tv_clear(&argv[0]); tv_clear(&argv[1]); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 959dabafb5..822ac4d16a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -274,14 +274,13 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg) ufunc_T *fp = NULL; partial_T *pt = NULL; int varargs; - int ret; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; char *tofree = NULL; // First, check if this is a lambda expression. "->" must exists. char *s = skipwhite(*arg + 1); - ret = get_function_args(&s, '-', NULL, NULL, NULL, true); + int ret = get_function_args(&s, '-', NULL, NULL, NULL, true); if (ret == FAIL || *s != '>') { return NOTDONE; } @@ -794,8 +793,6 @@ static void cleanup_function_call(funccall_T *fc) /// @param[in] force When true, we are exiting. static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) { - int i; - if (fc == NULL) { return; } @@ -810,7 +807,7 @@ static void funccal_unref(funccall_T *fc, ufunc_T *fp, bool force) } } } - for (i = 0; i < fc->fc_ufuncs.ga_len; i++) { + for (int i = 0; i < fc->fc_ufuncs.ga_len; i++) { if (((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] == fp) { ((ufunc_T **)(fc->fc_ufuncs.ga_data))[i] = NULL; } @@ -1846,16 +1843,13 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part FUNC_ATTR_NONNULL_ARG(1) { char *name = NULL; - const char *start; - const char *end; - int lead; int len; lval_T lv; if (fdp != NULL) { CLEAR_POINTER(fdp); } - start = *pp; + const char *start = *pp; // Check for hard coded : already translated function ID (from a user // command). @@ -1867,14 +1861,14 @@ char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, part // A name starting with "" or "" is local to a script. But // don't skip over "s:", get_lval() needs it for "s:dict.func". - lead = eval_fname_script(start); + int lead = eval_fname_script(start); if (lead > 2) { start += lead; } // Note that TFN_ flags use the same values as GLV_ flags. - end = get_lval((char *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, - lead > 2 ? 0 : FNE_CHECK_START); + const char *end = 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")); @@ -2134,10 +2128,7 @@ void ex_function(exarg_T *eap) { char *theline; char *line_to_free = NULL; - char c; bool saved_wait_return = need_wait_return; - char *name = NULL; - char *p; char *arg; char *line_arg = NULL; garray_T newargs; @@ -2147,16 +2138,9 @@ void ex_function(exarg_T *eap) int flags = 0; ufunc_T *fp; bool overwrite = false; - int indent; - int nesting; - dictitem_T *v; funcdict_T fudi; static int func_nr = 0; // number for nameless function - int paren; hashtab_T *ht; - hashitem_T *hi; - linenr_T sourcing_lnum_off; - linenr_T sourcing_lnum_top; bool is_heredoc = false; char *skip_until = NULL; char *heredoc_trimmed = NULL; @@ -2174,11 +2158,11 @@ void ex_function(exarg_T *eap) // ":function /pat": list functions matching pattern. if (*eap->arg == '/') { - p = skip_regexp(eap->arg + 1, '/', true); + char *p = skip_regexp(eap->arg + 1, '/', true); if (!eap->skip) { regmatch_T regmatch; - c = *p; + char c = *p; *p = NUL; regmatch.regprog = vim_regcomp(eap->arg + 1, RE_MAGIC); *p = c; @@ -2209,9 +2193,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; - name = save_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi); - paren = (vim_strchr(p, '(') != NULL); + char *p = eap->arg; + char *name = save_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi); + int paren = (vim_strchr(p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) { // Return on an invalid expression in braces, unless the expression // evaluation has been cancelled due to an aborting error, an @@ -2395,10 +2379,10 @@ void ex_function(exarg_T *eap) } // Save the starting line number. - sourcing_lnum_top = SOURCING_LNUM; + linenr_T sourcing_lnum_top = SOURCING_LNUM; - indent = 2; - nesting = 0; + int indent = 2; + int nesting = 0; while (true) { if (KeyTyped) { msg_scroll = true; @@ -2442,7 +2426,7 @@ void ex_function(exarg_T *eap) } // Detect line continuation: SOURCING_LNUM increased more than one. - sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); + linenr_T sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); if (SOURCING_LNUM < sourcing_lnum_off) { sourcing_lnum_off -= SOURCING_LNUM; } else { @@ -2641,7 +2625,7 @@ void ex_function(exarg_T *eap) // If there are no errors, add the function if (fudi.fd_dict == NULL) { - v = find_var(name, strlen(name), &ht, false); + dictitem_T *v = find_var(name, strlen(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { emsg_funcname(N_("E707: Function name conflicts with variable: %s"), name); goto erret; @@ -2706,16 +2690,13 @@ void ex_function(exarg_T *eap) if (fp == NULL) { if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) { - int slen, plen; - char *scriptname; - // Check that the autoload name matches the script name. int j = FAIL; if (SOURCING_NAME != NULL) { - scriptname = autoload_name(name, strlen(name)); + char *scriptname = autoload_name(name, strlen(name)); p = vim_strchr(scriptname, '/'); - plen = (int)strlen(p); - slen = (int)strlen(SOURCING_NAME); + int plen = (int)strlen(p); + int slen = (int)strlen(SOURCING_NAME); if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) { j = OK; } @@ -2753,7 +2734,7 @@ void ex_function(exarg_T *eap) // insert the new function in the function list set_ufunc_name(fp, name); if (overwrite) { - hi = hash_find(&func_hashtab, name); + hashitem_T *hi = hash_find(&func_hashtab, name); hi->hi_key = UF2HIKEY(fp); } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { xfree(fp); @@ -2862,7 +2843,6 @@ char *get_user_func_name(expand_T *xp, int idx) static size_t done; static int changed; static hashitem_T *hi; - ufunc_T *fp; if (idx == 0) { done = 0; @@ -2877,7 +2857,7 @@ char *get_user_func_name(expand_T *xp, int idx) while (HASHITEM_EMPTY(hi)) { hi++; } - fp = HI2UF(hi); + ufunc_T *fp = HI2UF(hi); if ((fp->uf_flags & FC_DICT) || strncmp(fp->uf_name, "", 8) == 0) { @@ -2904,12 +2884,10 @@ char *get_user_func_name(expand_T *xp, int idx) void ex_delfunction(exarg_T *eap) { ufunc_T *fp = NULL; - char *p; - char *name; funcdict_T fudi; - p = eap->arg; - name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); + char *p = eap->arg; + char *name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); xfree(fudi.fd_newkey); if (name == NULL) { if (fudi.fd_dict != NULL && !eap->skip) { @@ -2986,13 +2964,11 @@ void ex_delfunction(exarg_T *eap) /// becomes zero. void func_unref(char *name) { - ufunc_T *fp = NULL; - if (name == NULL || !func_name_refcount(name)) { return; } - fp = find_func(name); + ufunc_T *fp = find_func(name); if (fp == NULL && isdigit((uint8_t)(*name))) { #ifdef EXITFREE if (!entered_free_all_mem) { @@ -3028,12 +3004,10 @@ void func_ptr_unref(ufunc_T *fp) /// Count a reference to a Function. void func_ref(char *name) { - ufunc_T *fp; - if (name == NULL || !func_name_refcount(name)) { return; } - fp = find_func(name); + ufunc_T *fp = find_func(name); if (fp != NULL) { (fp->uf_refcount)++; } else if (isdigit((uint8_t)(*name))) { @@ -3333,10 +3307,6 @@ void invoke_all_defer(void) void ex_call(exarg_T *eap) { char *arg = eap->arg; - char *startarg; - char *name; - char *tofree; - int len; bool failed = false; funcdict_T fudi; partial_T *partial = NULL; @@ -3357,7 +3327,7 @@ void ex_call(exarg_T *eap) return; } - tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial); + char *tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. semsg(_(e_dictkey), fudi.fd_newkey); @@ -3376,13 +3346,13 @@ void ex_call(exarg_T *eap) // If it is the name of a variable of type VAR_FUNC or VAR_PARTIAL use its // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). - len = (int)strlen(tofree); + int len = (int)strlen(tofree); bool found_var = false; - name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false, &found_var); + char *name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false, &found_var); // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. - startarg = skipwhite(arg); + char *startarg = skipwhite(arg); if (*startarg != '(') { semsg(_(e_missingparen), eap->arg); @@ -3435,7 +3405,6 @@ end: /// false when the return gets pending. int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) { - int idx; cstack_T *const cstack = eap->cstack; if (reanimate) { @@ -3447,7 +3416,7 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) // 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); + int idx = cleanup_conditionals(eap->cstack, 0, true); if (idx >= 0) { cstack->cs_pending[idx] = CSTP_RETURN; @@ -3531,7 +3500,6 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->fc_func; char *retval; - garray_T *gap; // growarray with function lines // If breakpoints have been added/deleted need to check for it. if (fcp->fc_dbg_tick != debug_tick) { @@ -3542,7 +3510,7 @@ char *get_func_line(int c, void *cookie, int indent, bool do_concat) func_line_end(cookie); } - gap = &fp->uf_lines; + garray_T *gap = &fp->uf_lines; // growarray with function lines if (((fp->uf_flags & FC_ABORT) && did_emsg && !aborted_in_try()) || fcp->fc_returned) { retval = NULL; @@ -3904,15 +3872,11 @@ bool set_ref_in_call_stack(int copyID) /// Set "copyID" in all functions available by name. bool set_ref_in_functions(int copyID) { - int todo; - hashitem_T *hi = NULL; - ufunc_T *fp; - - todo = (int)func_hashtab.ht_used; - for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { + int todo = (int)func_hashtab.ht_used; + for (hashitem_T *hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { if (!HASHITEM_EMPTY(hi)) { todo--; - fp = HI2UF(hi); + ufunc_T *fp = HI2UF(hi); if (!func_name_refcount(fp->uf_name) && set_ref_in_func(NULL, fp, copyID)) { return true; @@ -3942,7 +3906,6 @@ bool set_ref_in_func_args(int copyID) bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) { ufunc_T *fp = fp_in; - funccall_T *fc; int error = FCERR_NONE; char fname_buf[FLEN_FIXED + 1]; char *tofree = NULL; @@ -3956,7 +3919,7 @@ bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) fp = find_func(fname); } if (fp != NULL) { - for (fc = fp->uf_scoped; fc != NULL; fc = fc->fc_func->uf_scoped) { + for (funccall_T *fc = fp->uf_scoped; fc != NULL; fc = fc->fc_func->uf_scoped) { abort = abort || set_ref_in_funccal(fc, copyID); } } -- cgit From a6e3d93421ba13c407a96fac9cc01fa41ec7ad98 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Thu, 16 Nov 2023 10:59:11 +0100 Subject: refactor: enable formatting for ternaries This requires removing the "Inner expression should be aligned" rule from clint as it prevents essentially any formatting regarding ternary operators. --- src/nvim/eval/funcs.c | 25 +++++++++++++------------ src/nvim/eval/userfunc.c | 6 +++--- 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8ef208f291..c370224476 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2897,8 +2897,8 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int timeout = (int)argvars[0].vval.v_number; typval_T expr = argvars[1]; int interval = argvars[2].v_type == VAR_NUMBER - ? (int)argvars[2].vval.v_number - : 200; // Default. + ? (int)argvars[2].vval.v_number + : 200; // Default. TimeWatcher *tw = xmalloc(sizeof(TimeWatcher)); // Start dummy timer. @@ -5712,11 +5712,11 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl // Find the two bytes before the 0xbf. If p is at buf, or buf + 1, // these may be in the "prev" string. char back1 = p >= buf + 1 ? p[-1] - : prevlen >= 1 ? prev[prevlen - 1] : NUL; + : prevlen >= 1 ? prev[prevlen - 1] : NUL; char back2 = p >= buf + 2 ? p[-2] - : p == buf + 1 && prevlen >= 1 ? prev[prevlen - 1] - : prevlen >= - 2 ? prev[prevlen - 2] : NUL; + : (p == buf + 1 && prevlen >= 1 + ? prev[prevlen - 1] + : prevlen >= 2 ? prev[prevlen - 2] : NUL); if ((uint8_t)back2 == 0xef && (uint8_t)back1 == 0xbb) { char *dest = p - 2; @@ -7914,10 +7914,11 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr tv_list_alloc_ret(rettv, 2); tv_list_append_string(rettv->vval.v_list, word, (ssize_t)len); tv_list_append_string(rettv->vval.v_list, - (attr == HLF_SPB ? "bad" : - attr == HLF_SPR ? "rare" : - attr == HLF_SPL ? "local" : - attr == HLF_SPC ? "caps" : NULL), -1); + (attr == HLF_SPB + ? "bad" : (attr == HLF_SPR + ? "rare" : (attr == HLF_SPL + ? "local" : (attr == HLF_SPC + ? "caps" : NULL)))), -1); } /// "spellsuggest()" function @@ -8410,8 +8411,8 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr cchar = syn_get_sub_char(); if (cchar == NUL && curwin->w_p_cole == 1) { cchar = (curwin->w_p_lcs_chars.conceal == NUL) - ? ' ' - : curwin->w_p_lcs_chars.conceal; + ? ' ' + : curwin->w_p_lcs_chars.conceal; } if (cchar != NUL) { utf_char2bytes(cchar, str); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 822ac4d16a..e15320e391 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2446,7 +2446,7 @@ void ex_function(exarg_T *eap) p = theline; } else if (is_heredoc) { p = skipwhite(theline) == theline - ? theline : theline + strlen(heredoc_trimmed); + ? theline : theline + strlen(heredoc_trimmed); } else { p = theline + strlen(heredoc_trimmed); } @@ -3573,8 +3573,8 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) fp = rettv->vval.v_partial->pt_func; } else { char *fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING - ? rettv->vval.v_string - : rettv->vval.v_partial->pt_name; + ? 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); fp = find_func(fname); -- cgit From 488038580934f301c1528a14548ec0cabd16c2cd Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 10 Nov 2023 14:06:04 +0100 Subject: build: adjust clang-tidy warning exclusion logic Enable all clang-tidy warnings by default instead of disabling them. This ensures that we don't miss useful warnings on each clang-tidy version upgrade. A drawback of this is that it will force us to either fix or adjust the warnings as soon as possible. --- src/nvim/eval/typval.h | 6 +-- src/nvim/eval/typval_encode.c.h | 94 ++++++++++++++++++++--------------------- src/nvim/eval/typval_encode.h | 42 ++++++++---------- 3 files changed, 67 insertions(+), 75 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 751b9646b3..d39425a327 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -339,7 +339,7 @@ extern bool tv_in_free_unref_items; /// @param[in] l List to iterate over. /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. -#define _TV_LIST_ITER_MOD(modifier, l, li, code) \ +#define TV_LIST_ITER_MOD(modifier, l, li, code) \ do { \ modifier list_T *const l_ = (l); \ if (l_ != NULL) { \ @@ -359,7 +359,7 @@ extern bool tv_in_free_unref_items; /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. #define TV_LIST_ITER(l, li, code) \ - _TV_LIST_ITER_MOD( , l, li, code) // NOLINT(whitespace/parens) + TV_LIST_ITER_MOD( , l, li, code) // NOLINT(whitespace/parens) /// Iterate over a list /// @@ -370,7 +370,7 @@ extern bool tv_in_free_unref_items; /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. #define TV_LIST_ITER_CONST(l, li, code) \ - _TV_LIST_ITER_MOD(const, l, li, code) + TV_LIST_ITER_MOD(const, l, li, code) // Below macros are macros to avoid duplicating code for functionally identical // const and non-const function variants. diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index b958239223..2e0b68d486 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -258,7 +258,7 @@ /// macros argument is (not) equal to `&TYPVAL_ENCODE_NODICT_VAR`. const dict_T *const TYPVAL_ENCODE_NODICT_VAR = NULL; -static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( +static inline int TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, void *const val, int *const val_copyID, const MPConvStack *const mpstack, const int copyID, @@ -281,7 +281,7 @@ static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( /// @param[in] objname Object name, used for error reporting. /// /// @return NOTDONE in case of success, what to return in case of failure. -static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( +static inline int TYPVAL_ENCODE_CHECK_SELF_REFERENCE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, void *const val, int *const val_copyID, const MPConvStack *const mpstack, const int copyID, const MPConvStackValType conv_type, const char *const objname) @@ -294,7 +294,7 @@ static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( return NOTDONE; } -static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( +static int TYPVAL_ENCODE_CONVERT_ONE_VALUE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, MPConvStack *const mpstack, MPConvStackVal *const cur_mpsv, typval_T *const tv, const int copyID, @@ -318,7 +318,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( /// @param[in] objname Object name, used for error reporting. /// /// @return OK in case of success, FAIL in case of failure. -static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( +static int TYPVAL_ENCODE_CONVERT_ONE_VALUE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, MPConvStack *const mpstack, MPConvStackVal *const cur_mpsv, typval_T *const tv, const int copyID, const char *const objname) { @@ -346,7 +346,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( partial_T *const pt = tv->vval.v_partial; (void)pt; TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); - _mp_push(*mpstack, ((MPConvStackVal) { + kvi_push(*mpstack, ((MPConvStackVal) { .type = kMPConvPartial, .tv = tv, .saved_copyID = copyID - 1, @@ -365,11 +365,11 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( break; } const int saved_copyID = tv_list_copyid(tv->vval.v_list); - _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, - kMPConvList); + TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_list, lv_copyID, copyID, + kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, tv_list_len(tv->vval.v_list)); assert(saved_copyID != copyID); - _mp_push(*mpstack, ((MPConvStackVal) { + kvi_push(*mpstack, ((MPConvStackVal) { .type = kMPConvList, .tv = tv, .saved_copyID = saved_copyID, @@ -380,7 +380,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( }, }, })); - TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, _mp_last(*mpstack)); + TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, kv_last(*mpstack)); break; } case VAR_BOOL: @@ -518,12 +518,12 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( goto _convert_one_value_regular_dict; } const int saved_copyID = tv_list_copyid(val_di->di_tv.vval.v_list); - _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, - lv_copyID, copyID, - kMPConvList); + TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_di->di_tv.vval.v_list, + lv_copyID, copyID, + kMPConvList); TYPVAL_ENCODE_CONV_LIST_START(tv, tv_list_len(val_di->di_tv.vval.v_list)); assert(saved_copyID != copyID && saved_copyID != copyID - 1); - _mp_push(*mpstack, ((MPConvStackVal) { + kvi_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvList, .saved_copyID = saved_copyID, @@ -552,12 +552,12 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } }); const int saved_copyID = tv_list_copyid(val_di->di_tv.vval.v_list); - _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, - kMPConvPairs); + TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val_list, lv_copyID, copyID, + kMPConvPairs); TYPVAL_ENCODE_CONV_DICT_START(tv, TYPVAL_ENCODE_NODICT_VAR, tv_list_len(val_list)); assert(saved_copyID != copyID && saved_copyID != copyID - 1); - _mp_push(*mpstack, ((MPConvStackVal) { + kvi_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvPairs, .saved_copyID = saved_copyID, @@ -600,12 +600,12 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( } _convert_one_value_regular_dict: {} const int saved_copyID = tv->vval.v_dict->dv_copyID; - _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, copyID, - kMPConvDict); + TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(tv->vval.v_dict, dv_copyID, copyID, + kMPConvDict); TYPVAL_ENCODE_CONV_DICT_START(tv, tv->vval.v_dict, tv->vval.v_dict->dv_hashtab.ht_used); assert(saved_copyID != copyID); - _mp_push(*mpstack, ((MPConvStackVal) { + kvi_push(*mpstack, ((MPConvStackVal) { .tv = tv, .type = kMPConvDict, .saved_copyID = saved_copyID, @@ -619,11 +619,11 @@ _convert_one_value_regular_dict: {} }, })); TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, tv->vval.v_dict, - _mp_last(*mpstack)); + kv_last(*mpstack)); break; } case VAR_UNKNOWN: - internal_error(STR(_TYPVAL_ENCODE_CONVERT_ONE_VALUE) "()"); + internal_error(STR(TYPVAL_ENCODE_CONVERT_ONE_VALUE) "()"); return FAIL; } typval_encode_stop_converting_one_item: @@ -632,7 +632,7 @@ typval_encode_stop_converting_one_item: goto typval_encode_stop_converting_one_item; } -TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( +TYPVAL_ENCODE_SCOPE int TYPVAL_ENCODE_ENCODE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, typval_T *const tv, const char *const objname) REAL_FATTR_NONNULL_ARG(2, 3) REAL_FATTR_WARN_UNUSED_RESULT; @@ -646,29 +646,29 @@ TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( /// @param[in] objname Object name, used for error reporting. /// /// @return OK in case of success, FAIL in case of failure. -TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( +TYPVAL_ENCODE_SCOPE int TYPVAL_ENCODE_ENCODE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, typval_T *const top_tv, const char *const objname) { const int copyID = get_copyID(); MPConvStack mpstack; - _mp_init(mpstack); - if (_TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, - NULL, - top_tv, copyID, objname) + kvi_init(mpstack); + if (TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, + NULL, + top_tv, copyID, objname) == FAIL) { goto encode_vim_to__error_ret; } /// Label common for this and convert_one_value functions, used for escaping /// from macros like TYPVAL_ENCODE_CONV_DICT_START. typval_encode_stop_converting_one_item: - while (_mp_size(mpstack)) { - MPConvStackVal *cur_mpsv = &_mp_last(mpstack); + while (kv_size(mpstack)) { + MPConvStackVal *cur_mpsv = &kv_last(mpstack); typval_T *tv = NULL; switch (cur_mpsv->type) { case kMPConvDict: { if (!cur_mpsv->data.d.todo) { - (void)_mp_pop(mpstack); + (void)kv_pop(mpstack); cur_mpsv->data.d.dict->dv_copyID = cur_mpsv->saved_copyID; TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, *cur_mpsv->data.d.dictp); continue; @@ -692,7 +692,7 @@ typval_encode_stop_converting_one_item: } case kMPConvList: if (cur_mpsv->data.l.li == NULL) { - (void)_mp_pop(mpstack); + (void)kv_pop(mpstack); tv_list_set_copyid(cur_mpsv->data.l.list, cur_mpsv->saved_copyID); TYPVAL_ENCODE_CONV_LIST_END(cur_mpsv->tv); continue; @@ -706,7 +706,7 @@ typval_encode_stop_converting_one_item: break; case kMPConvPairs: { if (cur_mpsv->data.l.li == NULL) { - (void)_mp_pop(mpstack); + (void)kv_pop(mpstack); tv_list_set_copyid(cur_mpsv->data.l.list, cur_mpsv->saved_copyID); TYPVAL_ENCODE_CONV_DICT_END(cur_mpsv->tv, TYPVAL_ENCODE_NODICT_VAR); continue; @@ -719,8 +719,8 @@ typval_encode_stop_converting_one_item: TYPVAL_ENCODE_SPECIAL_DICT_KEY_CHECK(encode_vim_to__error_ret, *TV_LIST_ITEM_TV(tv_list_first(kv_pair))); if ( - _TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, cur_mpsv, - TV_LIST_ITEM_TV(tv_list_first(kv_pair)), copyID, objname) + TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, cur_mpsv, + TV_LIST_ITEM_TV(tv_list_first(kv_pair)), copyID, objname) == FAIL) { goto encode_vim_to__error_ret; } @@ -742,7 +742,7 @@ typval_encode_stop_converting_one_item: cur_mpsv->data.p.stage = kMPConvPartialSelf; if (pt != NULL && pt->pt_argc > 0) { TYPVAL_ENCODE_CONV_LIST_START(NULL, pt->pt_argc); - _mp_push(mpstack, ((MPConvStackVal) { + kvi_push(mpstack, ((MPConvStackVal) { .type = kMPConvPartialList, .tv = NULL, .saved_copyID = copyID - 1, @@ -766,10 +766,10 @@ typval_encode_stop_converting_one_item: continue; } const int saved_copyID = dict->dv_copyID; - const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(TYPVAL_ENCODE_FIRST_ARG_NAME, - dict, &dict->dv_copyID, - &mpstack, copyID, kMPConvDict, - objname); + const int te_csr_ret = TYPVAL_ENCODE_CHECK_SELF_REFERENCE(TYPVAL_ENCODE_FIRST_ARG_NAME, + dict, &dict->dv_copyID, + &mpstack, copyID, kMPConvDict, + objname); if (te_csr_ret != NOTDONE) { if (te_csr_ret == FAIL) { goto encode_vim_to__error_ret; @@ -780,7 +780,7 @@ typval_encode_stop_converting_one_item: TYPVAL_ENCODE_CONV_DICT_START(NULL, pt->pt_dict, dict->dv_hashtab.ht_used); assert(saved_copyID != copyID && saved_copyID != copyID - 1); - _mp_push(mpstack, ((MPConvStackVal) { + kvi_push(mpstack, ((MPConvStackVal) { .type = kMPConvDict, .tv = NULL, .saved_copyID = saved_copyID, @@ -794,7 +794,7 @@ typval_encode_stop_converting_one_item: }, })); TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(NULL, pt->pt_dict, - _mp_last(mpstack)); + kv_last(mpstack)); } else { TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); } @@ -802,14 +802,14 @@ typval_encode_stop_converting_one_item: } case kMPConvPartialEnd: TYPVAL_ENCODE_CONV_FUNC_END(tv); - (void)_mp_pop(mpstack); + (void)kv_pop(mpstack); break; } continue; } case kMPConvPartialList: if (!cur_mpsv->data.a.todo) { - (void)_mp_pop(mpstack); + (void)kv_pop(mpstack); TYPVAL_ENCODE_CONV_LIST_END(NULL); continue; } else if (cur_mpsv->data.a.argv != cur_mpsv->data.a.arg) { @@ -820,16 +820,16 @@ typval_encode_stop_converting_one_item: break; } assert(tv != NULL); - if (_TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, - cur_mpsv, tv, copyID, objname) + if (TYPVAL_ENCODE_CONVERT_ONE_VALUE(TYPVAL_ENCODE_FIRST_ARG_NAME, &mpstack, + cur_mpsv, tv, copyID, objname) == FAIL) { goto encode_vim_to__error_ret; } } - _mp_destroy(mpstack); + kvi_destroy(mpstack); return OK; encode_vim_to__error_ret: - _mp_destroy(mpstack); + kvi_destroy(mpstack); return FAIL; // Prevent “unused label” warnings. goto typval_encode_stop_converting_one_item; diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 743acd8800..a6e0bd4b2b 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -62,14 +62,6 @@ typedef struct { /// Stack used to convert Vimscript values to messagepack. typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack; -// Defines for MPConvStack -#define _mp_size kv_size -#define _mp_init kvi_init -#define _mp_destroy kvi_destroy -#define _mp_push kvi_push -#define _mp_pop kv_pop -#define _mp_last kv_last - static inline size_t tv_strlen(const typval_T *tv) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL; @@ -95,21 +87,21 @@ static inline size_t tv_strlen(const typval_T *const tv) /// copyID (variable) it is set to copyID. /// @param[in] copyID CopyID used by the caller. /// @param conv_type Type of the conversion, @see MPConvStackValType. -#define _TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val, copyID_attr, copyID, \ - conv_type) \ +#define TYPVAL_ENCODE_DO_CHECK_SELF_REFERENCE(val, copyID_attr, copyID, \ + conv_type) \ do { \ - const int te_csr_ret = _TYPVAL_ENCODE_CHECK_SELF_REFERENCE(TYPVAL_ENCODE_FIRST_ARG_NAME, \ - (val), &(val)->copyID_attr, mpstack, \ - copyID, conv_type, objname); \ + const int te_csr_ret = TYPVAL_ENCODE_CHECK_SELF_REFERENCE(TYPVAL_ENCODE_FIRST_ARG_NAME, \ + (val), &(val)->copyID_attr, mpstack, \ + copyID, conv_type, objname); \ if (te_csr_ret != NOTDONE) { \ return te_csr_ret; \ } \ } while (0) -#define _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) \ +#define TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) \ pref##name##suf -#define _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, name, suf) \ - _TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) +#define TYPVAL_ENCODE_FUNC_NAME_INNER(pref, name, suf) \ + TYPVAL_ENCODE_FUNC_NAME_INNER_2(pref, name, suf) /// Construct function name, possibly using macros /// @@ -121,21 +113,21 @@ static inline size_t tv_strlen(const typval_T *const tv) /// @param[in] suf Suffix. /// /// @return Concat: pref + #TYPVAL_ENCODE_NAME + suf. -#define _TYPVAL_ENCODE_FUNC_NAME(pref, suf) \ - _TYPVAL_ENCODE_FUNC_NAME_INNER(pref, TYPVAL_ENCODE_NAME, suf) +#define TYPVAL_ENCODE_FUNC_NAME(pref, suf) \ + TYPVAL_ENCODE_FUNC_NAME_INNER(pref, TYPVAL_ENCODE_NAME, suf) /// Self reference checker function name -#define _TYPVAL_ENCODE_CHECK_SELF_REFERENCE \ - _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _check_self_reference) +#define TYPVAL_ENCODE_CHECK_SELF_REFERENCE \ + TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _check_self_reference) /// Entry point function name -#define _TYPVAL_ENCODE_ENCODE \ - _TYPVAL_ENCODE_FUNC_NAME(encode_vim_to_, ) +#define TYPVAL_ENCODE_ENCODE \ + TYPVAL_ENCODE_FUNC_NAME(encode_vim_to_, ) /// Name of the …convert_one_value function -#define _TYPVAL_ENCODE_CONVERT_ONE_VALUE \ - _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _convert_one_value) +#define TYPVAL_ENCODE_CONVERT_ONE_VALUE \ + TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _convert_one_value) /// Name of the dummy const dict_T *const variable #define TYPVAL_ENCODE_NODICT_VAR \ - _TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var) + TYPVAL_ENCODE_FUNC_NAME(_typval_encode_, _nodict_var) -- cgit From 76635847086344b1b6e7ac9e9a4d9276852be000 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Wed, 15 Nov 2023 13:49:35 +0100 Subject: refactor: remove __clang_analyzer__ macro It is less intrusive to silence the warning with a comment instead of a macro if needed. --- src/nvim/eval/userfunc.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e15320e391..c2c4405c31 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -671,9 +671,7 @@ static void cat_func_name(char *buf, size_t buflen, ufunc_T *fp) /// 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__ STRCPY(v->di_key, name); -#endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; hash_add(&dp->dv_hashtab, v->di_key); v->di_tv.v_type = VAR_NUMBER; @@ -976,10 +974,8 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Set l:self to "selfdict". Use "name" to avoid a warning from // some compiler that checks the destination size. v = (dictitem_T *)&fc->fc_fixvar[fixvar_idx++]; -#ifndef __clang_analyzer__ name = (char *)v->di_key; STRCPY(name, "self"); -#endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; hash_add(&fc->fc_l_vars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_DICT; @@ -1002,10 +998,8 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Use "name" to avoid a warning from some compiler that checks the // destination size. v = (dictitem_T *)&fc->fc_fixvar[fixvar_idx++]; -#ifndef __clang_analyzer__ name = (char *)v->di_key; STRCPY(name, "000"); -#endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; hash_add(&fc->fc_l_avars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_LIST; -- cgit From ee276f8758aea38205e04d839afc69e8537a2642 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 25 Nov 2023 10:50:51 +0800 Subject: vim-patch:8.2.4685: when a swap file is found for a popup there is no dialog (#26207) Problem: When a swap file is found for a popup there is no dialog and the buffer is loaded anyway. Solution: Silently load the buffer read-only. (closes vim/vim#10073) https://github.com/vim/vim/commit/188639d75c363dffaf813e8e2209f7350ad1e871 Co-authored-by: Bram Moolenaar --- src/nvim/eval/buffer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 616c1e06fc..93e4f14980 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -298,7 +298,9 @@ void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) buf_T *buf = get_buf_arg(&argvars[0]); if (buf != NULL) { - swap_exists_action = SEA_NONE; + if (swap_exists_action != SEA_READONLY) { + swap_exists_action = SEA_NONE; + } buf_ensure_loaded(buf); } } -- cgit From a827003e3052c6d9ee7bdb71518182e9bd76317d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 25 Nov 2023 11:32:32 +0100 Subject: build: rework IWYU mapping files Create mapping to most of the C spec and some POSIX specific functions. This is more robust than relying files shipped with IWYU. --- src/nvim/eval/funcs.c | 2 ++ src/nvim/eval/vars.c | 1 + 2 files changed, 3 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c370224476..2e9dce8b5b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8,11 +8,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3fd33720c9..cf02bbe224 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -7,6 +7,7 @@ #include #include #include +#include #include "nvim/ascii.h" #include "nvim/autocmd.h" -- cgit From 6361806aa28edca55ad3316a58bc3e936df9c0eb Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 26 Nov 2023 22:58:52 +0800 Subject: refactor: move garray_T to garray_defs.h (#26227) --- src/nvim/eval/encode.h | 2 +- src/nvim/eval/typval.c | 1 + src/nvim/eval/typval.h | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 1 + src/nvim/eval/userfunc.h | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index a30016e724..15a8277b7c 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -8,7 +8,7 @@ #include "nvim/eval.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" -#include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/vim.h" /// Convert Vimscript value to msgpack string diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 74bde0147d..a0329221d5 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -18,6 +18,7 @@ #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/hashtab.h" diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index d39425a327..b9f2f9b1b0 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -8,7 +8,7 @@ #include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" -#include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/gettext.h" #include "nvim/hashtab.h" #include "nvim/lib/queue.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 996dac20bc..3c539863f8 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -3,7 +3,7 @@ #include #include -#include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/hashtab.h" #include "nvim/lib/queue.h" #include "nvim/pos.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c2c4405c31..cd1ee94298 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -24,6 +24,7 @@ #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 61ada9dd73..4c4d35177e 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -7,7 +7,7 @@ #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" -#include "nvim/garray.h" +#include "nvim/garray_defs.h" #include "nvim/hashtab.h" #include "nvim/pos.h" #include "nvim/types.h" -- cgit From 09541d514dd18bf86f673d3784d406236fcbdad8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Nov 2023 09:51:26 +0800 Subject: build(IWYU): replace public-to-public mappings with pragmas (#26237) --- src/nvim/eval/funcs.c | 1 - src/nvim/eval/typval.h | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 2e9dce8b5b..fca1534dfc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -82,7 +82,6 @@ #include "nvim/message.h" #include "nvim/move.h" #include "nvim/msgpack_rpc/channel.h" -#include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/server.h" #include "nvim/normal.h" #include "nvim/ops.h" diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index b9f2f9b1b0..252dea2b64 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -6,7 +6,7 @@ #include #include -#include "nvim/eval/typval_defs.h" +#include "nvim/eval/typval_defs.h" // IWYU pragma: export #include "nvim/func_attr.h" #include "nvim/garray_defs.h" #include "nvim/gettext.h" -- cgit From 574d25642fc9ca65b396633aeab6e2d32778b642 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Nov 2023 17:21:58 +0800 Subject: refactor: move Arena and ArenaMem to memory_defs.h (#26240) --- src/nvim/eval/buffer.h | 5 +++-- src/nvim/eval/decode.h | 6 +++--- src/nvim/eval/executor.h | 2 +- src/nvim/eval/gc.h | 2 +- src/nvim/eval/typval.c | 2 +- src/nvim/eval/userfunc.c | 2 +- src/nvim/eval/vars.h | 9 +++++++-- 7 files changed, 17 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.h b/src/nvim/eval/buffer.h index fdd146885a..b0fc0f9208 100644 --- a/src/nvim/eval/buffer.h +++ b/src/nvim/eval/buffer.h @@ -1,7 +1,8 @@ #pragma once -#include "nvim/buffer_defs.h" -#include "nvim/eval/typval_defs.h" +#include "nvim/buffer_defs.h" // IWYU pragma: keep +#include "nvim/eval/typval_defs.h" // IWYU pragma: keep +#include "nvim/types.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/buffer.h.generated.h" diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index 3000cd3211..b80786bc32 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -1,9 +1,9 @@ #pragma once -#include -#include +#include // IWYU pragma: keep +#include // IWYU pragma: keep -#include "nvim/eval/typval_defs.h" +#include "nvim/eval/typval_defs.h" // IWYU pragma: keep #include "nvim/types.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval/executor.h b/src/nvim/eval/executor.h index 58edf7216b..d36ce08542 100644 --- a/src/nvim/eval/executor.h +++ b/src/nvim/eval/executor.h @@ -1,6 +1,6 @@ #pragma once -#include "nvim/eval/typval_defs.h" +#include "nvim/eval/typval_defs.h" // IWYU pragma: keep extern char *e_list_index_out_of_range_nr; diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h index ea91952fff..36149ec060 100644 --- a/src/nvim/eval/gc.h +++ b/src/nvim/eval/gc.h @@ -6,5 +6,5 @@ extern dict_T *gc_first_dict; extern list_T *gc_first_list; #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "eval/gc.h.generated.h" +# include "eval/gc.h.generated.h" // IWYU pragma: export #endif diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a0329221d5..e8ed6e5d32 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1,11 +1,11 @@ #include +#include #include #include #include #include #include -#include "lauxlib.h" #include "nvim/ascii.h" #include "nvim/assert.h" #include "nvim/charset.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index cd1ee94298..13d1290fa2 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3,11 +3,11 @@ #include #include #include +#include #include #include #include -#include "lauxlib.h" #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/charset.h" diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 124d73825b..646c6f24e3 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -1,7 +1,12 @@ #pragma once -#include "nvim/ex_cmds_defs.h" -#include "nvim/option_defs.h" +#include // IWYU pragma: keep + +#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep +#include "nvim/garray_defs.h" // IWYU pragma: keep +#include "nvim/hashtab.h" +#include "nvim/option_defs.h" // IWYU pragma: keep +#include "nvim/types.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" -- cgit From 2c16c6a6c42f46e290df5441c37572f296aeb09f Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 27 Nov 2023 10:43:13 +0100 Subject: docs: small fixes (#26154) --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index fca1534dfc..98deb7b32b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7440,7 +7440,7 @@ static void f_setenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char valbuf[NUMBUFLEN]; const char *name = tv_get_string_buf(&argvars[0], namebuf); - // seting an environment variable may be dangerous, e.g. you could + // setting an environment variable may be dangerous, e.g. you could // setenv GCONV_PATH=/tmp and then have iconv() unexpectedly call // a shell command using some shared library: if (check_secure()) { -- cgit From acf525287950277e7b83794184e3df5dcfdecc48 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Nov 2023 18:37:35 +0800 Subject: refactor: remove vim.h from more headers (#26244) --- src/nvim/eval/encode.h | 1 - 1 file changed, 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 15a8277b7c..26a3286f2b 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -9,7 +9,6 @@ #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" #include "nvim/garray_defs.h" -#include "nvim/vim.h" /// Convert Vimscript value to msgpack string /// -- cgit From 38a20dd89f91c45ec8589bf1c50d50732882d38a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 27 Nov 2023 20:58:37 +0800 Subject: build(IWYU): replace most private mappings with pragmas (#26247) --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/window.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 98deb7b32b..53fad45d04 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -90,7 +90,7 @@ #include "nvim/optionstr.h" #include "nvim/os/dl.h" #include "nvim/os/fileio.h" -#include "nvim/os/fs_defs.h" +#include "nvim/os/fs.h" #include "nvim/os/os.h" #include "nvim/os/pty_process.h" #include "nvim/os/shell.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 8502978ac1..fa9b9c41d4 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -11,7 +11,7 @@ #include "nvim/mark.h" #include "nvim/option_defs.h" #include "nvim/option_vars.h" -#include "nvim/os/os.h" +#include "nvim/os/fs.h" #include "nvim/pos.h" #include "nvim/vim.h" #include "nvim/window.h" -- cgit From 40139738eb479d0913ec6ce751ca5adfa50ad8c3 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 26 Nov 2023 21:36:02 +0100 Subject: build: enable IWYU on mac --- src/nvim/eval/typval.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index e8ed6e5d32..936e043b6a 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "nvim/ascii.h" #include "nvim/assert.h" -- cgit From 8b428ca8b79ebb7b36c3e403ff3bcb6924a635a6 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 16:00:21 +0100 Subject: build(IWYU): fix includes for func_attr.h --- src/nvim/eval/buffer.c | 1 + src/nvim/eval/decode.c | 1 + src/nvim/eval/executor.c | 1 + src/nvim/eval/funcs.c | 1 + src/nvim/eval/userfunc.c | 1 + src/nvim/eval/vars.c | 1 + 6 files changed, 6 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 93e4f14980..0a36107596 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -14,6 +14,7 @@ #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" +#include "nvim/func_attr.h" #include "nvim/globals.h" #include "nvim/macros.h" #include "nvim/memline.h" diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index c090d1c9fe..0f896ba531 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -14,6 +14,7 @@ #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/macros.h" diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 62c59db932..79069bbafd 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -5,6 +5,7 @@ #include "nvim/eval/executor.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_defs.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 53fad45d04..6ed992941a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -58,6 +58,7 @@ #include "nvim/ex_getln.h" #include "nvim/file_search.h" #include "nvim/fileio.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/getchar.h" #include "nvim/gettext.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 13d1290fa2..1597f0a524 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -23,6 +23,7 @@ #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/garray_defs.h" #include "nvim/getchar.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index cf02bbe224..9464e71b87 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -25,6 +25,7 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" +#include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" -- cgit From f4aedbae4cb1f206f5b7c6142697b71dd473059b Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 18:39:38 +0100 Subject: build(IWYU): fix includes for undo_defs.h --- src/nvim/eval/buffer.c | 2 +- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval.c | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.h | 2 +- src/nvim/eval/window.c | 2 +- src/nvim/eval/window.h | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 0a36107596..2665fa0503 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -21,7 +21,7 @@ #include "nvim/memory.h" #include "nvim/move.h" #include "nvim/path.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/sign.h" #include "nvim/types.h" #include "nvim/undo.h" diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6ed992941a..56958224ca 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -100,7 +100,7 @@ #include "nvim/path.h" #include "nvim/plines.h" #include "nvim/popupmenu.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/profile.h" #include "nvim/regexp.h" #include "nvim/runtime.h" diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 936e043b6a..036346aed7 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -31,7 +31,7 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/os/input.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/strings.h" #include "nvim/types.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 3c539863f8..98710d4c51 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -6,7 +6,7 @@ #include "nvim/garray_defs.h" #include "nvim/hashtab.h" #include "nvim/lib/queue.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/types.h" /// Type used for Vimscript VAR_NUMBER values diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 4c4d35177e..1c666f72ff 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -9,7 +9,7 @@ #include "nvim/ex_cmds_defs.h" #include "nvim/garray_defs.h" #include "nvim/hashtab.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/types.h" struct funccal_entry; diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index bcc29dfeed..db19d0c25f 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -22,7 +22,7 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/types.h" #include "nvim/vim.h" #include "nvim/window.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index fa9b9c41d4..aa3becf30b 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -12,7 +12,7 @@ #include "nvim/option_defs.h" #include "nvim/option_vars.h" #include "nvim/os/fs.h" -#include "nvim/pos.h" +#include "nvim/pos_defs.h" #include "nvim/vim.h" #include "nvim/window.h" -- cgit From 6c14ae6bfaf51415b555e9a6b85d1d280976358d Mon Sep 17 00:00:00 2001 From: dundargoc Date: Mon, 27 Nov 2023 20:27:32 +0100 Subject: refactor: rename types.h to types_defs.h --- src/nvim/eval/buffer.c | 2 +- src/nvim/eval/buffer.h | 2 +- src/nvim/eval/decode.c | 2 +- src/nvim/eval/decode.h | 2 +- src/nvim/eval/encode.c | 2 +- src/nvim/eval/executor.c | 2 +- src/nvim/eval/funcs.h | 2 +- src/nvim/eval/typval.c | 2 +- src/nvim/eval/typval.h | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 2 +- src/nvim/eval/userfunc.h | 2 +- src/nvim/eval/vars.c | 2 +- src/nvim/eval/vars.h | 2 +- src/nvim/eval/window.c | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 2665fa0503..ce67429d90 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -23,7 +23,7 @@ #include "nvim/path.h" #include "nvim/pos_defs.h" #include "nvim/sign.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/undo.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/buffer.h b/src/nvim/eval/buffer.h index b0fc0f9208..106a499bad 100644 --- a/src/nvim/eval/buffer.h +++ b/src/nvim/eval/buffer.h @@ -2,7 +2,7 @@ #include "nvim/buffer_defs.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" // IWYU pragma: keep -#include "nvim/types.h" +#include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/buffer.h.generated.h" diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 0f896ba531..dde990d693 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -21,7 +21,7 @@ #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" /// Helper structure for container_struct diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index b80786bc32..1c0fd445f1 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -4,7 +4,7 @@ #include // IWYU pragma: keep #include "nvim/eval/typval_defs.h" // IWYU pragma: keep -#include "nvim/types.h" +#include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 709733564e..f8bf53cf0c 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -28,7 +28,7 @@ #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" // For _() const char *const encode_bool_var_names[] = { diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 79069bbafd..70ab5e1aae 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -11,7 +11,7 @@ #include "nvim/globals.h" #include "nvim/message.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 858da53e13..09f709be06 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -7,7 +7,7 @@ #include "nvim/buffer_defs.h" #include "nvim/cmdexpand_defs.h" #include "nvim/eval/typval_defs.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" /// Prototype of C function that implements Vimscript function typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 036346aed7..25be8ecd62 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -33,7 +33,7 @@ #include "nvim/os/input.h" #include "nvim/pos_defs.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" /// struct storing information about current sort diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 252dea2b64..b8466b6943 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -15,7 +15,7 @@ #include "nvim/macros.h" #include "nvim/mbyte_defs.h" #include "nvim/message.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" // In a hashtab item "hi_key" points to "di_key" in a dictitem. // This avoids adding a pointer to the hashtab item. diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 98710d4c51..ea5d70bf19 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -7,7 +7,7 @@ #include "nvim/hashtab.h" #include "nvim/lib/queue.h" #include "nvim/pos_defs.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" /// Type used for Vimscript VAR_NUMBER values typedef int64_t varnumber_T; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1597f0a524..c095dace92 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -45,7 +45,7 @@ #include "nvim/runtime.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/ui.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 1c666f72ff..5ad5db80b7 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -10,7 +10,7 @@ #include "nvim/garray_defs.h" #include "nvim/hashtab.h" #include "nvim/pos_defs.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" struct funccal_entry; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 9464e71b87..75274d41af 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -40,7 +40,7 @@ #include "nvim/os/os.h" #include "nvim/search.h" #include "nvim/strings.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" #include "nvim/window.h" diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 646c6f24e3..849d0c4229 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -6,7 +6,7 @@ #include "nvim/garray_defs.h" // IWYU pragma: keep #include "nvim/hashtab.h" #include "nvim/option_defs.h" // IWYU pragma: keep -#include "nvim/types.h" +#include "nvim/types_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index db19d0c25f..387f524cbb 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -23,7 +23,7 @@ #include "nvim/message.h" #include "nvim/move.h" #include "nvim/pos_defs.h" -#include "nvim/types.h" +#include "nvim/types_defs.h" #include "nvim/vim.h" #include "nvim/window.h" #include "nvim/winfloat.h" -- cgit From 718053b7a97c4e2fbaa6077d3c9f4dc7012c8aad Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Nov 2023 07:47:36 +0800 Subject: refactor: fix runtime_defs.h (#26259) --- src/nvim/eval/buffer.h | 2 +- src/nvim/eval/decode.h | 2 +- src/nvim/eval/funcs.h | 12 +++++++----- src/nvim/eval/vars.h | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.h b/src/nvim/eval/buffer.h index 106a499bad..1d346b99a5 100644 --- a/src/nvim/eval/buffer.h +++ b/src/nvim/eval/buffer.h @@ -2,7 +2,7 @@ #include "nvim/buffer_defs.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" // IWYU pragma: keep -#include "nvim/types_defs.h" +#include "nvim/types_defs.h" // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/buffer.h.generated.h" diff --git a/src/nvim/eval/decode.h b/src/nvim/eval/decode.h index 1c0fd445f1..c0d10a469a 100644 --- a/src/nvim/eval/decode.h +++ b/src/nvim/eval/decode.h @@ -4,7 +4,7 @@ #include // IWYU pragma: keep #include "nvim/eval/typval_defs.h" // IWYU pragma: keep -#include "nvim/types_defs.h" +#include "nvim/types_defs.h" // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/decode.h.generated.h" diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index 09f709be06..0c345dacb4 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -3,18 +3,20 @@ #include #include -#include "nvim/api/private/dispatch.h" -#include "nvim/buffer_defs.h" -#include "nvim/cmdexpand_defs.h" +#include "nvim/buffer_defs.h" // IWYU pragma: keep +#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep #include "nvim/eval/typval_defs.h" +#include "nvim/pos_defs.h" // IWYU pragma: keep #include "nvim/types_defs.h" /// Prototype of C function that implements Vimscript function typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data); /// 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. +enum { + BASE_NONE = 0, ///< Not a method (no base argument). + BASE_LAST = UINT8_MAX, ///< Use the last argument as the method base. +}; /// Structure holding Vimscript function definition typedef struct { diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 849d0c4229..3512152184 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -6,7 +6,7 @@ #include "nvim/garray_defs.h" // IWYU pragma: keep #include "nvim/hashtab.h" #include "nvim/option_defs.h" // IWYU pragma: keep -#include "nvim/types_defs.h" +#include "nvim/types_defs.h" // IWYU pragma: keep #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" -- cgit From 1a8f60c7d2699826b51f23b040b83b1d96a14930 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 28 Nov 2023 10:47:22 +0800 Subject: refactor: move hashtab types to hashtab_defs.h (#26262) --- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 1 - src/nvim/eval/userfunc.h | 9 ++++----- src/nvim/eval/vars.h | 2 +- 4 files changed, 6 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index ea5d70bf19..c6bd11ccdb 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -4,7 +4,7 @@ #include #include "nvim/garray_defs.h" -#include "nvim/hashtab.h" +#include "nvim/hashtab_defs.h" #include "nvim/lib/queue.h" #include "nvim/pos_defs.h" #include "nvim/types_defs.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c095dace92..a859b8a94d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -25,7 +25,6 @@ #include "nvim/ex_getln.h" #include "nvim/func_attr.h" #include "nvim/garray.h" -#include "nvim/garray_defs.h" #include "nvim/getchar.h" #include "nvim/gettext.h" #include "nvim/globals.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 5ad5db80b7..8050caab2b 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -3,14 +3,13 @@ #include #include -#include "nvim/cmdexpand_defs.h" +#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep #include "nvim/eval.h" #include "nvim/eval/typval_defs.h" -#include "nvim/ex_cmds_defs.h" -#include "nvim/garray_defs.h" -#include "nvim/hashtab.h" +#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep +#include "nvim/hashtab_defs.h" // IWYU pragma: keep #include "nvim/pos_defs.h" -#include "nvim/types_defs.h" +#include "nvim/types_defs.h" // IWYU pragma: keep struct funccal_entry; diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 3512152184..6ddf449ff1 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -4,7 +4,7 @@ #include "nvim/ex_cmds_defs.h" // IWYU pragma: keep #include "nvim/garray_defs.h" // IWYU pragma: keep -#include "nvim/hashtab.h" +#include "nvim/hashtab_defs.h" // IWYU pragma: keep #include "nvim/option_defs.h" // IWYU pragma: keep #include "nvim/types_defs.h" // IWYU pragma: keep -- cgit From 79b6ff28ad1204fbb4199b9092f5c578d88cb28e Mon Sep 17 00:00:00 2001 From: dundargoc Date: Tue, 28 Nov 2023 20:31:00 +0100 Subject: refactor: fix headers with IWYU --- src/nvim/eval/buffer.c | 6 +++--- src/nvim/eval/decode.c | 6 +++--- src/nvim/eval/encode.c | 6 +++--- src/nvim/eval/executor.c | 2 +- src/nvim/eval/funcs.c | 8 ++++---- src/nvim/eval/typval.c | 8 ++++---- src/nvim/eval/typval.h | 2 +- src/nvim/eval/userfunc.c | 6 +++--- src/nvim/eval/vars.c | 6 +++--- src/nvim/eval/window.c | 6 +++--- src/nvim/eval/window.h | 2 +- 11 files changed, 29 insertions(+), 29 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index ce67429d90..c60a104381 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -3,7 +3,7 @@ #include #include -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" @@ -16,7 +16,7 @@ #include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" #include "nvim/globals.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/move.h" @@ -25,7 +25,7 @@ #include "nvim/sign.h" #include "nvim/types_defs.h" #include "nvim/undo.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" typedef struct { win_T *cob_curwin_save; diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index dde990d693..03f79fca84 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -7,7 +7,7 @@ #include #include "klib/kvec.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" @@ -17,12 +17,12 @@ #include "nvim/func_attr.h" #include "nvim/garray.h" #include "nvim/gettext.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" /// Helper structure for container_struct typedef struct { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index f8bf53cf0c..8505c30fad 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -14,7 +14,7 @@ #include "klib/kvec.h" #include "msgpack/pack.h" -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" @@ -22,14 +22,14 @@ #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/hashtab.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/math.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/strings.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" // For _() +#include "nvim/vim_defs.h" // For _() const char *const encode_bool_var_names[] = { [kBoolVarTrue] = "v:true", diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 70ab5e1aae..dc23fcdc72 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -12,7 +12,7 @@ #include "nvim/message.h" #include "nvim/strings.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/executor.c.generated.h" // IWYU pragma: export diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 56958224ca..13425b21d1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -24,8 +24,8 @@ #include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" -#include "nvim/ascii.h" -#include "nvim/assert.h" +#include "nvim/ascii_defs.h" +#include "nvim/assert_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" @@ -72,7 +72,7 @@ #include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/main.h" #include "nvim/mark.h" #include "nvim/math.h" @@ -114,7 +114,7 @@ #include "nvim/tag.h" #include "nvim/ui.h" #include "nvim/version.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" /// Describe data to return from find_some_match() diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 25be8ecd62..069cdced34 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -7,8 +7,8 @@ #include #include -#include "nvim/ascii.h" -#include "nvim/assert.h" +#include "nvim/ascii_defs.h" +#include "nvim/assert_defs.h" #include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" @@ -25,7 +25,7 @@ #include "nvim/hashtab.h" #include "nvim/lib/queue.h" #include "nvim/lua/executor.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mbyte.h" #include "nvim/mbyte_defs.h" #include "nvim/memory.h" @@ -34,7 +34,7 @@ #include "nvim/pos_defs.h" #include "nvim/strings.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" /// struct storing information about current sort typedef struct { diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index b8466b6943..58f74a9796 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -12,7 +12,7 @@ #include "nvim/gettext.h" #include "nvim/hashtab.h" #include "nvim/lib/queue.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mbyte_defs.h" #include "nvim/message.h" #include "nvim/types_defs.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a859b8a94d..23b3c4e1b2 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -8,7 +8,7 @@ #include #include -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/charset.h" #include "nvim/cmdexpand_defs.h" @@ -32,7 +32,7 @@ #include "nvim/insexpand.h" #include "nvim/keycodes.h" #include "nvim/lua/executor.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" @@ -46,7 +46,7 @@ #include "nvim/strings.h" #include "nvim/types_defs.h" #include "nvim/ui.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/userfunc.c.generated.h" diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 75274d41af..2968f75f4d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -9,7 +9,7 @@ #include #include -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer_defs.h" #include "nvim/charset.h" @@ -30,7 +30,7 @@ #include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/hashtab.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/ops.h" @@ -41,7 +41,7 @@ #include "nvim/search.h" #include "nvim/strings.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 387f524cbb..e0abbad477 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -6,7 +6,7 @@ #include #include -#include "nvim/ascii.h" +#include "nvim/ascii_defs.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" @@ -18,13 +18,13 @@ #include "nvim/garray.h" #include "nvim/gettext.h" #include "nvim/globals.h" -#include "nvim/macros.h" +#include "nvim/macros_defs.h" #include "nvim/memory.h" #include "nvim/message.h" #include "nvim/move.h" #include "nvim/pos_defs.h" #include "nvim/types_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" #include "nvim/winfloat.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index aa3becf30b..ed879c895a 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -13,7 +13,7 @@ #include "nvim/option_vars.h" #include "nvim/os/fs.h" #include "nvim/pos_defs.h" -#include "nvim/vim.h" +#include "nvim/vim_defs.h" #include "nvim/window.h" /// Structure used by switch_win() to pass values to restore_win() -- cgit