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/typval.c | 80 ++++++++++++++++++++++++++------------------------ 1 file changed, 42 insertions(+), 38 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval/typval.c') 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(); -- 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/typval.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval/typval.c') 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: -- 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/typval.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval/typval.c') 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/typval.c | 42 ++++++++++++++++++++++-------------------- 1 file changed, 22 insertions(+), 20 deletions(-) (limited to 'src/nvim/eval/typval.c') 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/typval.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/nvim/eval/typval.c') 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/typval.c') 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/typval.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c') 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/typval.c') 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/typval.c') 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 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src/nvim/eval/typval.c') 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) { -- 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/typval.c') 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/typval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval/typval.c') 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; -- 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/typval.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'src/nvim/eval/typval.c') 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: -- 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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); -- 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/typval.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval/typval.c') 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); -- 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/typval.c') 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 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/typval.c') 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 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/typval.c') 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/typval.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 -- 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/typval.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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; -- 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/typval.c') 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/typval.c') 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/typval.c') 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/typval.c') 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/typval.c') 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/typval.c') 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/typval.c') 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 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/typval.c') 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/typval.c') 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/typval.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 -- 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/typval.c') 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 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 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'src/nvim/eval/typval.c') 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 -- 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 -------------------------------------------------- 1 file changed, 80 deletions(-) (limited to 'src/nvim/eval/typval.c') 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; } -- 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/typval.c') 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 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'src/nvim/eval/typval.c') 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. -- 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/typval.c') 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/typval.c') 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 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/typval.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src/nvim/eval/typval.c') 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. -- 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/typval.c') 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 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/typval.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 345 +++++++++++++++++++++++++------------------------ 1 file changed, 173 insertions(+), 172 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval/typval.c') 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" -- 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/typval.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/nvim/eval/typval.c') 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 -- 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/typval.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 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/typval.c') 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 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/typval.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 -- 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/typval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval/typval.c') 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; -- 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/typval.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/nvim/eval/typval.c') 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); -- 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 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval/typval.c') 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]); -- 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/typval.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval/typval.c') 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" -- 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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" -- 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/typval.c') 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 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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" -- 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/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval/typval.c') 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 -- 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/typval.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval/typval.c') 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 { -- cgit