From 0ef6aaa3a73d5089bf53e804364950c81784574c Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Wed, 12 Oct 2022 14:53:40 +0100 Subject: refactor: clint (#20600) --- src/nvim/eval/decode.c | 40 ++++++++++++++++------------------------ src/nvim/eval/encode.c | 18 +++++++++--------- 2 files changed, 25 insertions(+), 33 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 94ef419bed..6b7eb2f8f8 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -271,11 +271,9 @@ typval_T decode_string(const char *const s, const size_t len, const TriState has list_T *const list = tv_list_alloc(kListLenMayKnow); tv_list_ref(list); create_special_dict(&tv, kMPString, - ((typval_T){ - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); + (typval_T){ .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list } }); const int elw_ret = encode_list_write((void *)list, s, len); if (s_allocated) { xfree((void *)s); @@ -368,7 +366,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, goto parse_json_string_fail; } } else { - uint8_t p_byte = (uint8_t)*p; + uint8_t p_byte = (uint8_t)(*p); // unescaped = %x20-21 / %x23-5B / %x5D-10FFFF if (p_byte < 0x20) { semsg(_("E474: ASCII control characters cannot be present " @@ -469,7 +467,7 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len, ['r'] = CAR, ['f'] = FF, }; - *str_end++ = escapes[(int)*t]; + *str_end++ = escapes[(int)(*t)]; break; } default: @@ -838,12 +836,10 @@ json_decode_string_cycle_start: .v_lock = VAR_UNLOCKED, .vval = { .v_list = list }, }; - kv_push(container_stack, ((ContainerStackItem) { - .stack_index = kv_size(stack), - .s = p, - .container = tv, - .special_val = NULL, - })); + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), + .s = p, + .container = tv, + .special_val = NULL })); kv_push(stack, OBJ(tv, false, didcomma, didcolon)); break; } @@ -862,12 +858,10 @@ json_decode_string_cycle_start: .vval = { .v_dict = dict }, }; } - kv_push(container_stack, ((ContainerStackItem) { - .stack_index = kv_size(stack), - .s = p, - .container = tv, - .special_val = val_list, - })); + kv_push(container_stack, ((ContainerStackItem) { .stack_index = kv_size(stack), + .s = p, + .container = tv, + .special_val = val_list })); kv_push(stack, OBJ(tv, false, didcomma, didcolon)); break; } @@ -1089,11 +1083,9 @@ msgpack_to_vim_generic_map: {} tv_list_append_number(list, mobj.via.ext.type); list_T *const ext_val_list = tv_list_alloc(kListLenMayKnow); tv_list_append_list(list, ext_val_list); - create_special_dict(rettv, kMPExt, ((typval_T) { - .v_type = VAR_LIST, - .v_lock = VAR_UNLOCKED, - .vval = { .v_list = list }, - })); + create_special_dict(rettv, kMPExt, ((typval_T) { .v_type = VAR_LIST, + .v_lock = VAR_UNLOCKED, + .vval = { .v_list = list } })); if (encode_list_write((void *)ext_val_list, mobj.via.ext.ptr, mobj.via.ext.size) == -1) { return FAIL; diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 27d35ea24f..82c9f04f8f 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -144,16 +144,16 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, case kMPConvPairs: case kMPConvList: { const int idx = (v.data.l.li == tv_list_first(v.data.l.list) - ? 0 - : (v.data.l.li == NULL - ? tv_list_len(v.data.l.list) - 1 - : (int)tv_list_idx_of_item(v.data.l.list, - TV_LIST_ITEM_PREV(v.data.l.list, - v.data.l.li)))); + ? 0 + : (v.data.l.li == NULL + ? tv_list_len(v.data.l.list) - 1 + : (int)tv_list_idx_of_item(v.data.l.list, + TV_LIST_ITEM_PREV(v.data.l.list, + v.data.l.li)))); const listitem_T *const li = (v.data.l.li == NULL - ? tv_list_last(v.data.l.list) - : TV_LIST_ITEM_PREV(v.data.l.list, - v.data.l.li)); + ? tv_list_last(v.data.l.list) + : TV_LIST_ITEM_PREV(v.data.l.list, + v.data.l.li)); if (v.type == kMPConvList || li == NULL || (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST -- cgit From eb123b565e201418dd135d2602dc20eea3cead39 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 13 Oct 2022 15:18:48 +0200 Subject: docs: fix typos (#20509) Co-authored-by: zeertzjq --- src/nvim/eval/userfunc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 4098622a14..ca09c2a6ec 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -23,7 +23,7 @@ #define FC_VIM9 0x400 // defined in vim9 script file #define FC_LUAREF 0x800 // luaref callback -///< Structure used by trans_function_name() +/// Structure used by trans_function_name() typedef struct { dict_T *fd_dict; ///< Dictionary used. char_u *fd_newkey; ///< New key in "dict" in allocated memory. -- cgit From 288208257c8d6b3c8dcce7ee6c7b6c7bb7bafb27 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 8 Oct 2022 15:48:07 +0100 Subject: feat(cscope)!: remove --- src/nvim/eval/funcs.c | 25 ------------------------- 1 file changed, 25 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index a326c44371..861f68993a 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -39,7 +39,6 @@ #include "nvim/getchar.h" #include "nvim/globals.h" #include "nvim/highlight_group.h" -#include "nvim/if_cscope.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/input.h" @@ -1132,29 +1131,6 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = n; } -/// "cscope_connection([{num} , {dbpath} [, {prepend}]])" function -/// -/// Checks the existence of a cscope connection. -static void f_cscope_connection(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int num = 0; - const char *dbpath = NULL; - const char *prepend = NULL; - char buf[NUMBUFLEN]; - - if (argvars[0].v_type != VAR_UNKNOWN - && argvars[1].v_type != VAR_UNKNOWN) { - num = (int)tv_get_number(&argvars[0]); - dbpath = tv_get_string(&argvars[1]); - if (argvars[2].v_type != VAR_UNKNOWN) { - prepend = tv_get_string_buf(&argvars[2], buf); - } - } - - rettv->vval.v_number = cs_connection(num, (char_u *)dbpath, - (char_u *)prepend); -} - /// "ctxget([{index}])" function static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3565,7 +3541,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "cmdwin", "comments", "conceal", - "cscope", "cursorbind", "cursorshape", #ifdef DEBUG -- cgit From 04cdea5f4ac49fa62cc4091a5c26791b80b4cc4c Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 41 +++++++++++++++++++---------------------- src/nvim/eval/userfunc.c | 35 +++++++++++++++++------------------ 2 files changed, 36 insertions(+), 40 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 861f68993a..5073ab8f1b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -577,7 +577,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) return NULL; } - char_u *name = (char_u *)tv->vval.v_string; + char *name = tv->vval.v_string; if (name == NULL || *name == NUL) { return curbuf; @@ -592,7 +592,7 @@ buf_T *tv_get_buf(typval_T *tv, int curtab_only) char *save_cpo = p_cpo; p_cpo = empty_option; - buf_T *buf = buflist_findnr(buflist_findpat((char *)name, (char *)name + STRLEN(name), + buf_T *buf = buflist_findnr(buflist_findpat(name, name + strlen(name), true, false, curtab_only)); p_magic = save_magic; @@ -1056,12 +1056,12 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (argvars[0].v_type == VAR_STRING) { - const char_u *expr = (char_u *)tv_get_string_chk(&argvars[1]); + const char *expr = tv_get_string_chk(&argvars[1]); const char_u *p = (char_u *)argvars[0].vval.v_string; if (!error && expr != NULL && *expr != NUL && p != NULL) { if (ic) { - const size_t len = STRLEN(expr); + const size_t len = strlen(expr); while (*p != NUL) { if (mb_strnicmp((char *)p, (char *)expr, len) == 0) { @@ -1075,7 +1075,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char_u *next; while ((next = (char_u *)strstr((char *)p, (char *)expr)) != NULL) { n++; - p = next + STRLEN(expr); + p = next + strlen(expr); } } } @@ -4855,9 +4855,9 @@ static void f_map(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void find_some_match(typval_T *const argvars, typval_T *const rettv, const SomeMatchType type) { - char_u *str = NULL; + char *str = NULL; long len = 0; - char_u *expr = NULL; + char *expr = NULL; regmatch_T regmatch; long start = 0; long nth = 1; @@ -4865,7 +4865,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, bool match = false; list_T *l = NULL; long idx = 0; - char_u *tofree = NULL; + char *tofree = NULL; // Make 'cpoptions' empty, the 'l' flag should not be used here. char *save_cpo = p_cpo; @@ -4902,8 +4902,8 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } li = tv_list_first(l); } else { - expr = str = (char_u *)tv_get_string(&argvars[0]); - len = (long)STRLEN(str); + expr = str = (char *)tv_get_string(&argvars[0]); + len = (long)strlen(str); } char patbuf[NUMBUFLEN]; @@ -4962,14 +4962,13 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, break; } xfree(tofree); - tofree = expr = str = (char_u *)encode_tv2echo(TV_LIST_ITEM_TV(li), - NULL); + tofree = expr = str = encode_tv2echo(TV_LIST_ITEM_TV(li), NULL); if (str == NULL) { break; } } - match = vim_regexec_nl(®match, str, startcol); + match = vim_regexec_nl(®match, (char_u *)str, startcol); if (match && --nth <= 0) { break; @@ -4983,9 +4982,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, li = TV_LIST_ITEM_NEXT(l, li); idx++; } else { - startcol = (colnr_T)((char_u *)regmatch.startp[0] + startcol = (colnr_T)(regmatch.startp[0] + utfc_ptr2len(regmatch.startp[0]) - str); - if (startcol > (colnr_T)len || str + startcol <= (char_u *)regmatch.startp[0]) { + if (startcol > (colnr_T)len || str + startcol <= regmatch.startp[0]) { match = false; break; } @@ -5003,9 +5002,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, xfree(TV_LIST_ITEM_TV(li1)->vval.v_string); const size_t rd = (size_t)(regmatch.endp[0] - regmatch.startp[0]); - TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz((const char *)regmatch.startp[0], rd); - TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)((char_u *)regmatch.startp[0] - expr); - TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - (char *)expr); + TV_LIST_ITEM_TV(li1)->vval.v_string = xmemdupz(regmatch.startp[0], rd); + TV_LIST_ITEM_TV(li3)->vval.v_number = (varnumber_T)(regmatch.startp[0] - expr); + TV_LIST_ITEM_TV(li4)->vval.v_number = (varnumber_T)(regmatch.endp[0] - expr); if (l != NULL) { TV_LIST_ITEM_TV(li2)->vval.v_number = (varnumber_T)idx; } @@ -5039,11 +5038,9 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, rettv->vval.v_number = idx; } else { if (type == kSomeMatch) { - rettv->vval.v_number = - (varnumber_T)((char_u *)regmatch.startp[0] - str); + rettv->vval.v_number = (varnumber_T)(regmatch.startp[0] - str); } else { - rettv->vval.v_number = - (varnumber_T)(regmatch.endp[0] - (char *)str); + rettv->vval.v_number = (varnumber_T)(regmatch.endp[0] - str); } rettv->vval.v_number += (varnumber_T)(str - expr); } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index b0a56c4440..fdeb52053c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -206,12 +206,12 @@ char_u *get_lambda_name(void) return name; } -static void set_ufunc_name(ufunc_T *fp, char_u *name) +static void set_ufunc_name(ufunc_T *fp, char *name) { STRCPY(fp->uf_name, name); - if (name[0] == K_SPECIAL) { - fp->uf_name_exp = xmalloc(STRLEN(name) + 3); + if ((uint8_t)name[0] == K_SPECIAL) { + fp->uf_name_exp = xmalloc(strlen(name) + 3); STRCPY(fp->uf_name_exp, ""); STRCAT(fp->uf_name_exp, fp->uf_name + 3); } @@ -275,9 +275,9 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) char_u *p; garray_T newlines; - char_u *name = get_lambda_name(); + char *name = (char *)get_lambda_name(); - fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); + fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); pt = xcalloc(1, sizeof(partial_T)); ga_init(&newlines, (int)sizeof(char_u *), 1); @@ -378,9 +378,9 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, if (partialp != NULL) { *partialp = pt; } - char_u *s = (char_u *)partial_name(pt); - *lenp = (int)STRLEN(s); - return s; + char *s = partial_name(pt); + *lenp = (int)strlen(s); + return (char_u *)s; } return (char_u *)name; @@ -2476,8 +2476,8 @@ void ex_function(exarg_T *eap) if (SOURCING_NAME != NULL) { scriptname = (char_u *)autoload_name((const char *)name, strlen(name)); p = vim_strchr((char *)scriptname, '/'); - plen = (int)STRLEN(p); - slen = (int)STRLEN(SOURCING_NAME); + plen = (int)strlen(p); + slen = (int)strlen(SOURCING_NAME); if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) { j = OK; } @@ -2513,7 +2513,7 @@ void ex_function(exarg_T *eap) } // insert the new function in the function list - set_ufunc_name(fp, (char_u *)name); + set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); hi->hi_key = UF2HIKEY(fp); @@ -2887,7 +2887,7 @@ void ex_call(exarg_T *eap) char_u *arg = (char_u *)eap->arg; char_u *startarg; char_u *name; - char_u *tofree; + char *tofree; int len; typval_T rettv; linenr_T lnum; @@ -2908,7 +2908,7 @@ void ex_call(exarg_T *eap) return; } - tofree = trans_function_name((char **)&arg, false, TFN_INT, &fudi, &partial); + tofree = (char *)trans_function_name((char **)&arg, false, TFN_INT, &fudi, &partial); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. semsg(_(e_dictkey), fudi.fd_newkey); @@ -2927,9 +2927,8 @@ void ex_call(exarg_T *eap) // If it is the name of a variable of type VAR_FUNC or VAR_PARTIAL use its // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). - len = (int)STRLEN(tofree); - name = deref_func_name((const char *)tofree, &len, - partial != NULL ? NULL : &partial, false); + len = (int)strlen(tofree); + name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. @@ -3556,8 +3555,8 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) /// Registers a luaref as a lambda. char_u *register_luafunc(LuaRef ref) { - char_u *name = get_lambda_name(); - ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + STRLEN(name) + 1); + char *name = (char *)get_lambda_name(); + ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); fp->uf_refcount = 1; fp->uf_varargs = true; -- cgit From 784e498c4a9c1f03266ced5ec3f55c3a6c94b80d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 21 Oct 2022 14:47:44 +0200 Subject: refactor: clang-tidy fixes to silence clangd warning (#20683) * refactor: readability-uppercase-literal-suffix * refactor: readability-named-parameter * refactor: bugprone-suspicious-string-compare * refactor: google-readability-casting * refactor: readability-redundant-control-flow * refactor: bugprone-too-small-loop-variable * refactor: readability-non-const-parameter * refactor: readability-avoid-const-params-in-decls * refactor: google-readability-todo * refactor: readability-inconsistent-declaration-parameter-name * refactor: bugprone-suspicious-missing-comma * refactor: remove noisy or slow warnings --- src/nvim/eval/encode.h | 12 ++++++------ src/nvim/eval/funcs.c | 12 ++++++------ src/nvim/eval/typval.c | 2 +- src/nvim/eval/typval.h | 40 ++++++++++++++++++++-------------------- src/nvim/eval/typval_encode.h | 2 +- src/nvim/eval/userfunc.c | 2 +- 6 files changed, 35 insertions(+), 35 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 8755ff48ac..9d311fe356 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -15,9 +15,9 @@ /// @param[in] objname Object name, used for error message. /// /// @return OK in case of success, FAIL otherwise. -int encode_vim_to_msgpack(msgpack_packer *const packer, - typval_T *const tv, - const char *const objname); +int encode_vim_to_msgpack(msgpack_packer *packer, + typval_T *tv, + const char *objname); /// Convert VimL value to :echo output /// @@ -26,9 +26,9 @@ int encode_vim_to_msgpack(msgpack_packer *const packer, /// @param[in] objname Object name, used for error message. /// /// @return OK in case of success, FAIL otherwise. -int encode_vim_to_echo(garray_T *const packer, - typval_T *const tv, - const char *const objname); +int encode_vim_to_echo(garray_T *packer, + typval_T *tv, + const char *objname); /// Structure defining state for read_from_list() typedef struct { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5073ab8f1b..f66ff7b5bb 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5866,8 +5866,8 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) char buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1 int io_size = sizeof(buf); char *prev = NULL; // previously read bytes, if any - long prevlen = 0; // length of data in prev - long prevsize = 0; // size of prev buffer + ptrdiff_t prevlen = 0; // length of data in prev + ptrdiff_t prevsize = 0; // size of prev buffer long maxline = MAXLNUM; if (argvars[1].v_type != VAR_UNKNOWN) { @@ -6022,17 +6022,17 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // small, to avoid repeatedly 'allocing' large and // 'reallocing' small. if (prevsize == 0) { - prevsize = (long)(p - start); + prevsize = p - start; } else { - long grow50pc = (prevsize * 3) / 2; - long growmin = (long)((p - start) * 2 + prevlen); + ptrdiff_t grow50pc = (prevsize * 3) / 2; + ptrdiff_t growmin = (p - start) * 2 + prevlen; prevsize = grow50pc > growmin ? grow50pc : growmin; } prev = xrealloc(prev, (size_t)prevsize); } // Add the line part to end of "prev". memmove(prev + prevlen, start, (size_t)(p - start)); - prevlen += (long)(p - start); + prevlen += p - start; } } // while diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a0b06aaaf4..6bb390d793 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1361,7 +1361,7 @@ void tv_list_reverse(list_T *const l) /// 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, bool *errp) + const ListSorter item_compare_func, const bool *errp) FUNC_ATTR_NONNULL_ARG(3, 4) { const int len = tv_list_len(l); diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 0a4adc1f53..e4cd76e8a6 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -90,7 +90,7 @@ static inline void list_log(const list_T *const l, const listitem_T *const li1, #define TV_DICT_HI2DI(hi) \ ((dictitem_T *)((hi)->hi_key - offsetof(dictitem_T, di_key))) -static inline void tv_list_ref(list_T *const l) +static inline void tv_list_ref(list_T *l) REAL_FATTR_ALWAYS_INLINE; /// Increase reference count for a given list @@ -106,7 +106,7 @@ static inline void tv_list_ref(list_T *const l) l->lv_refcount++; } -static inline void tv_list_set_ret(typval_T *const tv, list_T *const l) +static inline void tv_list_set_ret(typval_T *tv, list_T *l) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1); /// Set a list as the return value. Increments the reference count. @@ -120,7 +120,7 @@ static inline void tv_list_set_ret(typval_T *const tv, list_T *const l) tv_list_ref(l); } -static inline VarLockStatus tv_list_locked(const list_T *const l) +static inline VarLockStatus tv_list_locked(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get list lock status @@ -163,7 +163,7 @@ static inline void tv_list_set_copyid(list_T *const l, const int copyid) l->lv_copyID = copyid; } -static inline int tv_list_len(const list_T *const l) +static inline int tv_list_len(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get the number of items in a list @@ -178,7 +178,7 @@ static inline int tv_list_len(const list_T *const l) return l->lv_len; } -static inline int tv_list_copyid(const list_T *const l) +static inline int tv_list_copyid(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL; /// Get list copyID @@ -191,7 +191,7 @@ static inline int tv_list_copyid(const list_T *const l) return l->lv_copyID; } -static inline list_T *tv_list_latest_copy(const list_T *const l) +static inline list_T *tv_list_latest_copy(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL; /// Get latest list copy @@ -206,7 +206,7 @@ static inline list_T *tv_list_latest_copy(const list_T *const l) return l->lv_copylist; } -static inline int tv_list_uidx(const list_T *const l, int n) +static inline int tv_list_uidx(const list_T *l, int n) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Normalize index: that is, return either -1 or non-negative index @@ -229,7 +229,7 @@ static inline int tv_list_uidx(const list_T *const l, int n) return n; } -static inline bool tv_list_has_watchers(const list_T *const l) +static inline bool tv_list_has_watchers(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Check whether list has watchers @@ -244,7 +244,7 @@ static inline bool tv_list_has_watchers(const list_T *const l) return l && l->lv_watch; } -static inline listitem_T *tv_list_first(const list_T *const l) +static inline listitem_T *tv_list_first(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get first list item @@ -262,7 +262,7 @@ static inline listitem_T *tv_list_first(const list_T *const l) return l->lv_first; } -static inline listitem_T *tv_list_last(const list_T *const l) +static inline listitem_T *tv_list_last(const list_T *l) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get last list item @@ -280,7 +280,7 @@ static inline listitem_T *tv_list_last(const list_T *const l) return l->lv_last; } -static inline void tv_dict_set_ret(typval_T *const tv, dict_T *const d) +static inline void tv_dict_set_ret(typval_T *tv, dict_T *d) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1); /// Set a dictionary as the return value @@ -296,7 +296,7 @@ static inline void tv_dict_set_ret(typval_T *const tv, dict_T *const d) } } -static inline long tv_dict_len(const dict_T *const d) +static inline long tv_dict_len(const dict_T *d) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get the number of items in a Dictionary @@ -310,7 +310,7 @@ static inline long tv_dict_len(const dict_T *const d) return (long)d->dv_hashtab.ht_used; } -static inline bool tv_dict_is_watched(const dict_T *const d) +static inline bool tv_dict_is_watched(const dict_T *d) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Check if dictionary is watched @@ -323,7 +323,7 @@ static inline bool tv_dict_is_watched(const dict_T *const d) return d && !QUEUE_EMPTY(&d->watchers); } -static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b) +static inline void tv_blob_set_ret(typval_T *tv, blob_T *b) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ARG(1); /// Set a blob as the return value. @@ -341,7 +341,7 @@ static inline void tv_blob_set_ret(typval_T *const tv, blob_T *const b) } } -static inline int tv_blob_len(const blob_T *const b) +static inline int tv_blob_len(const blob_T *b) REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT; /// Get the length of the data in the blob, in bytes. @@ -355,7 +355,7 @@ static inline int tv_blob_len(const blob_T *const b) return b->bv_ga.ga_len; } -static inline char_u tv_blob_get(const blob_T *const b, int idx) +static inline char_u tv_blob_get(const blob_T *b, int idx) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Get the byte at index `idx` in the blob. @@ -369,7 +369,7 @@ static inline char_u tv_blob_get(const blob_T *const b, int idx) return ((char_u *)b->bv_ga.ga_data)[idx]; } -static inline void tv_blob_set(blob_T *const b, int idx, char_u c) +static inline void tv_blob_set(blob_T *b, int idx, char_u c) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL; /// Store the byte `c` at index `idx` in the blob. @@ -488,8 +488,8 @@ extern bool tv_in_free_unref_items; } \ }) -static inline bool tv_get_float_chk(const typval_T *const tv, - float_T *const ret_f) +static inline bool tv_get_float_chk(const typval_T *tv, + float_T *ret_f) REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Get the float value @@ -527,7 +527,7 @@ static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q) return QUEUE_DATA(q, DictWatcher, node); } -static inline bool tv_is_func(const typval_T tv) +static inline bool tv_is_func(typval_T tv) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST; /// Check whether given typval_T contains a function diff --git a/src/nvim/eval/typval_encode.h b/src/nvim/eval/typval_encode.h index 33e19c531c..2f19144da3 100644 --- a/src/nvim/eval/typval_encode.h +++ b/src/nvim/eval/typval_encode.h @@ -71,7 +71,7 @@ typedef kvec_withinit_t(MPConvStackVal, 8) MPConvStack; #define _mp_pop kv_pop #define _mp_last kv_last -static inline size_t tv_strlen(const typval_T *const tv) +static inline size_t tv_strlen(const typval_T *tv) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index fdeb52053c..f6530d0e92 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1193,7 +1193,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett /// For the first we only count the name stored in func_hashtab as a reference, /// using function() does not count as a reference, because the function is /// looked up by name. -static bool func_name_refcount(char_u *name) +static bool func_name_refcount(const char_u *name) { return isdigit(*name) || *name == '<'; } -- cgit From 6ff245732a5a8ab821598a38fb0c5805e6bd3779 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 14 Oct 2022 17:04:28 +0200 Subject: refactor(uncrustify): improved formatting rules --- src/nvim/eval/typval.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index e4cd76e8a6..fcc933c967 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -43,10 +43,8 @@ static inline ListLog *list_log_new(const size_t size) return ret; } -static inline void list_log(const list_T *const l, - const listitem_T *const li1, - const listitem_T *const li2, - const char *const action) +static inline void list_log(const list_T *const l, const listitem_T *const li1, + const listitem_T *const li2, const char *const action) REAL_FATTR_ALWAYS_INLINE; /// Add new entry to log @@ -488,8 +486,7 @@ extern bool tv_in_free_unref_items; } \ }) -static inline bool tv_get_float_chk(const typval_T *tv, - float_T *ret_f) +static inline bool tv_get_float_chk(const typval_T *tv, float_T *ret_f) REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Get the float value -- cgit From abf758a2977c4e6cab4dfa217f56da853d85851c Mon Sep 17 00:00:00 2001 From: dundargoc Date: Fri, 21 Oct 2022 16:43:03 +0200 Subject: refactor: fix uncrustify lint errors --- src/nvim/eval/encode.h | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 9d311fe356..c0c98e0990 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -15,9 +15,7 @@ /// @param[in] objname Object name, used for error message. /// /// @return OK in case of success, FAIL otherwise. -int encode_vim_to_msgpack(msgpack_packer *packer, - typval_T *tv, - const char *objname); +int encode_vim_to_msgpack(msgpack_packer *packer, typval_T *tv, const char *objname); /// Convert VimL value to :echo output /// @@ -26,9 +24,7 @@ int encode_vim_to_msgpack(msgpack_packer *packer, /// @param[in] objname Object name, used for error message. /// /// @return OK in case of success, FAIL otherwise. -int encode_vim_to_echo(garray_T *packer, - typval_T *tv, - const char *objname); +int encode_vim_to_echo(garray_T *packer, typval_T *tv, const char *objname); /// Structure defining state for read_from_list() typedef struct { -- cgit From c5f280c522d77b14e3f138797b6628f50fa80c14 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 24 Oct 2022 13:48:51 +0800 Subject: vim-patch:8.2.0908: crash when changing the function table while listing it Problem: Crash when changing the function table while listing it. Solution: Bail out when the function table changes. (closes vim/vim#6209) https://github.com/vim/vim/commit/3fffa97159a427067b60c80ed4645e168cc5c4bd Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 58 ++++++++++++++++++++++++++---------------------- 1 file changed, 32 insertions(+), 26 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index f6530d0e92..4a62b4bf8d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1877,6 +1877,36 @@ theend: #define MAX_FUNC_NESTING 50 +/// List functions. +/// +/// @param regmatch When NULL, all of them. +/// Otherwise functions matching "regmatch". +static void list_functions(regmatch_T *regmatch) +{ + const size_t used = func_hashtab.ht_used; + size_t todo = used; + const hashitem_T *const ht_array = func_hashtab.ht_array; + + for (const hashitem_T *hi = ht_array; todo > 0 && !got_int; hi++) { + if (!HASHITEM_EMPTY(hi)) { + ufunc_T *fp = HI2UF(hi); + todo--; + if ((fp->uf_flags & FC_DEAD) == 0 + && (regmatch == NULL + ? (!message_filtered((char *)fp->uf_name) + && !func_name_refcount(fp->uf_name)) + : (!isdigit(*fp->uf_name) + && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { + list_func_head(fp, false, false); + if (used != func_hashtab.ht_used || ht_array != func_hashtab.ht_array) { + emsg(_("E454: function list was modified")); + return; + } + } + } + } +} + /// ":function" void ex_function(exarg_T *eap) { @@ -1903,7 +1933,6 @@ void ex_function(exarg_T *eap) static int func_nr = 0; // number for nameless function int paren; hashtab_T *ht; - int todo; hashitem_T *hi; linenr_T sourcing_lnum_off; linenr_T sourcing_lnum_top; @@ -1916,19 +1945,7 @@ void ex_function(exarg_T *eap) // ":function" without argument: list functions. if (ends_excmd(*eap->arg)) { if (!eap->skip) { - todo = (int)func_hashtab.ht_used; - for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { - if (!HASHITEM_EMPTY(hi)) { - todo--; - fp = HI2UF(hi); - if (message_filtered((char *)fp->uf_name)) { - continue; - } - if (!func_name_refcount(fp->uf_name)) { - list_func_head(fp, false, false); - } - } - } + list_functions(NULL); } eap->nextcmd = check_nextcmd(eap->arg); return; @@ -1946,18 +1963,7 @@ void ex_function(exarg_T *eap) *p = c; if (regmatch.regprog != NULL) { regmatch.rm_ic = p_ic; - - todo = (int)func_hashtab.ht_used; - for (hi = func_hashtab.ht_array; todo > 0 && !got_int; hi++) { - if (!HASHITEM_EMPTY(hi)) { - todo--; - fp = HI2UF(hi); - if (!isdigit(*fp->uf_name) - && vim_regexec(®match, (char *)fp->uf_name, 0)) { - list_func_head(fp, false, false); - } - } - } + list_functions(®match); vim_regfree(regmatch.regprog); } } -- cgit From cfccae95844db21aad773c9a8f8b636f53d6c8c4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 26 Oct 2022 19:04:38 +0800 Subject: vim-patch:8.2.0610: some tests are still old style Problem: Some tests are still old style. Solution: Convert to new style tests. (Yegappan Lakshmanan, closes vim/vim#5957) https://github.com/vim/vim/commit/08f4157c5cabc55bcb22f04dd7c717aba40caa34 Fix missing error message when sort() compare function fails. Cherry-pick a line in test_utf8.vim from patch 8.2.0448. Cherry-pick builtin_function() change from patch 8.2.0595. --- src/nvim/eval/typval.c | 4 +++- src/nvim/eval/userfunc.c | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 6bb390d793..a6a8c16a3b 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1094,7 +1094,9 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero) tv_clear(&argv[1]); if (res == FAIL) { + // XXX: ITEM_COMPARE_FAIL is unused res = ITEM_COMPARE_FAIL; + sortinfo->item_compare_func_err = true; } else { res = (int)tv_get_number_chk(&rettv, &sortinfo->item_compare_func_err); if (res > 0) { @@ -1257,7 +1259,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } else { li = TV_LIST_ITEM_NEXT(l, li); } - if (info.item_compare_func_err) { // -V547 + if (info.item_compare_func_err) { emsg(_("E882: Uniq compare function failed")); break; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4a62b4bf8d..7440044e52 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1335,10 +1335,10 @@ void free_all_functions(void) /// @param[in] len length of "name", or -1 for NUL terminated. /// /// @return true if "name" looks like a builtin function name: starts with a -/// lower case letter and doesn't contain AUTOLOAD_CHAR. +/// lower case letter and doesn't contain AUTOLOAD_CHAR or ':'. static bool builtin_function(const char *name, int len) { - if (!ASCII_ISLOWER(name[0])) { + if (!ASCII_ISLOWER(name[0]) || name[1] == ':') { return false; } -- cgit From ef363ed37cdf5c460cca840aebc825011e0294ee Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 26 Oct 2022 19:53:54 +0800 Subject: vim-patch:8.2.0619: null dict is not handled like an empty dict Problem: Null dict is not handled like an empty dict. Solution: Fix the code and add tests. (Yegappan Lakshmanan, closes vim/vim#5968) https://github.com/vim/vim/commit/ea04a6e8baff2f27da7cdd54bf70a5525994f76d Nvim doesn't support modifying NULL list, so comment out a line. --- src/nvim/eval/typval.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index a6a8c16a3b..3b513bfafb 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2490,10 +2490,14 @@ bool tv_dict_equal(dict_T *const d1, dict_T *const d2, const bool ic, const bool if (d1 == d2) { return true; } - if (d1 == NULL || d2 == NULL) { + if (tv_dict_len(d1) != tv_dict_len(d2)) { return false; } - if (tv_dict_len(d1) != tv_dict_len(d2)) { + if (tv_dict_len(d1) == 0) { + // empty and NULL dicts are considered equal + return true; + } + if (d1 == NULL || d2 == NULL) { return false; } -- cgit From 1f438b23381cf79e9c6fbdfa69dfeff9ecbce3e6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Oct 2022 08:30:27 +0800 Subject: vim-patch:8.2.2726: confusing error message with white space before comma Problem: Confusing error message with white space before comma in the arguments of a function declaration. Solution: Give a specific error message. (closes vim/vim#2235) https://github.com/vim/vim/commit/86cdb8a4bd1abff40b5f80c3c4149b33cbaab990 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 7440044e52..2a7ad792df 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -48,6 +48,8 @@ static char *e_funcexts = N_("E122: Function %s already exists, add ! to replace static char *e_funcdict = N_("E717: Dictionary entry already exists"); static char *e_funcref = N_("E718: Funcref required"); static char *e_nofunc = N_("E130: Unknown function: %s"); +static char e_no_white_space_allowed_before_str_str[] + = N_("E1068: No white space allowed before '%s': %s"); void func_init(void) { @@ -149,6 +151,15 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int emsg(_("E989: Non-default argument follows default argument")); mustend = true; } + + if (ascii_iswhite(*p) && *skipwhite(p) == ',') { + // Be tolerant when skipping + if (!skip) { + semsg(_(e_no_white_space_allowed_before_str_str), ",", p); + goto err_ret; + } + p = skipwhite(p); + } if (*p == ',') { p++; } else { -- cgit From acbfbbb649c39694c3a6a92160984db2fcb6f3ec Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Oct 2022 09:44:13 +0800 Subject: vim-patch:8.2.3408: can delete a numbered function Problem: Can delete a numbered function. (Naohiro Ono) Solution: Disallow deleting a numbered function. (closes vim/vim#8760) https://github.com/vim/vim/commit/ddfc05100a29263a682dd96bb924dfde4354a654 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 2a7ad792df..147beb78ad 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2704,6 +2704,13 @@ void ex_delfunction(exarg_T *eap) *p = NUL; } + if (isdigit(*name) && fudi.fd_dict == NULL) { + if (!eap->skip) { + semsg(_(e_invarg2), eap->arg); + } + xfree(name); + return; + } if (!eap->skip) { fp = find_func(name); } -- cgit From b793395019333127e085997b7ced4ea02053697e Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Oct 2022 11:43:10 +0800 Subject: vim-patch:8.2.4070: using uninitialized memory when reading empty file MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Using uninitialized memory when reading empty file. Solution: Check for empty file before checking for NL. (Dominique Pellé, closes vim/vim#9511) https://github.com/vim/vim/commit/f5d639a8af719eb8ecb141b5c0890627e4d83134 Co-authored-by: Dominique Pelle --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index f66ff7b5bb..b475ff1096 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5921,7 +5921,7 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) for (p = buf, start = buf; p < buf + readlen || (readlen <= 0 && (prevlen > 0 || binary)); p++) { - if (*p == '\n' || readlen <= 0) { + if (readlen <= 0 || *p == '\n') { char *s = NULL; size_t len = (size_t)(p - start); -- cgit From 25cf4f2fc712530a65dc3b533508c36d0439b728 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Oct 2022 13:04:08 +0800 Subject: vim-patch:8.2.2653: build failure Problem: Build failure. Solution: Add missing changes. https://github.com/vim/vim/commit/3a0f092ac0dbdd4ce71f9c4abe020e89f13df36c Omit E1176: only applicable to Vim9 script. Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 3b513bfafb..fb601c4307 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -43,7 +43,7 @@ static char e_string_required_for_argument_nr[] = N_("E1174: String required for argument %d"); static char e_non_empty_string_required_for_argument_nr[] - = N_("E1142: Non-empty string required for argument %d"); + = N_("E1175: Non-empty string required for argument %d"); static char e_number_required_for_argument_nr[] = N_("E1210: Number required for argument %d"); -- cgit From 5568267ccb94924b9dcf7bfa5d52da0f16d161e4 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 27 Oct 2022 18:08:06 +0800 Subject: vim-patch:8.2.1544: cannot translate messages in a Vim script Problem: Cannot translate messages in a Vim script. Solution: Add gettext(). Try it out for a few messages in the options window. https://github.com/vim/vim/commit/0b39c3fd4c5d1c8ebd2efa85fced7df5e17efd3b Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b475ff1096..e08dc2e4a5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3502,6 +3502,19 @@ static void f_glob2regpat(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = (pat == NULL) ? NULL : file_pat_to_reg_pat(pat, NULL, NULL, false); } +/// "gettext()" function +static void f_gettext(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + if (argvars[0].v_type != VAR_STRING + || argvars[0].vval.v_string == NULL + || *argvars[0].vval.v_string == NUL) { + semsg(_(e_invarg2), tv_get_string(&argvars[0])); + } else { + rettv->v_type = VAR_STRING; + rettv->vval.v_string = xstrdup(_(argvars[0].vval.v_string)); + } +} + /// "has()" function static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From bfdf10d87088ee8094cdbab7cef1cb49dc637663 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Oct 2022 11:39:51 +0800 Subject: vim-patch:8.2.1395: Vim9: no error if declaring a funcref with lower case letter Problem: Vim9: no error if declaring a funcref with a lower case letter. Solution: Check the name after the type is inferred. Fix confusing name. https://github.com/vim/vim/commit/98b4f145eb89405021e23a4a37db51d60a75a1d0 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 2 +- src/nvim/eval/vars.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index fb601c4307..f45e68acb3 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2436,7 +2436,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action // Check the key to be valid when adding to any scope. if (d1->dv_scope == VAR_DEF_SCOPE && tv_is_func(di2->di_tv) - && !var_check_func_name((const char *)di2->di_key, di1 == NULL)) { + && var_wrong_func_name((const char *)di2->di_key, di1 == NULL)) { break; } if (!valid_varname((const char *)di2->di_key)) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 4d7214205d..ef6e3f02e2 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1257,7 +1257,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, v = find_var_in_scoped_ht(name, name_len, true); } - if (tv_is_func(*tv) && !var_check_func_name(name, v == NULL)) { + if (tv_is_func(*tv) && var_wrong_func_name(name, v == NULL)) { return; } @@ -1445,9 +1445,9 @@ bool var_check_fixed(const int flags, const char *name, size_t name_len) /// @param[in] name Possible function/funcref name. /// @param[in] new_var True if it is a name for a variable. /// -/// @return false in case of error, true in case of success. Also gives an +/// @return false in case of success, true in case of failure. Also gives an /// error message if appropriate. -bool var_check_func_name(const char *const name, const bool new_var) +bool var_wrong_func_name(const char *const name, const bool new_var) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { // Allow for w: b: s: and t:. @@ -1455,16 +1455,16 @@ bool var_check_func_name(const char *const name, const bool new_var) && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0])) { semsg(_("E704: Funcref variable name must start with a capital: %s"), name); - return false; + return true; } // Don't allow hiding a function. When "v" is not NULL we might be // assigning another function to the same var, the type is checked // below. if (new_var && function_exists(name, false)) { semsg(_("E705: Variable name conflicts with existing function: %s"), name); - return false; + return true; } - return true; + return false; } // TODO(ZyX-I): move to eval/expressions -- cgit From 3afcc48a05693738f613464607286b5684b148cd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Oct 2022 13:27:38 +0800 Subject: vim-patch:8.2.3407: using uninitialized memory with "let g:['bar'] = 2" Problem: Using uninitialized memory with "let g:['bar'] = 2". Solution: Initialize v_type of a new dict item. https://github.com/vim/vim/commit/3b318513561b5862944769188ae4af6b70311838 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index f45e68acb3..cc6c2b5d90 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1841,6 +1841,7 @@ dictitem_T *tv_dict_item_alloc_len(const char *const key, const size_t key_len) di->di_key[key_len] = NUL; di->di_flags = DI_FLAGS_ALLOC; di->di_tv.v_lock = VAR_UNLOCKED; + di->di_tv.v_type = VAR_UNKNOWN; return di; } -- cgit From d8dbf58b4372d1415e3ca69541fc6fe71890ba53 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 1 Nov 2022 07:29:55 +0800 Subject: vim-patch:9.0.0821: crash with win_move_statusline() in another tabpage (#20894) vim-patch:86e6717ace4f Problem: Crash when using win_move_statusline() in another tab page. Solution: Check for valid window pointer. (issue vim/vim#11427) https://github.com/vim/vim/commit/86e6717ace4f5e00eaeb84b59e3fc92bca548155 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e08dc2e4a5..17781cf4ef 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -112,6 +112,8 @@ PRAGMA_DIAG_POP static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static char *e_invalwindow = N_("E957: Invalid window number"); static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); +static char e_cannot_resize_window_in_another_tab_page[] + = N_("E1308: Cannot resize a window in another tab page"); /// Dummy va_list for passing to vim_snprintf /// @@ -9694,6 +9696,10 @@ static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, EvalFuncDa if (wp == NULL || wp->w_floating) { return; } + if (!win_valid(wp)) { + emsg(_(e_cannot_resize_window_in_another_tab_page)); + return; + } offset = (int)tv_get_number(&argvars[1]); win_drag_status_line(wp, offset); -- cgit From c46d46e9f11a9960fcf9c498ecc72be4c416cfa5 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 1 Nov 2022 20:21:48 +0800 Subject: vim-patch:8.2.2343: Vim9: return type of readfile() is any (#20896) Problem: Vim9: return type of readfile() is any. Solution: Add readblob() so that readfile() can be expected to always return a list of strings. (closes vim/vim#7671) https://github.com/vim/vim/commit/c423ad77ed763c11ba67729bbf63c1cf0915231f Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 17781cf4ef..79c93f1917 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5872,11 +5872,11 @@ static void f_readdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ga_clear_strings(&ga); } -/// "readfile()" function -static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// "readfile()" or "readblob()" function +static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_blob) { bool binary = false; - bool blob = false; + bool blob = always_blob; FILE *fd; char buf[(IOSIZE/256) * 256]; // rounded to avoid odd + 1 int io_size = sizeof(buf); @@ -6011,8 +6011,8 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int adjust_prevlen = 0; if (dest < buf) { // -V782 - adjust_prevlen = (int)(buf - dest); // -V782 // adjust_prevlen must be 1 or 2. + adjust_prevlen = (int)(buf - dest); // -V782 dest = buf; } if (readlen > p - buf + 1) { @@ -6055,6 +6055,18 @@ static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) fclose(fd); } +/// "readblob()" function +static void f_readblob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + read_file_or_blob(argvars, rettv, true); +} + +/// "readfile()" function +static void f_readfile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + read_file_or_blob(argvars, rettv, false); +} + /// "getreginfo()" function static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { -- cgit From b05d1943f063c382ea96b76d250877bc58297314 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 1 Nov 2022 15:39:49 +0100 Subject: build(lint): remove clint.py rules for braces #20880 Uncrustify is the source of truth where possible. Remove any redundant checks from clint.py. See also https://github.com/neovim/neovim/pull/18563 --- src/nvim/eval/typval.c | 28 ++++++++++++++-------------- src/nvim/eval/userfunc.c | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index cc6c2b5d90..11b2b6e5fd 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3595,13 +3595,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 @@ -3640,13 +3640,13 @@ bool tv_check_num(const typval_T *const tv) #define FUNC_ERROR "E729: using 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_FLOAT]=((const char *)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_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_FLOAT]= ((const char *)e_float_as_string), + [VAR_BLOB]= N_("E976: using Blob as a String"), + [VAR_UNKNOWN]= N_("E908: using an invalid value as a String"), }; #undef FUNC_ERROR diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 147beb78ad..c22718c65d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -998,7 +998,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett listitem_T *li = &fc->l_listitems[ai]; *TV_LIST_ITEM_TV(li) = argvars[i]; - TV_LIST_ITEM_TV(li)->v_lock = VAR_FIXED; + TV_LIST_ITEM_TV(li)->v_lock = VAR_FIXED; tv_list_append(&fc->l_varlist, li); } } -- cgit From 39f85cdf6b40cbdd26256260d0d6d4e071b631a2 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 1 Nov 2022 20:22:48 +0800 Subject: vim-patch:9.0.0824: crash when using win_move_separator() in other tab page Problem: Crash when using win_move_separator() in other tab page. Solution: Check for valid window in current tab page. (closes vim/vim#11479, closes vim/vim#11427) https://github.com/vim/vim/commit/873f41a0187e81a22aa4622fbf938de72a54abba --- src/nvim/eval/funcs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 79c93f1917..e676e2e656 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9690,6 +9690,10 @@ static void f_win_move_separator(typval_T *argvars, typval_T *rettv, EvalFuncDat if (wp == NULL || wp->w_floating) { return; } + if (!win_valid(wp)) { + emsg(_(e_cannot_resize_window_in_another_tab_page)); + return; + } int offset = (int)tv_get_number(&argvars[1]); win_drag_vsep_line(wp, offset); -- cgit From 4716a578ae0c3516d685495bb55e40c939a4ac87 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 23 Oct 2022 10:17:45 +0200 Subject: docs: fix typos --- src/nvim/eval/userfunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c22718c65d..71f33fe465 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -460,7 +460,7 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char **arg, funcex int i = 0; if (get_vim_var_nr(VV_TESTING)) { - // Prepare for calling garbagecollect_for_testing(), need to know + // Prepare for calling test_garbagecollect_now(), need to know // what variables are used on the call stack. if (funcargs.ga_itemsize == 0) { ga_init(&funcargs, (int)sizeof(typval_T *), 50); -- cgit From 04fbb1de4488852c3ba332898b17180500f8984e Mon Sep 17 00:00:00 2001 From: Jonathon <32371757+jwhite510@users.noreply.github.com> Date: Fri, 4 Nov 2022 05:07:22 -0400 Subject: Enable new diff option linematch (#14537) Co-authored-by: Lewis Russell --- src/nvim/eval/funcs.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index e676e2e656..0e3de29cce 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1573,9 +1573,10 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) || changedtick != buf_get_changedtick(curbuf) || fnum != curbuf->b_fnum) { // New line, buffer, change: need to get the values. - int filler_lines = diff_check(curwin, lnum); - if (filler_lines < 0) { - if (filler_lines == -1) { + int linestatus = 0; + int filler_lines = diff_check_with_linestatus(curwin, lnum, &linestatus); + if (filler_lines < 0 || linestatus < 0) { + if (filler_lines == -1 || linestatus == -1) { change_start = MAXCOL; change_end = -1; if (diff_find_change(curwin, lnum, &change_start, &change_end)) { -- cgit From 45ca7d4a62d9d6275339e9d9c0a4930448592712 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 11:17:10 +0800 Subject: vim-patch:8.2.0502: Vim9: some code is not tested Problem: Vim9: some code is not tested. Solution: Add more tests. Fix uncovered problems. https://github.com/vim/vim/commit/e8c4abbbd711af8fd3ed85ea69e9ac3d63a0d879 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 71f33fe465..4024410a04 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1964,7 +1964,7 @@ void ex_function(exarg_T *eap) // ":function /pat": list functions matching pattern. if (*eap->arg == '/') { - p = skip_regexp(eap->arg + 1, '/', true, NULL); + p = skip_regexp(eap->arg + 1, '/', true); if (!eap->skip) { regmatch_T regmatch; -- cgit From 5731f406fa6ddf9c8340329ec1e534cd968df94f Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 14:35:46 +0800 Subject: vim-patch:8.2.3252: duplicated code for adding buffer lines Problem: Duplicated code for adding buffer lines. Solution: Move code to a common function. Also move map functions to map.c. (Yegappan Lakshmanan, closes vim/vim#8665) https://github.com/vim/vim/commit/4a15504e911bc90a29d862862f0b7a46d8acd12a Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 0e3de29cce..c4d0604b67 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -370,18 +370,24 @@ static void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); } -/// "appendbufline(buf, lnum, string/list)" function -static void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// Set or append lines to a buffer. +static void buf_set_append_line(typval_T *argvars, typval_T *rettv, bool append) { buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { rettv->vval.v_number = 1; // FAIL } else { const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); - set_buffer_lines(buf, lnum, true, &argvars[2], rettv); + set_buffer_lines(buf, lnum, append, &argvars[2], rettv); } } +/// "appendbufline(buf, lnum, string/list)" function +static void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_set_append_line(argvars, rettv, true); +} + /// "atan2()" function static void f_atan2(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -7501,16 +7507,7 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "setbufline()" function static void f_setbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - linenr_T lnum; - buf_T *buf; - - buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - rettv->vval.v_number = 1; // FAIL - } else { - lnum = tv_get_lnum_buf(&argvars[1], buf); - set_buffer_lines(buf, lnum, false, &argvars[2], rettv); - } + buf_set_append_line(argvars, rettv, false); } /// Set the cursor or mark position. -- cgit From 48405df046e6d15c26aeea429fa44950ccc1a8ac Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 14:31:40 +0800 Subject: vim-patch:8.2.3919: Vim9: wrong argument for append() results in two errors Problem: Vim9: wrong argument for append() results in two errors. Solution: Check did_emsg. Also for setline(). Adjust the help for appendbufline(). https://github.com/vim/vim/commit/8b6256f6ec075cca40341e61ebc9f538b4902dd1 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c4d0604b67..cf924b1c49 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -365,20 +365,25 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "append(lnum, string/list)" function static void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + const int did_emsg_before = did_emsg; const linenr_T lnum = tv_get_lnum(&argvars[0]); - - set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); + if (did_emsg == did_emsg_before) { + set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); + } } /// Set or append lines to a buffer. static void buf_set_append_line(typval_T *argvars, typval_T *rettv, bool append) { + const int did_emsg_before = did_emsg; buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { rettv->vval.v_number = 1; // FAIL } else { const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); - set_buffer_lines(buf, lnum, append, &argvars[2], rettv); + if (did_emsg == did_emsg_before) { + set_buffer_lines(buf, lnum, append, &argvars[2], rettv); + } } } @@ -1476,9 +1481,10 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fp /// "deletebufline()" function static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + const int did_emsg_before = did_emsg; + rettv->vval.v_number = 1; // FAIL by default buf_T *const buf = tv_get_buf(&argvars[0], false); if (buf == NULL) { - rettv->vval.v_number = 1; // FAIL return; } const bool is_curbuf = buf == curbuf; @@ -1486,6 +1492,9 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fpt linenr_T last; const linenr_T first = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) { + return; + } if (argvars[2].v_type != VAR_UNKNOWN) { last = tv_get_lnum_buf(&argvars[2], buf); } else { @@ -1494,7 +1503,6 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fpt if (buf->b_ml.ml_mfp == NULL || first < 1 || first > buf->b_ml.ml_line_count || last < first) { - rettv->vval.v_number = 1; // FAIL return; } @@ -1547,6 +1555,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fpt curwin = curwin_save; VIsual_active = save_VIsual_active; } + rettv->vval.v_number = 0; // OK } /// "did_filetype()" function @@ -2581,9 +2590,12 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli /// "getbufline()" function static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + const int did_emsg_before = did_emsg; buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); - const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) { + return; + } const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN ? lnum : tv_get_lnum_buf(&argvars[2], buf)); @@ -7636,8 +7648,11 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "setline()" function static void f_setline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { + const int did_emsg_before = did_emsg; linenr_T lnum = tv_get_lnum(&argvars[0]); - set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv); + if (did_emsg == did_emsg_before) { + set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv); + } } /// "setpos()" function -- cgit From 562d572926e0c11329c13c9df45be7170888e7f6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 22 Oct 2022 10:05:34 +0800 Subject: vim-patch:8.1.1949: cannot scroll a popup window to the very bottom Problem: Cannot scroll a popup window to the very bottom. Solution: Scroll to the bottom when the "firstline" property was set to -1. (closes vim/vim#4577) Allow resetting min/max width/height. https://github.com/vim/vim/commit/8c6173c7d3431dd8bc2b6ffc076ef49512a7e175 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 11b2b6e5fd..31b73f8d48 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2060,10 +2060,25 @@ int tv_dict_get_tv(dict_T *d, const char *const key, typval_T *rettv) /// @return Dictionary item. varnumber_T tv_dict_get_number(const dict_T *const d, const char *const key) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return tv_dict_get_number_def(d, key, 0); +} + +/// Get a number item from a dictionary. +/// +/// Returns "def" if the entry doesn't exist. +/// +/// @param[in] d Dictionary to get item from. +/// @param[in] key Key to find in dictionary. +/// @param[in] def Default value. +/// +/// @return Dictionary item. +varnumber_T tv_dict_get_number_def(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 0; + return def; } return tv_get_number(&di->di_tv); } -- cgit From e25193143bca3a48920322634120a442854bb891 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 14:59:45 +0800 Subject: vim-patch:8.2.1751: using 2 where bool is expected may throw an error Problem: Using 2 where bool is expected may throw an error. Solution: Make this backwards compatible. https://github.com/vim/vim/commit/bade44e5cad1b08c85d4a8ba08d94a30458dddfb In legacy Vim script get_bool functions do the same thing as get_number functions, so just add aliases using #define. N/A patches for version.c: vim-patch:8.2.1506: Vim9: no error when using a number other than 0 or 1 as bool Problem: Vim9: no error when using a number other than 0 or 1 as bool. Solution: Check the number is 0 or 1. https://github.com/vim/vim/commit/d70840ed68296c1144d743e6335003c81c558c24 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 6 ++++-- src/nvim/eval/typval.h | 5 +++++ 2 files changed, 9 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index cf924b1c49..1661a7079e 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -112,6 +112,8 @@ PRAGMA_DIAG_POP static char *e_listblobarg = N_("E899: Argument of %s must be a List or Blob"); static char *e_invalwindow = N_("E957: Invalid window number"); static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); +static char e_using_number_as_bool_nr[] + = N_("E1023: Using a Number as a Bool: %d"); static char e_cannot_resize_window_in_another_tab_page[] = N_("E1308: Cannot resize a window in another tab page"); @@ -1361,7 +1363,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) noref = (int)tv_get_number_chk(&argvars[1], NULL); } if (noref < 0 || noref > 1) { - emsg(_(e_invarg)); + semsg(_(e_using_number_as_bool_nr), noref); } else { var_item_copy(NULL, &argvars[0], rettv, true, (noref == 0 ? get_copyID() @@ -8457,7 +8459,7 @@ static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) skipcc = (int)tv_get_number_chk(&argvars[1], NULL); } if (skipcc < 0 || skipcc > 1) { - emsg(_(e_invarg)); + semsg(_(e_using_number_as_bool_nr), skipcc); } else { func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; while (*s != NUL) { diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index fcc933c967..6757d058ef 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -559,4 +559,9 @@ EXTERN const size_t kTVTranslate INIT(= TV_TRANSLATE); #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/typval.h.generated.h" #endif + +#define tv_get_bool tv_get_number +#define tv_get_bool_chk tv_get_number_chk +#define tv_dict_get_bool tv_dict_get_number_def + #endif // NVIM_EVAL_TYPVAL_H -- cgit From 38c113ae842aa8c42ad66bba15f16cf401637ab8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 17:43:38 +0800 Subject: vim-patch:8.2.1600: Vim9: cannot use "true" with deepcopy() Problem: Vim9: cannot use "true" with deepcopy(). Solution: Use tv_get_bool_chk(). (closes vim/vim#6867) https://github.com/vim/vim/commit/44b4a246b62e0622550b963bcf3034dce3bcfc0c Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1661a7079e..553a377d21 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1360,7 +1360,7 @@ static void f_deepcopy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int noref = 0; if (argvars[1].v_type != VAR_UNKNOWN) { - noref = (int)tv_get_number_chk(&argvars[1], NULL); + noref = (int)tv_get_bool_chk(&argvars[1], NULL); } if (noref < 0 || noref > 1) { semsg(_(e_using_number_as_bool_nr), noref); -- cgit From d857569dbdc0a9374b2cf661b9a7d49b38aad966 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 15:02:54 +0800 Subject: vim-patch:8.2.1624: Vim9: cannot pass "true" to split(), str2nr() and strchars() Problem: Vim9: cannot pass "true" to split(), str2nr() and strchars(). Solution: Use tv_get_bool_chk(). (closes vim/vim#6884, closes vim/vim#6885, closes vim/vim#6886) https://github.com/vim/vim/commit/3986b94b090ea258109630008611230a599999ab Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 553a377d21..4939c5ef5d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8162,7 +8162,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) typeerr = true; } if (argvars[2].v_type != VAR_UNKNOWN) { - keepempty = (bool)tv_get_number_chk(&argvars[2], &typeerr); + keepempty = (bool)tv_get_bool_chk(&argvars[2], &typeerr); } } if (pat == NULL || *pat == NUL) { @@ -8292,7 +8292,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) emsg(_(e_invarg)); return; } - if (argvars[2].v_type != VAR_UNKNOWN && tv_get_number(&argvars[2])) { + if (argvars[2].v_type != VAR_UNKNOWN && tv_get_bool(&argvars[2])) { what |= STR2NR_QUOTE; } } @@ -8451,12 +8451,12 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *s = tv_get_string(&argvars[0]); - int skipcc = 0; + int skipcc = false; varnumber_T len = 0; int (*func_mb_ptr2char_adv)(const char_u **pp); if (argvars[1].v_type != VAR_UNKNOWN) { - skipcc = (int)tv_get_number_chk(&argvars[1], NULL); + skipcc = (int)tv_get_bool(&argvars[1]); } if (skipcc < 0 || skipcc > 1) { semsg(_(e_using_number_as_bool_nr), skipcc); -- cgit From 781616bee5e319fdfa034484c026222b50926ebf Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 17:16:49 +0800 Subject: vim-patch:8.2.2606: strchars() defaults to counting composing characters Problem: strchars() defaults to counting composing characters. Solution: Add strcharlen() which ignores composing characters. https://github.com/vim/vim/commit/70ce8a1561c5396e4c4381f76a005cbb97646f80 Use docs from latest Vim instead. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4939c5ef5d..7ad4850d40 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8447,26 +8447,38 @@ static void f_strlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = (varnumber_T)strlen(tv_get_string(&argvars[0])); } -/// "strchars()" function -static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc) { const char *s = tv_get_string(&argvars[0]); - int skipcc = false; varnumber_T len = 0; int (*func_mb_ptr2char_adv)(const char_u **pp); + func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; + while (*s != NUL) { + func_mb_ptr2char_adv((const char_u **)&s); + len++; + } + rettv->vval.v_number = len; +} + +/// "strcharlen()" function +static void f_strcharlen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + strchar_common(argvars, rettv, true); +} + +/// "strchars()" function +static void f_strchars(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + int skipcc = false; + if (argvars[1].v_type != VAR_UNKNOWN) { skipcc = (int)tv_get_bool(&argvars[1]); } if (skipcc < 0 || skipcc > 1) { semsg(_(e_using_number_as_bool_nr), skipcc); } else { - func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; - while (*s != NUL) { - func_mb_ptr2char_adv((const char_u **)&s); - len++; - } - rettv->vval.v_number = len; + strchar_common(argvars, rettv, skipcc); } } -- cgit From 8e868d699a9d0b68342d8d460a8f6dd9c075d7a8 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 22 Oct 2022 09:32:01 +0800 Subject: vim-patch:8.2.4679: cannot have expandcmd() give an error message for mistakes Problem: Cannot have expandcmd() give an error message for mistakes. Solution: Add an optional argument to give errors. Fix memory leak when expanding files fails. (Yegappan Lakshmanan, closes vim/vim#10071) https://github.com/vim/vim/commit/2b74b6805b5c8c4836b66df5d949f5ff6a77f8c7 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7ad4850d40..1e971791bd 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2058,6 +2058,12 @@ static void f_menu_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char *errormsg = NULL; + bool emsgoff = true; + + if (argvars[1].v_type == VAR_DICT + && tv_dict_get_bool(argvars[1].vval.v_dict, "errmsg", kBoolVarFalse)) { + emsgoff = false; + } rettv->v_type = VAR_STRING; char *cmdstr = xstrdup(tv_get_string(&argvars[0])); @@ -2071,9 +2077,17 @@ static void f_expandcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) }; eap.argt |= EX_NOSPC; - emsg_off++; - expand_filename(&eap, &cmdstr, &errormsg); - emsg_off--; + if (emsgoff) { + emsg_off++; + } + if (expand_filename(&eap, &cmdstr, &errormsg) == FAIL) { + if (!emsgoff && errormsg != NULL && *errormsg != NUL) { + emsg(errormsg); + } + } + if (emsgoff) { + emsg_off--; + } rettv->vval.v_string = cmdstr; } -- cgit From 3c0651fb459189f5be6165454810e4476296cb7c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 18:02:05 +0800 Subject: fix(eval): make error number of charidx() same as Vim --- src/nvim/eval/funcs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1e971791bd..26a5c133da 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -908,7 +908,7 @@ static void f_charidx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) countcc = (int)tv_get_number(&argvars[2]); } if (countcc < 0 || countcc > 1) { - emsg(_(e_invarg)); + semsg(_(e_using_number_as_bool_nr), countcc); return; } -- cgit From e03f23189d765ade07b21d2f50c047f84741a133 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Nov 2022 06:31:00 +0800 Subject: vim-patch:8.2.1274: Vim9: no error for missing white space at script level Problem: Vim9: no error for missing white space in assignment at script level. Solution: Check for white space. (closes vim/vim#6495) https://github.com/vim/vim/commit/63be3d4ba01d565e645d8bf7f4dc900fc9011534 Cherry-pick Test_let_errors() change from patch 8.2.0633. Co-authored-by: Bram Moolenaar --- src/nvim/eval/vars.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ef6e3f02e2..3f73dbfdc5 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -231,11 +231,13 @@ static void ex_let_const(exarg_T *eap, const bool is_const) expr++; } } - expr = skipwhite(expr + 2); + expr += 2; } else { - expr = skipwhite(expr + 1); + expr += 1; } + expr = skipwhite(expr); + if (eap->skip) { emsg_skip++; } -- cgit From dc17df31908ac0e0c092760d84f035d3bfc55aae Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Nov 2022 09:35:02 +0800 Subject: fix(eval): change some tv_dict_add() usages back to hash_add() Needed for Vim patch 8.2.2920. --- src/nvim/eval/userfunc.c | 10 +++++----- src/nvim/eval/vars.c | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 4024410a04..ef74ca58e3 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -589,7 +589,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) STRCPY(v->di_key, name); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - tv_dict_add(dp, v); + hash_add(&dp->dv_hashtab, v->di_key); v->di_tv.v_type = VAR_NUMBER; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_number = nr; @@ -885,7 +885,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - tv_dict_add(&fc->l_vars, v); + hash_add(&fc->l_vars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = VAR_UNLOCKED; v->di_tv.vval.v_dict = selfdict; @@ -911,7 +911,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - tv_dict_add(&fc->l_avars, v); + hash_add(&fc->l_avars.dv_hashtab, v->di_key); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_list = &fc->l_varlist; @@ -989,9 +989,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Named arguments can be accessed without the "a:" prefix in lambda // expressions. Add to the l: dict. tv_copy(&v->di_tv, &v->di_tv); - tv_dict_add(&fc->l_vars, v); + hash_add(&fc->l_vars.dv_hashtab, v->di_key); } else { - tv_dict_add(&fc->l_avars, v); + hash_add(&fc->l_avars.dv_hashtab, v->di_key); } if (ai >= 0 && ai < MAX_FUNC_ARGS) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3f73dbfdc5..a0877deaf7 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1331,7 +1331,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, v = xmalloc(sizeof(dictitem_T) + strlen(varname)); STRCPY(v->di_key, varname); - if (tv_dict_add(dict, v) == FAIL) { + if (hash_add(ht, v->di_key) == FAIL) { xfree(v); return; } -- cgit From 6b3db3f92906b1c155b11f177c9378d9ff4d7d6b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Oct 2022 11:56:29 +0800 Subject: vim-patch:8.2.2920: still a way to shadow a builtin function Problem: Still a way to shadow a builtin function. (Yasuhiro Matsumoto) Solution: Check the key when using extend(). (issue vim/vim#8302) https://github.com/vim/vim/commit/6f1d2aa437744a7cb0206fdaa543a788c5a56c79 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 31b73f8d48..2b44dacca4 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2206,6 +2206,18 @@ bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_ return res; } +/// Check for adding a function to g: or s:. +/// If the name is wrong give an error message and return true. +int tv_dict_wrong_func_name(dict_T *d, typval_T *tv, const char *name) +{ + return (d == &globvardict + // || (SCRIPT_ID_VALID(current_sctx.sc_sid) + // && d == &SCRIPT_ITEM(current_sctx.sc_sid)->sn_vars->sv_dict) + ) + && (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) + && var_wrong_func_name(name, true); +} + //{{{2 dict_add* /// Add item to dictionary @@ -2217,6 +2229,9 @@ bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_ 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)) { + return FAIL; + } return hash_add(&d->dv_hashtab, item->di_key); } @@ -2477,6 +2492,9 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { break; } + if (tv_dict_wrong_func_name(d1, &di2->di_tv, (const char *)di2->di_key)) { + break; + } if (watched) { tv_copy(&di1->di_tv, &oldtv); -- cgit From 4740672b37612004d559e9577ca87223ed49ec64 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 28 Oct 2022 12:08:18 +0800 Subject: vim-patch:8.2.2921: E704 for script local variable is not backwards compatible Problem: E704 for script local variable is not backwards compatible. (Yasuhiro Matsumoto) Solution: Only give the error in Vim9 script. Also check for function-local variable. https://github.com/vim/vim/commit/b54abeeafb074248597878a874fed9a66b114c06 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 2b44dacca4..c8f89407b9 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2210,10 +2210,7 @@ bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_ /// If the name is wrong give an error message and return true. int tv_dict_wrong_func_name(dict_T *d, typval_T *tv, const char *name) { - return (d == &globvardict - // || (SCRIPT_ID_VALID(current_sctx.sc_sid) - // && d == &SCRIPT_ITEM(current_sctx.sc_sid)->sn_vars->sv_dict) - ) + return (d == &globvardict || &d->dv_hashtab == get_funccal_local_ht()) && (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) && var_wrong_func_name(name, true); } -- cgit From d4353c3645f294b67f5b30dae9f39de8f99c7413 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Nov 2022 07:01:45 +0800 Subject: vim-patch:9.0.0836: wrong error when using extend() with funcref Problem: Wrong error when using extend() with funcref. Solution: Better check the variable type. (closes vim/vim#11468, closes vim/vim#11455) https://github.com/vim/vim/commit/91c75d18d9cdc32df57e648640de7476fbcb4d76 --- src/nvim/eval/typval.c | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index c8f89407b9..13d836071d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2206,12 +2206,12 @@ bool tv_dict_get_callback(dict_T *const d, const char *const key, const ptrdiff_ return res; } -/// Check for adding a function to g: or s:. +/// Check for adding a function to g: or l:. /// If the name is wrong give an error message and return true. int tv_dict_wrong_func_name(dict_T *d, typval_T *tv, const char *name) { return (d == &globvardict || &d->dv_hashtab == get_funccal_local_ht()) - && (tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL) + && tv_is_func(*tv) && var_wrong_func_name(name, true); } @@ -2459,17 +2459,9 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action TV_DICT_ITER(d2, di2, { dictitem_T *const di1 = tv_dict_find(d1, (const char *)di2->di_key, -1); - if (d1->dv_scope != VAR_NO_SCOPE) { - // Disallow replacing a builtin function in l: and g:. - // Check the key to be valid when adding to any scope. - if (d1->dv_scope == VAR_DEF_SCOPE - && tv_is_func(di2->di_tv) - && var_wrong_func_name((const char *)di2->di_key, di1 == NULL)) { - break; - } - if (!valid_varname((const char *)di2->di_key)) { - break; - } + // 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)) { + break; } if (di1 == NULL) { dictitem_T *const new_di = tv_dict_item_copy(di2); @@ -2489,6 +2481,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { break; } + // Disallow replacing a builtin function. if (tv_dict_wrong_func_name(d1, &di2->di_tv, (const char *)di2->di_key)) { break; } -- cgit From ed01ef7fa5c2611748f90acfdc2145b22629dc36 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 6 Nov 2022 15:11:48 +0800 Subject: vim-patch:9.0.0355: check for uppercase char in autoload name is wrong Problem: Check for uppercase char in autoload name is wrong, it checks the name of the script. Solution: Remove the check. (closes vim/vim#11031) https://github.com/vim/vim/commit/6c667bdc9489963102bd6c46b1b73e4d43c034ce Co-authored-by: thinca --- src/nvim/eval/vars.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index a0877deaf7..139e7ed66b 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1453,9 +1453,10 @@ bool var_wrong_func_name(const char *const name, const bool new_var) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT { // Allow for w: b: s: and t:. + // Allow autoload variable. if (!(vim_strchr("wbst", name[0]) != NULL && name[1] == ':') - && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') - ? name[2] : name[0])) { + && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0]) + && vim_strchr(name, '#') == NULL) { semsg(_("E704: Funcref variable name must start with a capital: %s"), name); return true; } -- cgit From 731cdde28ea8d48cc23ba2752a08c261c87eee92 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 22 Oct 2022 12:36:38 +0200 Subject: refactor: fix clang-tidy warnings Enable and fix bugprone-misplaced-widening-cast warning. Fix some modernize-macro-to-enum and readability-else-after-return warnings, but don't enable them. While the warnings can be useful, they are in general too noisy to enable. --- src/nvim/eval/decode.c | 11 +++++------ src/nvim/eval/funcs.c | 8 +++----- src/nvim/eval/typval.c | 3 +-- src/nvim/eval/userfunc.c | 3 +-- src/nvim/eval/vars.c | 6 ++---- 5 files changed, 12 insertions(+), 19 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index 6b7eb2f8f8..f677148e08 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -284,13 +284,12 @@ typval_T decode_string(const char *const s, const size_t len, const TriState has } } return tv; - } else { - return (typval_T) { - .v_type = VAR_STRING, - .v_lock = VAR_UNLOCKED, - .vval = { .v_string = ((s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, - }; } + return (typval_T) { + .v_type = VAR_STRING, + .v_lock = VAR_UNLOCKED, + .vval = { .v_string = ((s == NULL || s_allocated) ? (char *)s : xmemdupz(s, len)) }, + }; } /// Parse JSON double-quoted string diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 26a5c133da..5acc37bfb1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5238,10 +5238,9 @@ static void f_mkdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(failed_dir); rettv->vval.v_number = FAIL; return; - } else { - rettv->vval.v_number = OK; - return; } + rettv->vval.v_number = OK; + return; } } rettv->vval.v_number = vim_mkdir_emsg(dir, prot); @@ -7483,9 +7482,8 @@ static void f_serverstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[0].v_type != VAR_STRING) { emsg(_(e_invarg)); return; - } else { - address = xstrdup(tv_get_string(argvars)); } + address = xstrdup(tv_get_string(argvars)); } else { address = server_address_new(NULL); } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 13d836071d..e09fda173b 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1747,9 +1747,8 @@ static bool tv_dict_watcher_matches(DictWatcher *watcher, const char *const key) const size_t len = watcher->key_pattern_len; if (len && watcher->key_pattern[len - 1] == '*') { return strncmp(key, watcher->key_pattern, len - 1) == 0; - } else { - return strcmp(key, watcher->key_pattern) == 0; } + return strcmp(key, watcher->key_pattern) == 0; } /// Send a change notification to all dictionary watchers that match given key diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ef74ca58e3..638573a235 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2019,9 +2019,8 @@ void ex_function(exarg_T *eap) } xfree(fudi.fd_newkey); return; - } else { - eap->skip = true; } + eap->skip = true; } // An error in a function call during evaluation of an expression in magic diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 139e7ed66b..97630d4953 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -380,9 +380,8 @@ const char *skip_var_list(const char *arg, int *var_count, int *semicolon) } } return p + 1; - } else { - return skip_var_one((char *)arg); } + return skip_var_one((char *)arg); } /// Skip one (assignable) variable name, including @r, $VAR, &option, d.key, @@ -884,9 +883,8 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ lp->ll_n1++; if (lp->ll_li == NULL || (!lp->ll_empty2 && lp->ll_n2 < lp->ll_n1)) { break; - } else { - last_li = lp->ll_li; } + last_li = lp->ll_li; } tv_list_remove_items(lp->ll_list, first_li, last_li); } else { -- cgit From 3b3611a3d0f1e13e277360d6bacf97a0fb7eb6de Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 7 Nov 2022 07:03:31 +0800 Subject: vim-patch:9.0.0841: deletebufline() does not always return 1 on failure (#20980) Problem: deletebufline() does not always return 1 on failure. Solution: Refactor the code to make it work more predictable. (closes vim/vim#11511) https://github.com/vim/vim/commit/7af3ee2b83545169d78a28ab1cd89aff1127f8b3 --- src/nvim/eval/funcs.c | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 26a5c133da..1492a2d30d 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1510,6 +1510,7 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fpt buf_T *curbuf_save = NULL; win_T *curwin_save = NULL; + // After this don't use "return", goto "cleanup"! if (!is_curbuf) { VIsual_active = false; curbuf_save = curbuf; @@ -1530,34 +1531,35 @@ static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fpt } if (u_save(first - 1, last + 1) == FAIL) { - rettv->vval.v_number = 1; // FAIL - } else { - for (linenr_T lnum = first; lnum <= last; lnum++) { - ml_delete(first, true); - } + goto cleanup; + } - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp->w_buffer == buf) { - if (wp->w_cursor.lnum > last) { - wp->w_cursor.lnum -= (linenr_T)count; - } else if (wp->w_cursor.lnum > first) { - wp->w_cursor.lnum = first; - } - if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) { - wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count; - } + for (linenr_T lnum = first; lnum <= last; lnum++) { + ml_delete(first, true); + } + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer == buf) { + if (wp->w_cursor.lnum > last) { + wp->w_cursor.lnum -= (linenr_T)count; + } else if (wp->w_cursor.lnum > first) { + wp->w_cursor.lnum = first; + } + if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) { + wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count; } } - check_cursor_col(); - deleted_lines_mark(first, count); } + check_cursor_col(); + deleted_lines_mark(first, count); + rettv->vval.v_number = 0; // OK +cleanup: if (!is_curbuf) { curbuf = curbuf_save; curwin = curwin_save; VIsual_active = save_VIsual_active; } - rettv->vval.v_number = 0; // OK } /// "did_filetype()" function -- cgit From b3e9010f4783a51407ec5a5ad9fda1216d4db3fe Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 5 Nov 2022 15:30:54 +0800 Subject: vim-patch:8.2.3705: cannot pass a lambda name to function() or funcref() Problem: Cannot pass a lambda name to function() or funcref(). (Yegappan Lakshmanan) Solution: Handle a lambda name differently. https://github.com/vim/vim/commit/eba3b7f6645c8f856132b4c06a009a3b0a44e21c Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ef74ca58e3..e6b038a335 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1886,6 +1886,27 @@ theend: return (char_u *)name; } +/// Call trans_function_name(), except that a lambda is returned as-is. +/// Returns the name in allocated memory. +char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) +{ + char *p = *name; + char *saved; + + if (strncmp(p, "", 8) == 0) { + p += 8; + (void)getdigits(&p, false, 0); + saved = xstrndup(*name, (size_t)(p - *name)); + if (fudi != NULL) { + CLEAR_POINTER(fudi); + } + } else { + saved = (char *)trans_function_name(&p, skip, flags, fudi, NULL); + } + *name = p; + return saved; +} + #define MAX_FUNC_NESTING 50 /// List functions. @@ -2000,14 +2021,7 @@ void ex_function(exarg_T *eap) // s:func script-local function name // g:func global function name, same as "func" p = eap->arg; - if (strncmp(p, "", 8) == 0) { - p += 8; - (void)getdigits(&p, false, 0); - name = xstrndup(eap->arg, (size_t)(p - eap->arg)); - CLEAR_FIELD(fudi); - } else { - name = (char *)trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL); - } + name = save_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi); paren = (vim_strchr(p, '(') != NULL); if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip) { // Return on an invalid expression in braces, unless the expression -- cgit From 1e4adf4b56cb7a360d16c4d04290c50ae7e80fbc Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 20 Aug 2022 08:45:15 +0800 Subject: vim-patch:8.2.3725: cannot use a lambda for 'completefunc' and 'omnifunc' Problem: Cannot use a lambda for 'completefunc' and 'omnifunc'. Solution: Implement lambda support. (Yegappan Lakshmanan, closes vim/vim#9257) https://github.com/vim/vim/commit/8658c759f05b317707d56e3b65a5ef63930c7498 Comment out Vim9 script in tests. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index e6b038a335..d07cfe0bd9 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1393,6 +1393,24 @@ func_call_skip_call: return r; } +/// call the 'callback' function and return the result as a number. +/// Returns -1 when calling the function fails. Uses argv[0] to argv[argc - 1] +/// for the function arguments. argv[argc] should have type VAR_UNKNOWN. +/// +/// @param argcount number of "argvars" +/// @param argvars vars for arguments, must have "argcount" PLUS ONE elements! +varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argvars) +{ + typval_T rettv; + if (!callback_call(callback, argcount, argvars, &rettv)) { + return -1; + } + + varnumber_T retval = tv_get_number_chk(&rettv, NULL); + tv_clear(&rettv); + return retval; +} + /// Give an error message for the result of a function. /// Nothing if "error" is FCERR_NONE. static void user_func_error(int error, const char_u *name) -- cgit From d337814906b1377e34aa2c2dfd8aa16285328692 Mon Sep 17 00:00:00 2001 From: Victor Blanchard <48864055+Viblanc@users.noreply.github.com> Date: Mon, 7 Nov 2022 04:31:50 +0100 Subject: feat: ":write ++p" creates parent dirs #20835 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `:write ++p foo/bar/baz.txt` should create parent directories `foo/bar/` if they do not exist - Note: `:foo ++…` is usually for options. No existing options have a single-char abbreviation (presumably by design), so it's safe to special-case `++p` here. - Same for `writefile(…, 'foo/bar/baz.txt', 'p')` - `BufWriteCmd` can see the ++p flag via `v:cmdarg`. closes #19884 --- src/nvim/eval/funcs.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1492a2d30d..5fcbc40623 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -9970,6 +9970,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool binary = false; bool append = false; bool do_fsync = !!p_fs; + bool mkdir_p = false; if (argvars[2].v_type != VAR_UNKNOWN) { const char *const flags = tv_get_string_chk(&argvars[2]); if (flags == NULL) { @@ -9985,6 +9986,8 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) do_fsync = true; break; case 'S': do_fsync = false; break; + case 'p': + mkdir_p = true; break; default: // Using %s, p and not %c, *p to preserve multibyte characters semsg(_("E5060: Unknown flag: %s"), p); @@ -10004,6 +10007,7 @@ static void f_writefile(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) emsg(_("E482: Can't open file with an empty name")); } else if ((error = file_open(&fp, fname, ((append ? kFileAppend : kFileTruncate) + | (mkdir_p ? kFileMkDir : kFileCreate) | kFileCreate), 0666)) != 0) { semsg(_("E482: Can't open file %s for writing: %s"), fname, os_strerror(error)); -- cgit From 42e44d6d334bda8b97afe9e34a819ab293e5e10a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 7 Nov 2022 10:26:54 +0800 Subject: vim-patch:8.2.3751: cannot assign a lambda to an option that takes a function Problem: Cannot assign a lambda to an option that takes a function. Solution: Automatically convert the lambda to a string. (Yegappan Lakshmanan, closes vim/vim#9286) https://github.com/vim/vim/commit/6409553b6e3b4de4e1d72b8ee5445595214581ff Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/vars.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 139e7ed66b..6c4d33df89 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -560,8 +560,6 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo { char *arg_end = NULL; int len; - int opt_flags; - char *tofree = NULL; // ":let $VAR = expr": Set environment variable. if (*arg == '$') { @@ -582,12 +580,12 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo && vim_strchr(endchars, *skipwhite(arg)) == NULL) { emsg(_(e_letunexp)); } else if (!check_secure()) { + char *tofree = NULL; const char c1 = name[len]; name[len] = NUL; const char *p = tv_get_string_chk(tv); if (p != NULL && op != NULL && *op == '.') { char *s = vim_getenv(name); - if (s != NULL) { tofree = concat_str(s, p); p = (const char *)tofree; @@ -611,7 +609,8 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo return NULL; } // Find the end of the name. - char *const p = (char *)find_option_end((const char **)&arg, &opt_flags); + int scope; + char *const p = (char *)find_option_end((const char **)&arg, &scope); if (p == NULL || (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)) { @@ -623,11 +622,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo char *stringval = NULL; const char *s = NULL; bool failed = false; + uint32_t opt_p_flags; + char *tofree = NULL; const char c1 = *p; *p = NUL; - opt_type = get_option_value(arg, &numval, &stringval, opt_flags); + opt_type = get_option_value(arg, &numval, &stringval, &opt_p_flags, scope); if (opt_type == gov_bool || opt_type == gov_number || opt_type == gov_hidden_bool @@ -636,8 +637,13 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo n = (long)tv_get_number(tv); } - // Avoid setting a string option to the text "v:false" or similar. - if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { + if ((opt_p_flags & P_FUNC) && tv_is_func(*tv)) { + // If the option can be set to a function reference or a lambda + // and the passed value is a function reference, then convert it to + // the name (string) of the function reference. + s = tofree = encode_tv2string(tv, NULL); + } else if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) { + // Avoid setting a string option to the text "v:false" or similar. s = tv_get_string_chk(tv); } @@ -674,7 +680,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo if (!failed) { if (opt_type != gov_string || s != NULL) { - char *err = set_option_value(arg, n, s, opt_flags); + char *err = set_option_value(arg, n, s, scope); arg_end = p; if (err != NULL) { emsg(_(err)); @@ -685,6 +691,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo } *p = c1; xfree(stringval); + xfree(tofree); } // ":let @r = expr": Set register contents. } else if (*arg == '@') { -- cgit From d7bd7f13a8f026b8b95fdc49b4754f6199105891 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 7 Nov 2022 11:04:33 +0800 Subject: vim-patch:8.2.3756: might crash when callback is not valid Problem: might crash when callback is not valid. Solution: Check for valid callback. (Yegappan Lakshmanan, closes vim/vim#9293) https://github.com/vim/vim/commit/4dc24eb5adbcc76838fae1e900936dd230209d96 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index d07cfe0bd9..cc21bf56ca 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1394,7 +1394,7 @@ func_call_skip_call: } /// call the 'callback' function and return the result as a number. -/// Returns -1 when calling the function fails. Uses argv[0] to argv[argc - 1] +/// Returns -2 when calling the function fails. Uses argv[0] to argv[argc - 1] /// for the function arguments. argv[argc] should have type VAR_UNKNOWN. /// /// @param argcount number of "argvars" @@ -1403,7 +1403,7 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv { typval_T rettv; if (!callback_call(callback, argcount, argvars, &rettv)) { - return -1; + return -2; } varnumber_T retval = tv_get_number_chk(&rettv, NULL); -- cgit From bdb98de2d16ce7185a0f53740e06511904fdd814 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 7 Nov 2022 10:21:44 +0000 Subject: refactor: more clint (#20910) --- src/nvim/eval/executor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 0e0d0fe696..e253098df5 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -122,8 +122,8 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons break; } const float_T f = (tv2->v_type == VAR_FLOAT - ? tv2->vval.v_float - : (float_T)tv_get_number(tv2)); + ? tv2->vval.v_float + : (float_T)tv_get_number(tv2)); switch (*op) { case '+': tv1->vval.v_float += f; break; -- cgit From 849394e4e26f487586761a3640475c27ceca30b9 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sun, 13 Nov 2022 08:29:05 +0800 Subject: vim-patch:9.0.0863: col() and charcol() only work for the current window (#21038) Problem: col() and charcol() only work for the current window. Solution: Add an optional winid argument. (Yegappan Lakshmanan, closes vim/vim#11466, closes vim/vim#11461) https://github.com/vim/vim/commit/4c8d2f02b3ce037bbe1d5ee12887e343c6bde88f Cherry-pick test_functions.vim change from patch 8.2.0633. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 29 ++++++++++++++++++++++++++++- src/nvim/eval/typval.c | 13 +++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index be48dc7732..8acdc3256c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -846,9 +846,32 @@ static void f_char2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// otherwise the byte index of the column. static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) { + if (tv_check_for_string_or_list_arg(argvars, 0) == FAIL + || tv_check_for_opt_number_arg(argvars, 1) == FAIL) { + return; + } + + switchwin_T switchwin; + bool winchanged = false; + + if (argvars[1].v_type != VAR_UNKNOWN) { + // use the window specified in the second argument + tabpage_T *tp; + win_T *wp = win_id2wp_tp((int)tv_get_number(&argvars[1]), &tp); + if (wp == NULL || tp == NULL) { + return; + } + + if (switch_win_noblock(&switchwin, wp, tp, true) != OK) { + return; + } + + check_cursor(); + winchanged = true; + } + colnr_T col = 0; int fnum = curbuf->b_fnum; - pos_T *fp = var2fpos(&argvars[0], false, &fnum, charcol); if (fp != NULL && fnum == curbuf->b_fnum) { if (fp->col == MAXCOL) { @@ -876,6 +899,10 @@ static void get_col(typval_T *argvars, typval_T *rettv, bool charcol) } } rettv->vval.v_number = col; + + if (winchanged) { + restore_win_noblock(&switchwin, true); + } } /// "charcol()" function diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index e09fda173b..7e4066adb7 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -46,6 +46,8 @@ static char e_non_empty_string_required_for_argument_nr[] = N_("E1175: Non-empty string 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"); bool tv_in_free_unref_items = false; @@ -3880,6 +3882,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 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 +{ + if (args[idx].v_type != VAR_STRING && args[idx].v_type != VAR_LIST) { + semsg(_(e_string_or_list_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 66360675cf4d091b7460e4a8e1435c13216c1929 Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sun, 11 Sep 2022 17:12:44 +0200 Subject: build: allow IWYU to fix includes for all .c files Allow Include What You Use to remove unnecessary includes and only include what is necessary. This helps with reducing compilation times and makes it easier to visualise which dependencies are actually required. Work on https://github.com/neovim/neovim/issues/549, but doesn't close it since this only works fully for .c files and not headers. --- src/nvim/eval/decode.c | 19 ++++++++++++---- src/nvim/eval/encode.c | 11 ++++++--- src/nvim/eval/encode.h | 5 +++- src/nvim/eval/executor.c | 10 +++++++- src/nvim/eval/funcs.c | 59 ++++++++++++++++++++++++++++++++++++++---------- src/nvim/eval/funcs.h | 5 ++++ src/nvim/eval/gc.c | 5 ++-- src/nvim/eval/gc.h | 1 + src/nvim/eval/typval.c | 3 ++- src/nvim/eval/typval.h | 5 ++++ src/nvim/eval/userfunc.c | 24 ++++++++++++++++++-- src/nvim/eval/userfunc.h | 10 ++++++++ src/nvim/eval/vars.c | 22 ++++++++++++++++-- src/nvim/eval/vars.h | 2 +- 14 files changed, 152 insertions(+), 29 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c index f677148e08..cd1479f150 100644 --- a/src/nvim/eval/decode.c +++ b/src/nvim/eval/decode.c @@ -1,20 +1,31 @@ // 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 +#include #include +#include +#include +#include #include "klib/kvec.h" #include "nvim/ascii.h" -#include "nvim/charset.h" // vim_str2nr +#include "nvim/charset.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" -#include "nvim/globals.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/hashtab.h" #include "nvim/macros.h" +#include "nvim/mbyte.h" +#include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/vim.h" // OK, FAIL +#include "nvim/types.h" +#include "nvim/vim.h" /// Helper structure for container_struct typedef struct { diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 82c9f04f8f..3e002ef52c 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -10,23 +10,28 @@ #include #include #include -#include +#include #include +#include +#include #include "klib/kvec.h" +#include "msgpack/pack.h" #include "nvim/ascii.h" -#include "nvim/buffer_defs.h" -#include "nvim/charset.h" // vim_isprintc() #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/typval.h" #include "nvim/eval/typval_encode.h" #include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/hashtab.h" #include "nvim/macros.h" #include "nvim/math.h" #include "nvim/mbyte.h" #include "nvim/memory.h" #include "nvim/message.h" +#include "nvim/strings.h" +#include "nvim/types.h" #include "nvim/vim.h" // For _() const char *const encode_bool_var_names[] = { diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index c0c98e0990..5c217abb5a 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -2,11 +2,14 @@ #define NVIM_EVAL_ENCODE_H #include +#include #include #include "nvim/eval.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/garray.h" -#include "nvim/vim.h" // For STRLEN +#include "nvim/vim.h" /// Convert VimL value to msgpack string /// diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index e253098df5..86d6063b01 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -1,15 +1,23 @@ // 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 "nvim/eval.h" #include "nvim/eval/executor.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/message.h" +#include "nvim/strings.h" +#include "nvim/types.h" #include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "eval/executor.c.generated.h" +# include "eval/executor.c.generated.h" // IWYU pragma: export #endif char *e_listidx = N_("E684: list index out of range: %" PRId64); diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8acdc3256c..244802a183 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1,25 +1,42 @@ // 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 +#include +#include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "auto/config.h" #include "nvim/api/private/converter.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/dispatch.h" #include "nvim/api/private/helpers.h" #include "nvim/api/vim.h" -#include "nvim/arglist.h" #include "nvim/ascii.h" #include "nvim/assert.h" +#include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" -#include "nvim/cmdhist.h" #include "nvim/context.h" #include "nvim/cursor.h" #include "nvim/diff.h" -#include "nvim/digraph.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/decode.h" @@ -29,54 +46,71 @@ #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" +#include "nvim/event/loop.h" +#include "nvim/event/multiqueue.h" +#include "nvim/event/process.h" +#include "nvim/event/time.h" #include "nvim/ex_cmds.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" #include "nvim/file_search.h" #include "nvim/fileio.h" -#include "nvim/fold.h" +#include "nvim/garray.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" #include "nvim/globals.h" +#include "nvim/grid_defs.h" +#include "nvim/hashtab.h" +#include "nvim/highlight_defs.h" #include "nvim/highlight_group.h" #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/input.h" -#include "nvim/insexpand.h" +#include "nvim/keycodes.h" #include "nvim/lua/executor.h" #include "nvim/macros.h" -#include "nvim/mapping.h" +#include "nvim/main.h" #include "nvim/mark.h" -#include "nvim/match.h" #include "nvim/math.h" +#include "nvim/mbyte.h" +#include "nvim/memfile_defs.h" #include "nvim/memline.h" +#include "nvim/memory.h" #include "nvim/menu.h" +#include "nvim/message.h" #include "nvim/mouse.h" #include "nvim/move.h" #include "nvim/msgpack_rpc/channel.h" +#include "nvim/msgpack_rpc/channel_defs.h" #include "nvim/msgpack_rpc/server.h" +#include "nvim/normal.h" #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/optionstr.h" #include "nvim/os/dl.h" +#include "nvim/os/fileio.h" +#include "nvim/os/fs_defs.h" +#include "nvim/os/os.h" +#include "nvim/os/pty_process.h" #include "nvim/os/shell.h" +#include "nvim/os/stdpaths_defs.h" +#include "nvim/os/time.h" #include "nvim/path.h" #include "nvim/plines.h" #include "nvim/popupmenu.h" +#include "nvim/pos.h" #include "nvim/profile.h" -#include "nvim/quickfix.h" #include "nvim/regexp.h" #include "nvim/runtime.h" -#include "nvim/screen.h" #include "nvim/search.h" #include "nvim/sha256.h" -#include "nvim/sign.h" #include "nvim/spell.h" #include "nvim/spellsuggest.h" #include "nvim/state.h" +#include "nvim/strings.h" #include "nvim/syntax.h" #include "nvim/tag.h" -#include "nvim/testing.h" #include "nvim/ui.h" #include "nvim/undo.h" #include "nvim/version.h" @@ -105,6 +139,7 @@ typedef enum { PRAGMA_DIAG_PUSH_IGNORE_MISSING_PROTOTYPES PRAGMA_DIAG_PUSH_IGNORE_IMPLICIT_FALLTHROUGH # include "funcs.generated.h" + PRAGMA_DIAG_POP PRAGMA_DIAG_POP #endif diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h index adff0b2441..1ae031a952 100644 --- a/src/nvim/eval/funcs.h +++ b/src/nvim/eval/funcs.h @@ -1,9 +1,14 @@ #ifndef NVIM_EVAL_FUNCS_H #define NVIM_EVAL_FUNCS_H +#include +#include + #include "nvim/api/private/dispatch.h" #include "nvim/buffer_defs.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/types.h" /// Prototype of C function that implements VimL function typedef void (*VimLFunc)(typval_T *args, typval_T *rvar, EvalFuncData data); diff --git a/src/nvim/eval/gc.c b/src/nvim/eval/gc.c index 633e6abacf..6a54c4ddc1 100644 --- a/src/nvim/eval/gc.c +++ b/src/nvim/eval/gc.c @@ -1,11 +1,12 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com +#include + #include "nvim/eval/gc.h" -#include "nvim/eval/typval.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "eval/gc.c.generated.h" +# include "eval/gc.c.generated.h" // IWYU pragma: export #endif /// Head of list of all dictionaries diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h index c2e862e469..3185750c3b 100644 --- a/src/nvim/eval/gc.h +++ b/src/nvim/eval/gc.h @@ -2,6 +2,7 @@ #define NVIM_EVAL_GC_H #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" extern dict_T *gc_first_dict; extern list_T *gc_first_list; diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7e4066adb7..f38e07f09d 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -28,9 +28,9 @@ #include "nvim/lua/executor.h" #include "nvim/macros.h" #include "nvim/mbyte.h" +#include "nvim/mbyte_defs.h" #include "nvim/memory.h" #include "nvim/message.h" -#include "nvim/os/fileio.h" #include "nvim/os/input.h" #include "nvim/pos.h" #include "nvim/types.h" @@ -3150,6 +3150,7 @@ static inline void _nothing_conv_dict_end(typval_T *const tv, dict_T **const dic #define TYPVAL_ENCODE_FIRST_ARG_TYPE const void *const #define TYPVAL_ENCODE_FIRST_ARG_NAME ignored #include "nvim/eval/typval_encode.c.h" + #undef TYPVAL_ENCODE_SCOPE #undef TYPVAL_ENCODE_NAME #undef TYPVAL_ENCODE_FIRST_ARG_TYPE diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 6757d058ef..8ff7f7f43a 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -4,14 +4,19 @@ #include #include #include +#include #include #include "nvim/eval/typval_defs.h" #include "nvim/func_attr.h" +#include "nvim/garray.h" #include "nvim/gettext.h" +#include "nvim/hashtab.h" +#include "nvim/lib/queue.h" #include "nvim/macros.h" #include "nvim/mbyte_defs.h" #include "nvim/message.h" +#include "nvim/types.h" #ifdef LOG_LIST_ACTIONS # include "nvim/memory.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c01bd1e3df..2210a61d7c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -3,28 +3,48 @@ // User defined function support +#include +#include +#include +#include +#include +#include + +#include "lauxlib.h" #include "nvim/ascii.h" +#include "nvim/autocmd.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/debugger.h" -#include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" +#include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" #include "nvim/ex_getln.h" -#include "nvim/fileio.h" #include "nvim/getchar.h" +#include "nvim/gettext.h" #include "nvim/globals.h" #include "nvim/insexpand.h" +#include "nvim/keycodes.h" #include "nvim/lua/executor.h" +#include "nvim/macros.h" +#include "nvim/mbyte.h" +#include "nvim/memline_defs.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/option_defs.h" #include "nvim/os/input.h" +#include "nvim/path.h" #include "nvim/profile.h" #include "nvim/regexp.h" #include "nvim/runtime.h" #include "nvim/search.h" +#include "nvim/strings.h" #include "nvim/ui.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index ca09c2a6ec..1255f86103 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -1,8 +1,18 @@ #ifndef NVIM_EVAL_USERFUNC_H #define NVIM_EVAL_USERFUNC_H +#include +#include + #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/ex_cmds_defs.h" +#include "nvim/garray.h" +#include "nvim/hashtab.h" +#include "nvim/pos.h" +#include "nvim/types.h" + +struct funccal_entry; // From user function to hashitem and back. #define UF2HIKEY(fp) ((fp)->uf_name) diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 3a625df988..54ff0a53d3 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -3,24 +3,42 @@ // eval/vars.c: functions for dealing with variables +#include +#include +#include +#include +#include +#include + #include "nvim/ascii.h" #include "nvim/autocmd.h" -#include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/charset.h" #include "nvim/drawscreen.h" #include "nvim/eval.h" #include "nvim/eval/encode.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" #include "nvim/ex_cmds.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" #include "nvim/ex_eval.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/hashtab.h" +#include "nvim/macros.h" +#include "nvim/memory.h" +#include "nvim/message.h" #include "nvim/ops.h" #include "nvim/option.h" -#include "nvim/screen.h" +#include "nvim/os/os.h" #include "nvim/search.h" +#include "nvim/strings.h" +#include "nvim/types.h" +#include "nvim/vim.h" #include "nvim/window.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/eval/vars.h b/src/nvim/eval/vars.h index 73efc4938a..b87c9d62cb 100644 --- a/src/nvim/eval/vars.h +++ b/src/nvim/eval/vars.h @@ -1,7 +1,7 @@ #ifndef NVIM_EVAL_VARS_H #define NVIM_EVAL_VARS_H -#include "nvim/ex_cmds_defs.h" // For exarg_T +#include "nvim/ex_cmds_defs.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/vars.h.generated.h" -- cgit From a4114f16bf0867bc93ef2c1cc47f01383c9820ee Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 18 Nov 2022 22:19:14 +0800 Subject: vim-patch:8.2.0469: Vim9: no error for missing ] after list Problem: Vim9: no error for missing ] after list. Solution: Add error message. Add more tests. https://github.com/vim/vim/commit/ee619e5bc0992e818f2d9540b093b769b9c27651 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 2210a61d7c..893a4c77eb 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -297,6 +297,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) e = (char_u *)(*arg); *arg = skipwhite(*arg); if (**arg != '}') { + semsg(_("E451: Expected }: %s"), *arg); goto errret; } (*arg)++; -- cgit From 92e51d7e4b79913434c7b74a275babcf65098b97 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 19 Nov 2022 12:47:44 +0800 Subject: vim-patch:8.2.5167: get(Fn, 'name') on funcref returns special byte code (#21112) Problem: get(Fn, 'name') on funcref returns special byte code. Solution: Use the printable name. https://github.com/vim/vim/commit/1ae8c262df7083dfb4b41485508951c50eccc84c Cherry-pick printable_func_name() from patch 8.2.0149. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 12 ++++++++---- src/nvim/eval/userfunc.c | 5 +++++ 2 files changed, 13 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 244802a183..12568ec965 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2528,13 +2528,17 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *const what = tv_get_string(&argvars[1]); if (strcmp(what, "func") == 0 || strcmp(what, "name") == 0) { + const char *name = (const char *)partial_name(pt); rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); - const char *const n = (const char *)partial_name(pt); - assert(n != NULL); - rettv->vval.v_string = xstrdup(n); + assert(name != NULL); if (rettv->v_type == VAR_FUNC) { - func_ref((char_u *)rettv->vval.v_string); + func_ref((char_u *)name); } + if (*what == 'n' && pt->pt_name == NULL && pt->pt_func != NULL) { + // use instead of the byte code + name = (const char *)printable_func_name(pt->pt_func); + } + rettv->vval.v_string = xstrdup(name); } else if (strcmp(what, "dict") == 0) { what_is_dict = true; if (pt->pt_dict != NULL) { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 893a4c77eb..ae867cb716 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1652,6 +1652,11 @@ theend: return ret; } +char_u *printable_func_name(ufunc_T *fp) +{ + return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; +} + /// List the head of the function: "name(arg1, arg2)". /// /// @param[in] fp Function pointer. -- cgit From 40f3f75867bf03abfd90e0389a38197a00d37af1 Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 12568ec965..e49b0fd14c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2343,13 +2343,13 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) { xfree(fresult); } - fresult = find_file_in_path_option(first ? (char_u *)fname : NULL, - first ? strlen(fname) : 0, - 0, first, path, - find_what, (char_u *)curbuf->b_ffname, - (find_what == FINDFILE_DIR - ? (char_u *)"" - : (char_u *)curbuf->b_p_sua)); + fresult = (char_u *)find_file_in_path_option(first ? (char *)fname : NULL, + first ? strlen(fname) : 0, + 0, first, (char *)path, + find_what, curbuf->b_ffname, + (find_what == FINDFILE_DIR + ? "" + : curbuf->b_p_sua)); first = false; if (fresult != NULL && rettv->v_type == VAR_LIST) { -- cgit From 9b768752353d3cf99c6cb02e6c1f9d70c029ecb6 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 22 Nov 2022 06:52:21 +0800 Subject: vim-patch:9.0.0916: getbufline() is inefficient for getting a single line Problem: getbufline() is inefficient for getting a single line. Solution: Add getbufoneline(). https://github.com/vim/vim/commit/ce30ccc06af7f2c03762e5b18dde37b26ea6ec42 Cherry-pick part of usr_41.txt from patch 8.1.1628. Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 12568ec965..8666aa4f35 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -2671,8 +2671,9 @@ static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retli } } -/// "getbufline()" function -static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +/// @param retlist true: "getbufline()" function +/// false: "getbufoneline()" function +static void getbufline(typval_T *argvars, typval_T *rettv, bool retlist) { const int did_emsg_before = did_emsg; buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); @@ -2684,7 +2685,19 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ? lnum : tv_get_lnum_buf(&argvars[2], buf)); - get_buffer_lines(buf, lnum, end, true, rettv); + get_buffer_lines(buf, lnum, end, retlist, rettv); +} + +/// "getbufline()" function +static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + getbufline(argvars, rettv, true); +} + +/// "getbufoneline()" function +static void f_getbufoneline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + getbufline(argvars, rettv, false); } /// "getchangelist()" function -- cgit From 7c10774860b4238090f0d36a26203080542ef1ac Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 22 Nov 2022 01:09:33 +0100 Subject: refactor: remove old TODO comments that aren't relevant anymore (#21144) --- src/nvim/eval/userfunc.c | 2 -- src/nvim/eval/vars.c | 16 ---------------- 2 files changed, 18 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index ae867cb716..42f78422cb 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2960,8 +2960,6 @@ void ex_return(exarg_T *eap) } } -// TODO(ZyX-I): move to eval/ex_cmds - /// ":1,25call func(arg1, arg2)" function call. void ex_call(exarg_T *eap) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 54ff0a53d3..733bc3ac2d 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -558,8 +558,6 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first) return arg; } -// TODO(ZyX-I): move to eval/ex_cmds - /// Set one item of `:let var = expr` or `:let [v1, v2] = list` to its value /// /// @param[in] arg Start of the variable name. @@ -769,8 +767,6 @@ void ex_unlet(exarg_T *eap) ex_unletlock(eap, eap->arg, 0, do_unlet_var); } -// TODO(ZyX-I): move to eval/ex_cmds - /// ":lockvar" and ":unlockvar" commands void ex_lockvar(exarg_T *eap) { @@ -787,8 +783,6 @@ void ex_lockvar(exarg_T *eap) ex_unletlock(eap, arg, deep, do_lock_var); } -// TODO(ZyX-I): move to eval/ex_cmds - /// Common parsing logic for :unlet, :lockvar and :unlockvar. /// /// Invokes `callback` afterwards if successful and `eap->skip == false`. @@ -853,8 +847,6 @@ static void ex_unletlock(exarg_T *eap, char *argstart, int deep, ex_unletlock_ca eap->nextcmd = check_nextcmd(arg); } -// TODO(ZyX-I): move to eval/ex_cmds - /// Unlet a variable indicated by `lp`. /// /// @param[in] lp The lvalue. @@ -944,8 +936,6 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ return ret; } -// TODO(ZyX-I): move to eval/ex_cmds - /// unlet a variable /// /// @param[in] name Variable name to unlet. @@ -1016,8 +1006,6 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit) return FAIL; } -// TODO(ZyX-I): move to eval/ex_cmds - /// Lock or unlock variable indicated by `lp`. /// /// Locks if `eap->cmdidx == CMD_lockvar`, unlocks otherwise. @@ -1463,8 +1451,6 @@ bool var_check_fixed(const int flags, const char *name, size_t name_len) return false; } -// TODO(ZyX-I): move to eval/expressions - /// Check if name is a valid name to assign funcref to /// /// @param[in] name Possible function/funcref name. @@ -1493,8 +1479,6 @@ bool var_wrong_func_name(const char *const name, const bool new_var) return false; } -// TODO(ZyX-I): move to eval/expressions - /// Check if a variable name is valid /// /// @param[in] varname Variable name to check. -- cgit From 4571ba4d0a5234408e544c3a98f107688a792f0d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 23 Nov 2022 09:54:48 +0800 Subject: vim-patch:partial:9.0.0917: the WinScrolled autocommand event is not enough (#21161) Problem: The WinScrolled autocommand event is not enough. Solution: Add WinResized and provide information about what changed. (closes vim/vim#11576) https://github.com/vim/vim/commit/35fc61cb5b5eba8bbb9d8f0700332fbab38f40ca Omit "func_name" comment in tv_dict_extend(): Vim9 script only. Skip layout locking and E1312. Skip list_alloc_with_items() and list_set_item(). Since this overrides remaining changes in patch 9.0.0913, that patch can now be marked as fully ported: vim-patch:9.0.0913: only change in current window triggers the WinScrolled event N/A patches for version.c: vim-patch:9.0.0919: build failure with tiny features Problem: Build failure with tiny features. Solution: Adjust #ifdef's. https://github.com/vim/vim/commit/9c5b7cb4cf67c64648a324e9dfd1e17d793335a4 Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index f38e07f09d..47c3551a56 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2446,10 +2446,10 @@ void tv_dict_clear(dict_T *const d) /// /// @param d1 Dictionary to extend. /// @param[in] d2 Dictionary to extend with. -/// @param[in] action "error", "force", "keep": -/// +/// @param[in] action "error", "force", "move", "keep": /// e*, including "error": duplicate key gives an error. /// f*, including "force": duplicate d2 keys override d1. +/// m*, including "move": move items instead of copying. /// other, including "keep": duplicate d2 keys ignored. void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action) FUNC_ATTR_NONNULL_ALL @@ -2458,19 +2458,31 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action const char *const arg_errmsg = _("extend() argument"); const size_t arg_errmsg_len = strlen(arg_errmsg); - TV_DICT_ITER(d2, di2, { + if (*action == 'm') { + hash_lock(&d2->dv_hashtab); // don't rehash on hash_remove() + } + + 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); // 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)) { break; } if (di1 == NULL) { - 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); + if (*action == 'm') { + // cheap way to move a dict item from "d2" to "d1" + dictitem_T *const new_di = di2; + tv_dict_add(d1, new_di); + hash_remove(&d2->dv_hashtab, hi2); + tv_dict_watcher_notify(d1, (const char *)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); + } } } else if (*action == 'e') { semsg(_("E737: Key already exists: %s"), di2->di_key); @@ -2501,6 +2513,10 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action } } }); + + if (*action == 'm') { + hash_unlock(&d2->dv_hashtab); + } } /// Compare two dictionaries -- cgit From 65d95fa41530bfc85ba5dd6ae10201e6b788e4a3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 23 Nov 2022 19:56:50 +0800 Subject: vim-patch:9.0.0926: Coverity warns for not using return value of dict_add() Problem: Coverity warns for not using return value of dict_add(). Solution: When dict_add() fails then don't call hash_remove(). https://github.com/vim/vim/commit/bc222152d8dea252aa5f1fa24b5536ed269feb92 N/A patches for version.c: vim-patch:9.0.0927: Coverity warns for using a NULL pointer Problem: Coverity warns for using a NULL pointer. Solution: Check for memory allocaion failure. https://github.com/vim/vim/commit/96cbbe29debba25d7eec8d01955c5ac01f5c420d Co-authored-by: Bram Moolenaar --- src/nvim/eval/typval.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 47c3551a56..25b2a20bac 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2471,11 +2471,13 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action } if (di1 == NULL) { if (*action == 'm') { - // cheap way to move a dict item from "d2" to "d1" + // Cheap way to move a dict item from "d2" to "d1". + // If dict_add() fails then "d2" won't be empty. dictitem_T *const new_di = di2; - tv_dict_add(d1, new_di); - hash_remove(&d2->dv_hashtab, hi2); - tv_dict_watcher_notify(d1, (const char *)new_di->di_key, &new_di->di_tv, NULL); + 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); + } } else { dictitem_T *const new_di = tv_dict_item_copy(di2); if (tv_dict_add(d1, new_di) == FAIL) { -- cgit From 5bdd787a7a2274d802479498ccd1d1f0c4fc589b Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 25 Nov 2022 10:35:20 +0800 Subject: vim-patch:8.2.2466: max() and min() can give many error messages Problem: Max() and min() can give many error messages. Solution: Bail out at the first error. (closes vim/vim#1039, closes vim/vim#7778) https://github.com/vim/vim/commit/ab65fc77c5389f7d3f788bbdc3d931561feab131 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8ab1178b17..96c483ea75 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5245,7 +5245,7 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool TV_LIST_ITER_CONST(tv->vval.v_list, li, { const varnumber_T i = tv_get_number_chk(TV_LIST_ITEM_TV(li), &error); if (error) { - return; + return; // type error; errmsg already given } if (domax ? i > n : i < n) { n = i; @@ -5258,7 +5258,7 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool TV_DICT_ITER(tv->vval.v_dict, di, { const varnumber_T i = tv_get_number_chk(&di->di_tv, &error); if (error) { - return; + return; // type error; errmsg already given } if (domax ? i > n : i < n) { n = i; @@ -5268,6 +5268,7 @@ static void max_min(const typval_T *const tv, typval_T *const rettv, const bool semsg(_(e_listdictarg), domax ? "max()" : "min()"); return; } + rettv->vval.v_number = n; } -- cgit From bd22585061b66d7f71d4832b4a81e950b3c9d19d Mon Sep 17 00:00:00 2001 From: Dundar Göc Date: Fri, 26 Aug 2022 23:11:25 +0200 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/encode.c | 6 +++--- src/nvim/eval/encode.h | 2 +- src/nvim/eval/funcs.c | 3 +-- src/nvim/eval/typval.c | 6 +++--- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 32 ++++++++++++++++---------------- src/nvim/eval/vars.c | 4 ++-- 7 files changed, 27 insertions(+), 28 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 3e002ef52c..b7ef109f06 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -136,9 +136,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, typval_T key_tv = { .v_type = VAR_STRING, .vval = { .v_string = - (char *)(v.data.d.hi == - NULL ? v.data.d.dict->dv_hashtab.ht_array : (v.data.d.hi - - 1))->hi_key }, + (v.data.d.hi == + NULL ? v.data.d.dict->dv_hashtab.ht_array : (v.data.d.hi - + 1))->hi_key }, }; char *const key = encode_tv2string(&key_tv, NULL); vim_snprintf((char *)IObuff, IOSIZE, key_msg, key); diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index 5c217abb5a..e66dab1cff 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -47,7 +47,7 @@ static inline ListReaderState encode_init_lrstate(const list_T *const list) .offset = 0, .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL ? 0 - : STRLEN(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)), + : strlen(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)), }; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 96c483ea75..67da5803d9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7996,8 +7996,7 @@ static void f_shellescape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const bool do_special = non_zero_arg(&argvars[1]); rettv->vval.v_string = - (char *)vim_strsave_shellescape((const char_u *)tv_get_string(&argvars[0]), do_special, - do_special); + vim_strsave_shellescape(tv_get_string(&argvars[0]), do_special, do_special); rettv->v_type = VAR_STRING; } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 25b2a20bac..1de268a9d8 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2098,7 +2098,7 @@ 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(var->di_key) + strlen(str) + strlen("=") + 1; + size_t len = strlen((char *)var->di_key) + strlen(str) + strlen("=") + 1; env[i] = xmalloc(len); snprintf(env[i], len, "%s=%s", (char *)var->di_key, str); i++; @@ -2230,7 +2230,7 @@ int tv_dict_add(dict_T *const d, dictitem_T *const item) if (tv_dict_wrong_func_name(d, &item->di_tv, (const char *)item->di_key)) { return FAIL; } - return hash_add(&d->dv_hashtab, item->di_key); + return hash_add(&d->dv_hashtab, (char *)item->di_key); } /// Add a list entry to dictionary @@ -2586,7 +2586,7 @@ dict_T *tv_dict_copy(const vimconv_T *const conv, dict_T *const orig, const bool if (conv == NULL || conv->vc_type == CONV_NONE) { new_di = tv_dict_item_alloc((const char *)di->di_key); } else { - size_t len = STRLEN(di->di_key); + size_t len = strlen((char *)di->di_key); char *const key = (char *)string_convert(conv, (char *)di->di_key, &len); if (key == NULL) { new_di = tv_dict_item_alloc_len((const char *)di->di_key, len); diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 1c0a438751..f025f21cf7 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -339,7 +339,7 @@ struct ufunc { funccall_T *uf_scoped; ///< l: local variables for closure char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with ///< "" as a string, otherwise NULL - char_u uf_name[]; ///< Name of function (actual size equals name); + char uf_name[]; ///< Name of function (actual size equals name); ///< can start with 123_ ///< ( is K_SPECIAL KS_EXTRA KE_SNR) }; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 42f78422cb..7f0ac06f60 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -595,7 +595,7 @@ ufunc_T *find_func(const char_u *name) /// Takes care of script-local function names. static void cat_func_name(char_u *buf, ufunc_T *fp) { - if (fp->uf_name[0] == K_SPECIAL) { + if ((uint8_t)fp->uf_name[0] == K_SPECIAL) { STRCPY(buf, ""); STRCAT(buf, fp->uf_name + 3); } else { @@ -610,7 +610,7 @@ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) STRCPY(v->di_key, name); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&dp->dv_hashtab, v->di_key); + hash_add(&dp->dv_hashtab, (char *)v->di_key); v->di_tv.v_type = VAR_NUMBER; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_number = nr; @@ -906,7 +906,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "self"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_vars.dv_hashtab, v->di_key); + hash_add(&fc->l_vars.dv_hashtab, (char *)v->di_key); v->di_tv.v_type = VAR_DICT; v->di_tv.v_lock = VAR_UNLOCKED; v->di_tv.vval.v_dict = selfdict; @@ -932,7 +932,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett STRCPY(name, "000"); #endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; - hash_add(&fc->l_avars.dv_hashtab, v->di_key); + hash_add(&fc->l_avars.dv_hashtab, (char *)v->di_key); v->di_tv.v_type = VAR_LIST; v->di_tv.v_lock = VAR_FIXED; v->di_tv.vval.v_list = &fc->l_varlist; @@ -1010,9 +1010,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett // Named arguments can be accessed without the "a:" prefix in lambda // expressions. Add to the l: dict. tv_copy(&v->di_tv, &v->di_tv); - hash_add(&fc->l_vars.dv_hashtab, v->di_key); + hash_add(&fc->l_vars.dv_hashtab, (char *)v->di_key); } else { - hash_add(&fc->l_avars.dv_hashtab, v->di_key); + hash_add(&fc->l_avars.dv_hashtab, (char *)v->di_key); } if (ai >= 0 && ai < MAX_FUNC_ARGS) { @@ -1318,7 +1318,7 @@ void free_all_functions(void) // Only free functions that are not refcounted, those are // supposed to be freed when no longer referenced. fp = HI2UF(hi); - if (func_name_refcount(fp->uf_name)) { + if (func_name_refcount((char_u *)fp->uf_name)) { skipped++; } else { used = func_hashtab.ht_used; @@ -1344,7 +1344,7 @@ void free_all_functions(void) // Only free functions that are not refcounted, those are // supposed to be freed when no longer referenced. fp = HI2UF(hi); - if (func_name_refcount(fp->uf_name)) { + if (func_name_refcount((char_u *)fp->uf_name)) { skipped++; } else { func_free(fp); @@ -1654,7 +1654,7 @@ theend: char_u *printable_func_name(ufunc_T *fp) { - return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; + return fp->uf_name_exp != NULL ? fp->uf_name_exp : (char_u *)fp->uf_name; } /// List the head of the function: "name(arg1, arg2)". @@ -1970,7 +1970,7 @@ static void list_functions(regmatch_T *regmatch) if ((fp->uf_flags & FC_DEAD) == 0 && (regmatch == NULL ? (!message_filtered((char *)fp->uf_name) - && !func_name_refcount(fp->uf_name)) + && !func_name_refcount((char_u *)fp->uf_name)) : (!isdigit(*fp->uf_name) && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { list_func_head(fp, false, false); @@ -2590,7 +2590,7 @@ void ex_function(exarg_T *eap) set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); - hi->hi_key = UF2HIKEY(fp); + hi->hi_key = (char *)UF2HIKEY(fp); } else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL) { xfree(fp); goto erret; @@ -2718,7 +2718,7 @@ char *get_user_func_name(expand_T *xp, int idx) return ""; // don't show dict and lambda functions } - if (STRLEN(fp->uf_name) + 4 >= IOSIZE) { + if (strlen(fp->uf_name) + 4 >= IOSIZE) { return (char *)fp->uf_name; // Prevent overflow. } @@ -2802,7 +2802,7 @@ void ex_delfunction(exarg_T *eap) // it and the refcount is more than one, it should be kept. // A numbered function or lambda should be kept if the refcount is // one or more. - if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1)) { + if (fp->uf_refcount > (func_name_refcount((char_u *)fp->uf_name) ? 0 : 1)) { // Function is still referenced somewhere. Don't free it but // do remove it from the hashtable. if (func_remove(fp)) { @@ -3320,7 +3320,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) /// @return the name of the executed function. char_u *func_name(void *cookie) { - return ((funccall_T *)cookie)->func->uf_name; + return (char_u *)((funccall_T *)cookie)->func->uf_name; } /// @return the address holding the next breakpoint line for a funccall cookie. @@ -3579,7 +3579,7 @@ bool set_ref_in_functions(int copyID) if (!HASHITEM_EMPTY(hi)) { todo--; fp = HI2UF(hi); - if (!func_name_refcount(fp->uf_name) + if (!func_name_refcount((char_u *)fp->uf_name) && set_ref_in_func(NULL, fp, copyID)) { return true; } @@ -3648,5 +3648,5 @@ char_u *register_luafunc(LuaRef ref) hash_add(&func_hashtab, UF2HIKEY(fp)); // coverity[leaked_storage] - return fp->uf_name; + return (char_u *)fp->uf_name; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 733bc3ac2d..2d7df6fde9 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1174,7 +1174,7 @@ void delete_var(hashtab_T *ht, hashitem_T *hi) static void list_one_var(dictitem_T *v, const char *prefix, int *first) { char *const s = encode_tv2echo(&v->di_tv, NULL); - list_one_var_a(prefix, (const char *)v->di_key, (ptrdiff_t)STRLEN(v->di_key), + list_one_var_a(prefix, (const char *)v->di_key, (ptrdiff_t)strlen((char *)v->di_key), v->di_tv.v_type, (s == NULL ? "" : s), first); xfree(s); } @@ -1342,7 +1342,7 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, v = xmalloc(sizeof(dictitem_T) + strlen(varname)); STRCPY(v->di_key, varname); - if (hash_add(ht, v->di_key) == FAIL) { + if (hash_add(ht, (char *)v->di_key) == FAIL) { xfree(v); return; } -- cgit From 3b96ccf7d35be90e49029dec76344d3d92ad91dc Mon Sep 17 00:00:00 2001 From: dundargoc Date: Sat, 26 Nov 2022 18:57:46 +0100 Subject: refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 4 ++-- src/nvim/eval/userfunc.c | 34 +++++++++++++++++----------------- src/nvim/eval/vars.c | 6 +++--- 3 files changed, 22 insertions(+), 22 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 67da5803d9..ebe7e0325b 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -173,7 +173,7 @@ char *get_function_name(expand_T *xp, int idx) char_u *name = (char_u *)get_user_func_name(xp, idx); if (name != NULL) { if (*name != NUL && *name != '<' - && STRNCMP("g:", xp->xp_pattern, 2) == 0) { + && strncmp("g:", xp->xp_pattern, 2) == 0) { return cat_prefix_varname('g', (char *)name); } return (char *)name; @@ -9476,7 +9476,7 @@ static void f_tr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int fromlen; for (const char *p = fromstr; *p != NUL; p += fromlen) { fromlen = utfc_ptr2len(p); - if (fromlen == inlen && STRNCMP(in_str, p, inlen) == 0) { + if (fromlen == inlen && strncmp(in_str, p, (size_t)inlen) == 0) { int tolen; for (p = tostr; *p != NUL; p += tolen) { tolen = utfc_ptr2len(p); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 7f0ac06f60..359ce08554 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -118,8 +118,8 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int p++; } if (arg == p || isdigit(*arg) - || (p - arg == 9 && STRNCMP(arg, "firstline", 9) == 0) - || (p - arg == 8 && STRNCMP(arg, "lastline", 8) == 0)) { + || (p - arg == 9 && strncmp(arg, "firstline", 9) == 0) + || (p - arg == 8 && strncmp(arg, "lastline", 8) == 0)) { if (!skip) { semsg(_("E125: Illegal argument: %s"), arg); } @@ -887,7 +887,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett ga_init(&fc->fc_funcs, sizeof(ufunc_T *), 1); func_ptr_ref(fp); - if (STRNCMP(fp->uf_name, "", 8) == 0) { + if (strncmp(fp->uf_name, "", 8) == 0) { islambda = true; } @@ -1846,7 +1846,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa if (name != NULL) { name = xstrdup(name); *pp = (char *)end; - if (STRNCMP(name, "", 5) == 0) { + if (strncmp(name, "", 5) == 0) { // Change "" to the byte sequence. name[0] = (char)K_SPECIAL; name[1] = (char)KS_EXTRA; @@ -2187,16 +2187,16 @@ void ex_function(exarg_T *eap) // find extra arguments "range", "dict", "abort" and "closure" for (;;) { p = skipwhite(p); - if (STRNCMP(p, "range", 5) == 0) { + if (strncmp(p, "range", 5) == 0) { flags |= FC_RANGE; p += 5; - } else if (STRNCMP(p, "dict", 4) == 0) { + } else if (strncmp(p, "dict", 4) == 0) { flags |= FC_DICT; p += 4; - } else if (STRNCMP(p, "abort", 5) == 0) { + } else if (strncmp(p, "abort", 5) == 0) { flags |= FC_ABORT; p += 5; - } else if (STRNCMP(p, "closure", 7) == 0) { + } else if (strncmp(p, "closure", 7) == 0) { flags |= FC_CLOSURE; p += 7; if (current_funccal == NULL) { @@ -2298,7 +2298,7 @@ void ex_function(exarg_T *eap) // * ":let {var-name} =<< [trim] {marker}" and "{marker}" if (heredoc_trimmed == NULL || (is_heredoc && skipwhite(theline) == theline) - || STRNCMP(theline, heredoc_trimmed, + || strncmp(theline, heredoc_trimmed, strlen(heredoc_trimmed)) == 0) { if (heredoc_trimmed == NULL) { p = theline; @@ -2348,12 +2348,12 @@ void ex_function(exarg_T *eap) // Increase indent inside "if", "while", "for" and "try", decrease // at "end". - if (indent > 2 && STRNCMP(p, "end", 3) == 0) { + if (indent > 2 && strncmp(p, "end", 3) == 0) { indent -= 2; - } else if (STRNCMP(p, "if", 2) == 0 - || STRNCMP(p, "wh", 2) == 0 - || STRNCMP(p, "for", 3) == 0 - || STRNCMP(p, "try", 3) == 0) { + } else if (strncmp(p, "if", 2) == 0 + || strncmp(p, "wh", 2) == 0 + || strncmp(p, "for", 3) == 0 + || strncmp(p, "try", 3) == 0) { indent += 2; } @@ -2381,7 +2381,7 @@ void ex_function(exarg_T *eap) && (!ASCII_ISALPHA(p[1]) || (p[1] == 'h' && (!ASCII_ISALPHA(p[2]) || (p[2] == 'a' - && (STRNCMP(&p[3], "nge", 3) != 0 + && (strncmp(&p[3], "nge", 3) != 0 || !ASCII_ISALPHA(p[6]))))))) || (p[0] == 'i' && (!ASCII_ISALPHA(p[1]) || (p[1] == 'n' @@ -2432,7 +2432,7 @@ void ex_function(exarg_T *eap) && (!ASCII_ISALNUM(p[2]) || (p[2] == 't' && !ASCII_ISALNUM(p[3]))))) { p = skipwhite(arg + 3); - if (STRNCMP(p, "trim", 4) == 0) { + if (strncmp(p, "trim", 4) == 0) { // Ignore leading white space. p = skipwhite(p + 4); heredoc_trimmed = xstrnsave(theline, (size_t)(skipwhite(theline) - theline)); @@ -2714,7 +2714,7 @@ char *get_user_func_name(expand_T *xp, int idx) fp = HI2UF(hi); if ((fp->uf_flags & FC_DICT) - || STRNCMP(fp->uf_name, "", 8) == 0) { + || strncmp(fp->uf_name, "", 8) == 0) { return ""; // don't show dict and lambda functions } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 2d7df6fde9..a08d37511e 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -80,7 +80,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) // Check for the optional 'trim' word before the marker cmd = skipwhite(cmd); - if (STRNCMP(cmd, "trim", 4) == 0 + if (strncmp(cmd, "trim", 4) == 0 && (cmd[4] == NUL || ascii_iswhite(cmd[4]))) { cmd = skipwhite(cmd + 4); @@ -128,7 +128,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) // with "trim": skip the indent matching the :let line to find the // marker if (marker_indent_len > 0 - && STRNCMP(theline, *eap->cmdlinep, marker_indent_len) == 0) { + && strncmp(theline, *eap->cmdlinep, (size_t)marker_indent_len) == 0) { mi = marker_indent_len; } if (strcmp(marker, theline + mi) == 0) { @@ -208,7 +208,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) } expr = skipwhite(argend); if (*expr != '=' && !((vim_strchr("+-*/%.", *expr) != NULL - && expr[1] == '=') || STRNCMP(expr, "..=", 3) == 0)) { + && expr[1] == '=') || strncmp(expr, "..=", 3) == 0)) { // ":let" without "=": list variables if (*arg == '[') { emsg(_(e_invarg)); -- cgit From 7328c4de54ac96b39853b3f43736aff863fd209d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 11:18:15 +0800 Subject: vim-patch:9.0.0733: use of strftime() is not safe (#21228) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: Use of strftime() is not safe. Solution: Check the return value of strftime(). Use a larger buffer and correctly pass the available space. (Dominique Pellé, closes vim/vim#11348) https://github.com/vim/vim/commit/84d14ccdb50dc9f362066a2c83bfaf331314e5ea Co-authored-by: Dominique Pelle --- src/nvim/eval/funcs.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ebe7e0325b..c312ae61a5 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -8445,9 +8445,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) p = string_convert(&conv, p, NULL); } char result_buf[256]; - if (p != NULL) { - (void)strftime(result_buf, sizeof(result_buf), p, curtime_ptr); - } else { + if (p == NULL || strftime(result_buf, sizeof(result_buf), p, curtime_ptr) == 0) { result_buf[0] = NUL; } -- cgit From 0b79137c59fbe44bded76f123602e552dc6f7b03 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 16:47:29 +0800 Subject: vim-patch:8.1.2001: some source files are too big (#21231) Problem: Some source files are too big. Solution: Move buffer and window related functions to evalbuffer.c and evalwindow.c. (Yegappan Lakshmanan, closes vim/vim#4898) https://github.com/vim/vim/commit/261f346f8154c0ec7094a4a211c653c74e9f7c2e --- src/nvim/eval/buffer.c | 700 +++++++++++++++++++++++++++++++++ src/nvim/eval/buffer.h | 10 + src/nvim/eval/funcs.c | 1014 +----------------------------------------------- src/nvim/eval/vars.c | 1 + src/nvim/eval/window.c | 945 ++++++++++++++++++++++++++++++++++++++++++++ src/nvim/eval/window.h | 68 ++++ 6 files changed, 1727 insertions(+), 1011 deletions(-) create mode 100644 src/nvim/eval/buffer.c create mode 100644 src/nvim/eval/buffer.h create mode 100644 src/nvim/eval/window.c create mode 100644 src/nvim/eval/window.h (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c new file mode 100644 index 0000000000..41ba8d2e88 --- /dev/null +++ b/src/nvim/eval/buffer.c @@ -0,0 +1,700 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// eval/buffer.c: Buffer related builtin functions + +#include +#include + +#include "nvim/ascii.h" +#include "nvim/autocmd.h" +#include "nvim/buffer.h" +#include "nvim/change.h" +#include "nvim/cursor.h" +#include "nvim/eval.h" +#include "nvim/eval/buffer.h" +#include "nvim/eval/funcs.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/globals.h" +#include "nvim/macros.h" +#include "nvim/memline.h" +#include "nvim/memory.h" +#include "nvim/move.h" +#include "nvim/path.h" +#include "nvim/pos.h" +#include "nvim/sign.h" +#include "nvim/types.h" +#include "nvim/undo.h" +#include "nvim/vim.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/buffer.c.generated.h" +#endif + +/// Find a buffer by number or exact name. +buf_T *find_buffer(typval_T *avar) +{ + buf_T *buf = NULL; + + if (avar->v_type == VAR_NUMBER) { + buf = buflist_findnr((int)avar->vval.v_number); + } else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) { + buf = buflist_findname_exp(avar->vval.v_string); + if (buf == NULL) { + // No full path name match, try a match with a URL or a "nofile" + // buffer, these don't use the full path. + FOR_ALL_BUFFERS(bp) { + if (bp->b_fname != NULL + && (path_with_url(bp->b_fname) || bt_nofilename(bp)) + && strcmp(bp->b_fname, avar->vval.v_string) == 0) { + buf = bp; + break; + } + } + } + } + return buf; +} + +/// If there is a window for "curbuf", make it the current window. +static void find_win_for_curbuf(void) +{ + for (wininfo_T *wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next) { + if (wip->wi_win != NULL) { + curwin = wip->wi_win; + break; + } + } +} + +/// Set line or list of lines in buffer "buf" to "lines". +/// Any type is allowed and converted to a string. +static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_T *lines, + typval_T *rettv) + FUNC_ATTR_NONNULL_ARG(4, 5) +{ + linenr_T lnum = lnum_arg + (append ? 1 : 0); + long added = 0; + buf_T *curbuf_save = NULL; + win_T *curwin_save = NULL; + const bool is_curbuf = buf == curbuf; + const bool save_VIsual_active = VIsual_active; + + // When using the current buffer ml_mfp will be set if needed. Useful when + // setline() is used on startup. For other buffers the buffer must be + // loaded. + if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1) { + rettv->vval.v_number = 1; // FAIL + return; + } + + if (!is_curbuf) { + VIsual_active = false; + curbuf_save = curbuf; + curwin_save = curwin; + curbuf = buf; + find_win_for_curbuf(); + } + + linenr_T append_lnum; + if (append) { + // appendbufline() uses the line number below which we insert + append_lnum = lnum - 1; + } else { + // setbufline() uses the line number above which we insert, we only + // append if it's below the last line + append_lnum = curbuf->b_ml.ml_line_count; + } + + list_T *l = NULL; + listitem_T *li = NULL; + char *line = NULL; + if (lines->v_type == VAR_LIST) { + l = lines->vval.v_list; + if (l == NULL || tv_list_len(l) == 0) { + // set proper return code + if (lnum > curbuf->b_ml.ml_line_count) { + rettv->vval.v_number = 1; // FAIL + } + goto done; + } + li = tv_list_first(l); + } else { + line = typval_tostring(lines, false); + } + + // Default result is zero == OK. + for (;;) { + if (lines->v_type == VAR_LIST) { + // List argument, get next string. + if (li == NULL) { + break; + } + xfree(line); + line = typval_tostring(TV_LIST_ITEM_TV(li), false); + li = TV_LIST_ITEM_NEXT(l, li); + } + + rettv->vval.v_number = 1; // FAIL + if (line == NULL || lnum > curbuf->b_ml.ml_line_count + 1) { + break; + } + + // When coming here from Insert mode, sync undo, so that this can be + // undone separately from what was previously inserted. + if (u_sync_once == 2) { + u_sync_once = 1; // notify that u_sync() was called + u_sync(true); + } + + if (!append && lnum <= curbuf->b_ml.ml_line_count) { + // Existing line, replace it. + int old_len = (int)strlen(ml_get(lnum)); + if (u_savesub(lnum) == OK + && ml_replace(lnum, line, true) == OK) { + inserted_bytes(lnum, 0, old_len, (int)strlen(line)); + if (is_curbuf && lnum == curwin->w_cursor.lnum) { + check_cursor_col(); + } + rettv->vval.v_number = 0; // OK + } + } else if (added > 0 || u_save(lnum - 1, lnum) == OK) { + // append the line. + added++; + if (ml_append(lnum - 1, line, 0, false) == OK) { + rettv->vval.v_number = 0; // OK + } + } + + if (l == NULL) { // only one string argument + break; + } + lnum++; + } + xfree(line); + + if (added > 0) { + appended_lines_mark(append_lnum, added); + + // Only adjust the cursor for buffers other than the current, unless it + // is the current window. For curbuf and other windows it has been done + // in mark_adjust_internal(). + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer == buf + && (wp->w_buffer != curbuf || wp == curwin) + && wp->w_cursor.lnum > append_lnum) { + wp->w_cursor.lnum += (linenr_T)added; + } + } + check_cursor_col(); + update_topline(curwin); + } + +done: + if (!is_curbuf) { + curbuf = curbuf_save; + curwin = curwin_save; + VIsual_active = save_VIsual_active; + } +} + +/// "append(lnum, string/list)" function +void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + const int did_emsg_before = did_emsg; + const linenr_T lnum = tv_get_lnum(&argvars[0]); + if (did_emsg == did_emsg_before) { + set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); + } +} + +/// Set or append lines to a buffer. +static void buf_set_append_line(typval_T *argvars, typval_T *rettv, bool append) +{ + const int did_emsg_before = did_emsg; + buf_T *const buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + rettv->vval.v_number = 1; // FAIL + } else { + const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg == did_emsg_before) { + set_buffer_lines(buf, lnum, append, &argvars[2], rettv); + } + } +} + +/// "appendbufline(buf, lnum, string/list)" function +void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_set_append_line(argvars, rettv, true); +} + +/// "bufadd(expr)" function +void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char_u *name = (char_u *)tv_get_string(&argvars[0]); + + rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0); +} + +/// "bufexists(expr)" function +void f_bufexists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); +} + +/// "buflisted(expr)" function +void f_buflisted(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_T *buf; + + buf = find_buffer(&argvars[0]); + rettv->vval.v_number = (buf != NULL && buf->b_p_bl); +} + +/// "bufload(expr)" function +void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) +{ + buf_T *buf = get_buf_arg(&argvars[0]); + + if (buf != NULL && buf->b_ml.ml_mfp == NULL) { + aco_save_T aco; + + aucmd_prepbuf(&aco, buf); + swap_exists_action = SEA_NONE; + open_buffer(false, NULL, 0); + aucmd_restbuf(&aco); + } +} + +/// "bufloaded(expr)" function +void f_bufloaded(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_T *buf; + + buf = find_buffer(&argvars[0]); + rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); +} + +/// "bufname(expr)" function +void f_bufname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + const buf_T *buf; + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + if (argvars[0].v_type == VAR_UNKNOWN) { + buf = curbuf; + } else { + buf = tv_get_buf_from_arg(&argvars[0]); + } + if (buf != NULL && buf->b_fname != NULL) { + rettv->vval.v_string = xstrdup(buf->b_fname); + } +} + +/// "bufnr(expr)" function +void f_bufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + const buf_T *buf; + bool error = false; + + rettv->vval.v_number = -1; + + if (argvars[0].v_type == VAR_UNKNOWN) { + buf = curbuf; + } else { + // Don't use tv_get_buf_from_arg(); we continue if the buffer wasn't found + // and the second argument isn't zero, but we want to return early if the + // first argument isn't a string or number so only one error is shown. + if (!tv_check_str_or_nr(&argvars[0])) { + return; + } + emsg_off++; + buf = tv_get_buf(&argvars[0], false); + emsg_off--; + } + + // If the buffer isn't found and the second argument is not zero create a + // new buffer. + const char *name; + if (buf == NULL + && argvars[1].v_type != VAR_UNKNOWN + && tv_get_number_chk(&argvars[1], &error) != 0 + && !error + && (name = tv_get_string_chk(&argvars[0])) != NULL) { + buf = buflist_new((char *)name, NULL, 1, 0); + } + + if (buf != NULL) { + rettv->vval.v_number = buf->b_fnum; + } +} + +static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) +{ + const buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); + if (buf == NULL) { // no need to search if invalid arg or buffer not found + rettv->vval.v_number = -1; + return; + } + + int winnr = 0; + int winid; + bool found_buf = false; + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + winnr++; + if (wp->w_buffer == buf) { + found_buf = true; + winid = wp->handle; + break; + } + } + rettv->vval.v_number = (found_buf ? (get_nr ? winnr : winid) : -1); +} + +/// "bufwinid(nr)" function +void f_bufwinid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_win_common(argvars, rettv, false); +} + +/// "bufwinnr(nr)" function +void f_bufwinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_win_common(argvars, rettv, true); +} + +/// "deletebufline()" function +void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + const int did_emsg_before = did_emsg; + rettv->vval.v_number = 1; // FAIL by default + buf_T *const buf = tv_get_buf(&argvars[0], false); + if (buf == NULL) { + return; + } + const bool is_curbuf = buf == curbuf; + const bool save_VIsual_active = VIsual_active; + + linenr_T last; + const linenr_T first = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) { + return; + } + if (argvars[2].v_type != VAR_UNKNOWN) { + last = tv_get_lnum_buf(&argvars[2], buf); + } else { + last = first; + } + + if (buf->b_ml.ml_mfp == NULL || first < 1 + || first > buf->b_ml.ml_line_count || last < first) { + return; + } + + buf_T *curbuf_save = NULL; + win_T *curwin_save = NULL; + // After this don't use "return", goto "cleanup"! + if (!is_curbuf) { + VIsual_active = false; + curbuf_save = curbuf; + curwin_save = curwin; + curbuf = buf; + find_win_for_curbuf(); + } + if (last > curbuf->b_ml.ml_line_count) { + last = curbuf->b_ml.ml_line_count; + } + const long count = last - first + 1; + + // When coming here from Insert mode, sync undo, so that this can be + // undone separately from what was previously inserted. + if (u_sync_once == 2) { + u_sync_once = 1; // notify that u_sync() was called + u_sync(true); + } + + if (u_save(first - 1, last + 1) == FAIL) { + goto cleanup; + } + + for (linenr_T lnum = first; lnum <= last; lnum++) { + ml_delete(first, true); + } + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer == buf) { + if (wp->w_cursor.lnum > last) { + wp->w_cursor.lnum -= (linenr_T)count; + } else if (wp->w_cursor.lnum > first) { + wp->w_cursor.lnum = first; + } + if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) { + wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count; + } + } + } + check_cursor_col(); + deleted_lines_mark(first, count); + rettv->vval.v_number = 0; // OK + +cleanup: + if (!is_curbuf) { + curbuf = curbuf_save; + curwin = curwin_save; + VIsual_active = save_VIsual_active; + } +} + +/// @return buffer options, variables and other attributes in a dictionary. +static dict_T *get_buffer_info(buf_T *buf) +{ + dict_T *const dict = tv_dict_alloc(); + + tv_dict_add_nr(dict, S_LEN("bufnr"), buf->b_fnum); + tv_dict_add_str(dict, S_LEN("name"), + buf->b_ffname != NULL ? (const char *)buf->b_ffname : ""); + tv_dict_add_nr(dict, S_LEN("lnum"), + buf == curbuf ? curwin->w_cursor.lnum : buflist_findlnum(buf)); + tv_dict_add_nr(dict, S_LEN("linecount"), buf->b_ml.ml_line_count); + tv_dict_add_nr(dict, S_LEN("loaded"), buf->b_ml.ml_mfp != NULL); + tv_dict_add_nr(dict, S_LEN("listed"), buf->b_p_bl); + tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf)); + tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf)); + tv_dict_add_nr(dict, S_LEN("hidden"), + buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0); + + // Get a reference to buffer variables + tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars); + + // List of windows displaying this buffer + list_T *const windows = tv_list_alloc(kListLenMayKnow); + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer == buf) { + tv_list_append_number(windows, (varnumber_T)wp->handle); + } + } + tv_dict_add_list(dict, S_LEN("windows"), windows); + + if (buf->b_signlist != NULL) { + // List of signs placed in this buffer + tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf)); + } + + tv_dict_add_nr(dict, S_LEN("lastused"), buf->b_last_used); + + return dict; +} + +/// "getbufinfo()" function +void f_getbufinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_T *argbuf = NULL; + bool filtered = false; + bool sel_buflisted = false; + bool sel_bufloaded = false; + bool sel_bufmodified = false; + + tv_list_alloc_ret(rettv, kListLenMayKnow); + + // List of all the buffers or selected buffers + if (argvars[0].v_type == VAR_DICT) { + dict_T *sel_d = argvars[0].vval.v_dict; + + if (sel_d != NULL) { + dictitem_T *di; + + filtered = true; + + di = tv_dict_find(sel_d, S_LEN("buflisted")); + if (di != NULL && tv_get_number(&di->di_tv)) { + sel_buflisted = true; + } + + di = tv_dict_find(sel_d, S_LEN("bufloaded")); + if (di != NULL && tv_get_number(&di->di_tv)) { + sel_bufloaded = true; + } + di = tv_dict_find(sel_d, S_LEN("bufmodified")); + if (di != NULL && tv_get_number(&di->di_tv)) { + sel_bufmodified = true; + } + } + } else if (argvars[0].v_type != VAR_UNKNOWN) { + // Information about one buffer. Argument specifies the buffer + argbuf = tv_get_buf_from_arg(&argvars[0]); + if (argbuf == NULL) { + return; + } + } + + // Return information about all the buffers or a specified buffer + FOR_ALL_BUFFERS(buf) { + if (argbuf != NULL && argbuf != buf) { + continue; + } + if (filtered && ((sel_bufloaded && buf->b_ml.ml_mfp == NULL) + || (sel_buflisted && !buf->b_p_bl) + || (sel_bufmodified && !buf->b_changed))) { + continue; + } + + dict_T *const d = get_buffer_info(buf); + tv_list_append_dict(rettv->vval.v_list, d); + if (argbuf != NULL) { + return; + } + } +} + +/// Get line or list of lines from buffer "buf" into "rettv". +/// +/// @param retlist if true, then the lines are returned as a Vim List. +/// +/// @return range (from start to end) of lines in rettv from the specified +/// buffer. +static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv) +{ + rettv->v_type = (retlist ? VAR_LIST : VAR_STRING); + rettv->vval.v_string = NULL; + + if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0 || end < start) { + if (retlist) { + tv_list_alloc_ret(rettv, 0); + } + return; + } + + if (retlist) { + if (start < 1) { + start = 1; + } + if (end > buf->b_ml.ml_line_count) { + end = buf->b_ml.ml_line_count; + } + tv_list_alloc_ret(rettv, end - start + 1); + while (start <= end) { + tv_list_append_string(rettv->vval.v_list, + (const char *)ml_get_buf(buf, start++, false), -1); + } + } else { + rettv->v_type = VAR_STRING; + rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count) + ? xstrdup(ml_get_buf(buf, start, false)) : NULL); + } +} + +/// @param retlist true: "getbufline()" function +/// false: "getbufoneline()" function +static void getbufline(typval_T *argvars, typval_T *rettv, bool retlist) +{ + const int did_emsg_before = did_emsg; + buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); + const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); + if (did_emsg > did_emsg_before) { + return; + } + const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN + ? lnum + : tv_get_lnum_buf(&argvars[2], buf)); + + get_buffer_lines(buf, lnum, end, retlist, rettv); +} + +/// "getbufline()" function +void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + getbufline(argvars, rettv, true); +} + +/// "getbufoneline()" function +void f_getbufoneline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + getbufline(argvars, rettv, false); +} + +/// "getline(lnum, [end])" function +void f_getline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + linenr_T end; + bool retlist; + + const linenr_T lnum = tv_get_lnum(argvars); + if (argvars[1].v_type == VAR_UNKNOWN) { + end = lnum; + retlist = false; + } else { + end = tv_get_lnum(&argvars[1]); + retlist = true; + } + + get_buffer_lines(curbuf, lnum, end, retlist, rettv); +} + +/// "setbufline()" function +void f_setbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + buf_set_append_line(argvars, rettv, false); +} + +/// "setline()" function +void f_setline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + const int did_emsg_before = did_emsg; + linenr_T lnum = tv_get_lnum(&argvars[0]); + if (did_emsg == did_emsg_before) { + set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv); + } +} + +/// Make "buf" the current buffer. +/// +/// restore_buffer() MUST be called to undo. +/// No autocommands will be executed. Use aucmd_prepbuf() if there are any. +void switch_buffer(bufref_T *save_curbuf, buf_T *buf) +{ + block_autocmds(); + set_bufref(save_curbuf, curbuf); + curbuf->b_nwindows--; + curbuf = buf; + curwin->w_buffer = buf; + curbuf->b_nwindows++; +} + +/// Restore the current buffer after using switch_buffer(). +void restore_buffer(bufref_T *save_curbuf) +{ + unblock_autocmds(); + // Check for valid buffer, just in case. + if (bufref_valid(save_curbuf)) { + curbuf->b_nwindows--; + curwin->w_buffer = save_curbuf->br_buf; + curbuf = save_curbuf->br_buf; + curbuf->b_nwindows++; + } +} + +/// Find a window for buffer "buf". +/// If found true is returned and "wp" and "tp" are set to +/// the window and tabpage. +/// If not found, false is returned. +/// +/// @param buf buffer to find a window for +/// @param[out] wp stores the found window +/// @param[out] tp stores the found tabpage +/// +/// @return true if a window was found for the buffer. +bool find_win_for_buf(buf_T *buf, win_T **wp, tabpage_T **tp) +{ + *wp = NULL; + *tp = NULL; + FOR_ALL_TAB_WINDOWS(tp2, wp2) { + if (wp2->w_buffer == buf) { + *tp = tp2; + *wp = wp2; + return true; + } + } + return false; +} diff --git a/src/nvim/eval/buffer.h b/src/nvim/eval/buffer.h new file mode 100644 index 0000000000..4a2f8f9e94 --- /dev/null +++ b/src/nvim/eval/buffer.h @@ -0,0 +1,10 @@ +#ifndef NVIM_EVAL_BUFFER_H +#define NVIM_EVAL_BUFFER_H + +#include "nvim/buffer_defs.h" +#include "nvim/eval/typval_defs.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/buffer.h.generated.h" +#endif +#endif // NVIM_EVAL_BUFFER_H diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c312ae61a5..ec62c583a6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -30,7 +30,6 @@ #include "nvim/autocmd.h" #include "nvim/buffer.h" #include "nvim/buffer_defs.h" -#include "nvim/change.h" #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/cmdexpand.h" @@ -39,6 +38,7 @@ #include "nvim/diff.h" #include "nvim/edit.h" #include "nvim/eval.h" +#include "nvim/eval/buffer.h" #include "nvim/eval/decode.h" #include "nvim/eval/encode.h" #include "nvim/eval/executor.h" @@ -46,6 +46,7 @@ #include "nvim/eval/typval.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" +#include "nvim/eval/window.h" #include "nvim/event/loop.h" #include "nvim/event/multiqueue.h" #include "nvim/event/process.h" @@ -149,8 +150,6 @@ static char *e_invalwindow = N_("E957: Invalid window number"); static char *e_reduceempty = N_("E998: Reduce of an empty %s with no initial value"); static char e_using_number_as_bool_nr[] = N_("E1023: Using a Number as a Bool: %d"); -static char e_cannot_resize_window_in_another_tab_page[] - = N_("E1308: Cannot resize a window in another tab page"); /// Dummy va_list for passing to vim_snprintf /// @@ -399,37 +398,6 @@ static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) (void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL); } -/// "append(lnum, string/list)" function -static void f_append(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const int did_emsg_before = did_emsg; - const linenr_T lnum = tv_get_lnum(&argvars[0]); - if (did_emsg == did_emsg_before) { - set_buffer_lines(curbuf, lnum, true, &argvars[1], rettv); - } -} - -/// Set or append lines to a buffer. -static void buf_set_append_line(typval_T *argvars, typval_T *rettv, bool append) -{ - const int did_emsg_before = did_emsg; - buf_T *const buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - rettv->vval.v_number = 1; // FAIL - } else { - const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); - if (did_emsg == did_emsg_before) { - set_buffer_lines(buf, lnum, append, &argvars[2], rettv); - } - } -} - -/// "appendbufline(buf, lnum, string/list)" function -static void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_set_append_line(argvars, rettv, true); -} - /// "atan2()" function static void f_atan2(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -457,166 +425,6 @@ static void f_browsedir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) f_browse(argvars, rettv, fptr); } -/// Find a buffer by number or exact name. -static buf_T *find_buffer(typval_T *avar) -{ - buf_T *buf = NULL; - - if (avar->v_type == VAR_NUMBER) { - buf = buflist_findnr((int)avar->vval.v_number); - } else if (avar->v_type == VAR_STRING && avar->vval.v_string != NULL) { - buf = buflist_findname_exp(avar->vval.v_string); - if (buf == NULL) { - // No full path name match, try a match with a URL or a "nofile" - // buffer, these don't use the full path. - FOR_ALL_BUFFERS(bp) { - if (bp->b_fname != NULL - && (path_with_url(bp->b_fname) || bt_nofilename(bp)) - && strcmp(bp->b_fname, avar->vval.v_string) == 0) { - buf = bp; - break; - } - } - } - } - return buf; -} - -/// "bufadd(expr)" function -static void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - char_u *name = (char_u *)tv_get_string(&argvars[0]); - - rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0); -} - -/// "bufexists(expr)" function -static void f_bufexists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = (find_buffer(&argvars[0]) != NULL); -} - -/// "buflisted(expr)" function -static void f_buflisted(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_T *buf; - - buf = find_buffer(&argvars[0]); - rettv->vval.v_number = (buf != NULL && buf->b_p_bl); -} - -/// "bufload(expr)" function -static void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) -{ - buf_T *buf = get_buf_arg(&argvars[0]); - - if (buf != NULL && buf->b_ml.ml_mfp == NULL) { - aco_save_T aco; - - aucmd_prepbuf(&aco, buf); - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); - aucmd_restbuf(&aco); - } -} - -/// "bufloaded(expr)" function -static void f_bufloaded(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_T *buf; - - buf = find_buffer(&argvars[0]); - rettv->vval.v_number = (buf != NULL && buf->b_ml.ml_mfp != NULL); -} - -/// "bufname(expr)" function -static void f_bufname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const buf_T *buf; - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - if (argvars[0].v_type == VAR_UNKNOWN) { - buf = curbuf; - } else { - buf = tv_get_buf_from_arg(&argvars[0]); - } - if (buf != NULL && buf->b_fname != NULL) { - rettv->vval.v_string = xstrdup(buf->b_fname); - } -} - -/// "bufnr(expr)" function -static void f_bufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const buf_T *buf; - bool error = false; - - rettv->vval.v_number = -1; - - if (argvars[0].v_type == VAR_UNKNOWN) { - buf = curbuf; - } else { - // Don't use tv_get_buf_from_arg(); we continue if the buffer wasn't found - // and the second argument isn't zero, but we want to return early if the - // first argument isn't a string or number so only one error is shown. - if (!tv_check_str_or_nr(&argvars[0])) { - return; - } - emsg_off++; - buf = tv_get_buf(&argvars[0], false); - emsg_off--; - } - - // If the buffer isn't found and the second argument is not zero create a - // new buffer. - const char *name; - if (buf == NULL - && argvars[1].v_type != VAR_UNKNOWN - && tv_get_number_chk(&argvars[1], &error) != 0 - && !error - && (name = tv_get_string_chk(&argvars[0])) != NULL) { - buf = buflist_new((char *)name, NULL, 1, 0); - } - - if (buf != NULL) { - rettv->vval.v_number = buf->b_fnum; - } -} - -static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr) -{ - const buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); - if (buf == NULL) { // no need to search if invalid arg or buffer not found - rettv->vval.v_number = -1; - return; - } - - int winnr = 0; - int winid; - bool found_buf = false; - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - winnr++; - if (wp->w_buffer == buf) { - found_buf = true; - winid = wp->handle; - break; - } - } - rettv->vval.v_number = (found_buf ? (get_nr ? winnr : winid) : -1); -} - -/// "bufwinid(nr)" function -static void f_bufwinid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_win_common(argvars, rettv, false); -} - -/// "bufwinnr(nr)" function -static void f_bufwinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_win_common(argvars, rettv, true); -} - /// Get buffer by number or pattern. buf_T *tv_get_buf(typval_T *tv, int curtab_only) { @@ -1542,88 +1350,6 @@ static void f_dictwatcherdel(typval_T *argvars, typval_T *rettv, EvalFuncData fp callback_free(&callback); } -/// "deletebufline()" function -static void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const int did_emsg_before = did_emsg; - rettv->vval.v_number = 1; // FAIL by default - buf_T *const buf = tv_get_buf(&argvars[0], false); - if (buf == NULL) { - return; - } - const bool is_curbuf = buf == curbuf; - const bool save_VIsual_active = VIsual_active; - - linenr_T last; - const linenr_T first = tv_get_lnum_buf(&argvars[1], buf); - if (did_emsg > did_emsg_before) { - return; - } - if (argvars[2].v_type != VAR_UNKNOWN) { - last = tv_get_lnum_buf(&argvars[2], buf); - } else { - last = first; - } - - if (buf->b_ml.ml_mfp == NULL || first < 1 - || first > buf->b_ml.ml_line_count || last < first) { - return; - } - - buf_T *curbuf_save = NULL; - win_T *curwin_save = NULL; - // After this don't use "return", goto "cleanup"! - if (!is_curbuf) { - VIsual_active = false; - curbuf_save = curbuf; - curwin_save = curwin; - curbuf = buf; - find_win_for_curbuf(); - } - if (last > curbuf->b_ml.ml_line_count) { - last = curbuf->b_ml.ml_line_count; - } - const long count = last - first + 1; - - // When coming here from Insert mode, sync undo, so that this can be - // undone separately from what was previously inserted. - if (u_sync_once == 2) { - u_sync_once = 1; // notify that u_sync() was called - u_sync(true); - } - - if (u_save(first - 1, last + 1) == FAIL) { - goto cleanup; - } - - for (linenr_T lnum = first; lnum <= last; lnum++) { - ml_delete(first, true); - } - - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp->w_buffer == buf) { - if (wp->w_cursor.lnum > last) { - wp->w_cursor.lnum -= (linenr_T)count; - } else if (wp->w_cursor.lnum > first) { - wp->w_cursor.lnum = first; - } - if (wp->w_cursor.lnum > wp->w_buffer->b_ml.ml_line_count) { - wp->w_cursor.lnum = wp->w_buffer->b_ml.ml_line_count; - } - } - } - check_cursor_col(); - deleted_lines_mark(first, count); - rettv->vval.v_number = 0; // OK - -cleanup: - if (!is_curbuf) { - curbuf = curbuf_save; - curwin = curwin_save; - VIsual_active = save_VIsual_active; - } -} - /// "did_filetype()" function static void f_did_filetype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -1864,7 +1590,7 @@ static char *get_list_line(int c, void *cookie, int indent, bool do_concat) return s == NULL ? NULL : xstrdup(s); } -static void execute_common(typval_T *argvars, typval_T *rettv, int arg_off) +void execute_common(typval_T *argvars, typval_T *rettv, int arg_off) { const int save_msg_silent = msg_silent; const int save_emsg_silent = emsg_silent; @@ -1948,21 +1674,6 @@ static void f_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) execute_common(argvars, rettv, 0); } -/// "win_execute(win_id, command)" function -static void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - // Return an empty string if something fails. - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - - int id = (int)tv_get_number(argvars); - tabpage_T *tp; - win_T *wp = win_id2wp_tp(id, &tp); - if (wp != NULL && tp != NULL) { - WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); - } -} - /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -2573,133 +2284,6 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -/// "getbufinfo()" function -static void f_getbufinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_T *argbuf = NULL; - bool filtered = false; - bool sel_buflisted = false; - bool sel_bufloaded = false; - bool sel_bufmodified = false; - - tv_list_alloc_ret(rettv, kListLenMayKnow); - - // List of all the buffers or selected buffers - if (argvars[0].v_type == VAR_DICT) { - dict_T *sel_d = argvars[0].vval.v_dict; - - if (sel_d != NULL) { - dictitem_T *di; - - filtered = true; - - di = tv_dict_find(sel_d, S_LEN("buflisted")); - if (di != NULL && tv_get_number(&di->di_tv)) { - sel_buflisted = true; - } - - di = tv_dict_find(sel_d, S_LEN("bufloaded")); - if (di != NULL && tv_get_number(&di->di_tv)) { - sel_bufloaded = true; - } - di = tv_dict_find(sel_d, S_LEN("bufmodified")); - if (di != NULL && tv_get_number(&di->di_tv)) { - sel_bufmodified = true; - } - } - } else if (argvars[0].v_type != VAR_UNKNOWN) { - // Information about one buffer. Argument specifies the buffer - argbuf = tv_get_buf_from_arg(&argvars[0]); - if (argbuf == NULL) { - return; - } - } - - // Return information about all the buffers or a specified buffer - FOR_ALL_BUFFERS(buf) { - if (argbuf != NULL && argbuf != buf) { - continue; - } - if (filtered && ((sel_bufloaded && buf->b_ml.ml_mfp == NULL) - || (sel_buflisted && !buf->b_p_bl) - || (sel_bufmodified && !buf->b_changed))) { - continue; - } - - dict_T *const d = get_buffer_info(buf); - tv_list_append_dict(rettv->vval.v_list, d); - if (argbuf != NULL) { - return; - } - } -} - -/// Get line or list of lines from buffer "buf" into "rettv". -/// -/// @param retlist if true, then the lines are returned as a Vim List. -/// -/// @return range (from start to end) of lines in rettv from the specified -/// buffer. -static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv) -{ - rettv->v_type = (retlist ? VAR_LIST : VAR_STRING); - rettv->vval.v_string = NULL; - - if (buf == NULL || buf->b_ml.ml_mfp == NULL || start < 0 || end < start) { - if (retlist) { - tv_list_alloc_ret(rettv, 0); - } - return; - } - - if (retlist) { - if (start < 1) { - start = 1; - } - if (end > buf->b_ml.ml_line_count) { - end = buf->b_ml.ml_line_count; - } - tv_list_alloc_ret(rettv, end - start + 1); - while (start <= end) { - tv_list_append_string(rettv->vval.v_list, - (const char *)ml_get_buf(buf, start++, false), -1); - } - } else { - rettv->v_type = VAR_STRING; - rettv->vval.v_string = ((start >= 1 && start <= buf->b_ml.ml_line_count) - ? xstrdup(ml_get_buf(buf, start, false)) : NULL); - } -} - -/// @param retlist true: "getbufline()" function -/// false: "getbufoneline()" function -static void getbufline(typval_T *argvars, typval_T *rettv, bool retlist) -{ - const int did_emsg_before = did_emsg; - buf_T *const buf = tv_get_buf_from_arg(&argvars[0]); - const linenr_T lnum = tv_get_lnum_buf(&argvars[1], buf); - if (did_emsg > did_emsg_before) { - return; - } - const linenr_T end = (argvars[2].v_type == VAR_UNKNOWN - ? lnum - : tv_get_lnum_buf(&argvars[2], buf)); - - get_buffer_lines(buf, lnum, end, retlist, rettv); -} - -/// "getbufline()" function -static void f_getbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - getbufline(argvars, rettv, true); -} - -/// "getbufoneline()" function -static void f_getbufoneline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - getbufline(argvars, rettv, false); -} - /// "getchangelist()" function static void f_getchangelist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -2823,15 +2407,6 @@ static void f_getcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt tv_dict_add_nr(dict, S_LEN("until"), last_csearch_until()); } -/// "getcmdwintype()" function -static void f_getcmdwintype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - rettv->vval.v_string = xmallocz(1); - rettv->vval.v_string[0] = (char)cmdwin_type; -} - /// `getcwd([{win}[, {tab}]])` function /// /// Every scope not specified implies the currently selected scope object. @@ -3083,24 +2658,6 @@ static void f_getjumplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -/// "getline(lnum, [end])" function -static void f_getline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - linenr_T end; - bool retlist; - - const linenr_T lnum = tv_get_lnum(argvars); - if (argvars[1].v_type == VAR_UNKNOWN) { - end = lnum; - retlist = false; - } else { - end = tv_get_lnum(&argvars[1]); - retlist = true; - } - - get_buffer_lines(curbuf, lnum, end, retlist, rettv); -} - /// "getmarklist()" function static void f_getmarklist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3259,38 +2816,6 @@ static void f_getregtype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = xstrdup(buf); } -/// "gettabinfo()" function -static void f_gettabinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tabpage_T *tparg = NULL; - - tv_list_alloc_ret(rettv, (argvars[0].v_type == VAR_UNKNOWN - ? 1 - : kListLenMayKnow)); - - if (argvars[0].v_type != VAR_UNKNOWN) { - // Information about one tab page - tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); - if (tparg == NULL) { - return; - } - } - - // Get information about a specific tab page or all tab pages - int tpnr = 0; - FOR_ALL_TABS(tp) { - tpnr++; - if (tparg != NULL && tp != tparg) { - continue; - } - dict_T *const d = get_tabpage_info(tp, tpnr); - tv_list_append_dict(rettv->vval.v_list, d); - if (tparg != NULL) { - return; - } - } -} - /// "gettagstack()" function static void f_gettagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -3308,41 +2833,6 @@ static void f_gettagstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) get_tagstack(wp, rettv->vval.v_dict); } -/// "getwininfo()" function -static void f_getwininfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wparg = NULL; - - tv_list_alloc_ret(rettv, kListLenMayKnow); - - if (argvars[0].v_type != VAR_UNKNOWN) { - wparg = win_id2wp((int)tv_get_number(&argvars[0])); - if (wparg == NULL) { - return; - } - } - - // Collect information about either all the windows across all the tab - // pages or one particular window. - int16_t tabnr = 0; - FOR_ALL_TABS(tp) { - tabnr++; - int16_t winnr = 0; - FOR_ALL_WINDOWS_IN_TAB(wp, tp) { - winnr++; - if (wparg != NULL && wp != wparg) { - continue; - } - dict_T *const d = get_win_info(wp, tabnr, winnr); - tv_list_append_dict(rettv->vval.v_list, d); - if (wparg != NULL) { - // found information about a specific window - return; - } - } - } -} - /// Dummy timer callback. Used by f_wait(). static void dummy_timer_due_cb(TimeWatcher *tw, void *data) {} @@ -3407,111 +2897,6 @@ static void f_wait(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) time_watcher_close(tw, dummy_timer_close_cb); } -/// "win_screenpos()" function -static void f_win_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_list_alloc_ret(rettv, 2); - const win_T *const wp = find_win_by_nr_or_id(&argvars[0]); - tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1); - tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); -} - -/// Move the window wp into a new split of targetwin in a given direction -static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) -{ - int height = wp->w_height; - win_T *oldwin = curwin; - - if (wp == targetwin || wp == aucmd_win) { - return; - } - - // Jump to the target window - if (curwin != targetwin) { - win_goto(targetwin); - } - - // Remove the old window and frame from the tree of frames - int dir; - (void)winframe_remove(wp, &dir, NULL); - win_remove(wp, NULL); - last_status(false); // may need to remove last status line - (void)win_comp_pos(); // recompute window positions - - // Split a window on the desired side and put the old window there - (void)win_split_ins(size, flags, wp, dir); - - // If splitting horizontally, try to preserve height - if (size == 0 && !(flags & WSP_VERT)) { - win_setheight_win(height, wp); - if (p_ea) { - win_equal(wp, true, 'v'); - } - } - - if (oldwin != curwin) { - win_goto(oldwin); - } -} - -/// "win_splitmove()" function -static void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - win_T *targetwin = find_win_by_nr_or_id(&argvars[1]); - - if (wp == NULL || targetwin == NULL || wp == targetwin - || !win_valid(wp) || !win_valid(targetwin) - || win_valid_floating(wp) || win_valid_floating(targetwin)) { - emsg(_(e_invalwindow)); - rettv->vval.v_number = -1; - return; - } - - int flags = 0, size = 0; - - if (argvars[2].v_type != VAR_UNKNOWN) { - dict_T *d; - dictitem_T *di; - - if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { - emsg(_(e_invarg)); - return; - } - - d = argvars[2].vval.v_dict; - if (tv_dict_get_number(d, "vertical")) { - flags |= WSP_VERT; - } - if ((di = tv_dict_find(d, "rightbelow", -1)) != NULL) { - flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE; - } - size = (int)tv_dict_get_number(d, "size"); - } - - win_move_into_split(wp, targetwin, size, flags); -} - -/// "getwinpos({timeout})" function -static void f_getwinpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_list_alloc_ret(rettv, 2); - tv_list_append_number(rettv->vval.v_list, -1); - tv_list_append_number(rettv->vval.v_list, -1); -} - -/// "getwinposx()" function -static void f_getwinposx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = -1; -} - -/// "getwinposy()" function -static void f_getwinposy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = -1; -} - /// "glob()" function static void f_glob(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -7612,12 +6997,6 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } -/// "setbufline()" function -static void f_setbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - buf_set_append_line(argvars, rettv, false); -} - /// Set the cursor or mark position. /// If 'charpos' is true, then use the column number as a character offset. /// Otherwise use the column number as a byte offset. @@ -7741,16 +7120,6 @@ static void f_setfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = os_setperm(fname, mode) == OK; } -/// "setline()" function -static void f_setline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - const int did_emsg_before = did_emsg; - linenr_T lnum = tv_get_lnum(&argvars[0]); - if (did_emsg == did_emsg_before) { - set_buffer_lines(curbuf, lnum, false, &argvars[1], rettv); - } -} - /// "setpos()" function static void f_setpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -9076,105 +8445,6 @@ static void f_tabpagebuflist(typval_T *argvars, typval_T *rettv, EvalFuncData fp } } -/// "tabpagenr()" function -static void f_tabpagenr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int nr = 1; - - if (argvars[0].v_type != VAR_UNKNOWN) { - const char *const arg = tv_get_string_chk(&argvars[0]); - nr = 0; - if (arg != NULL) { - if (strcmp(arg, "$") == 0) { - nr = tabpage_index(NULL) - 1; - } else if (strcmp(arg, "#") == 0) { - nr = valid_tabpage(lastused_tabpage) ? tabpage_index(lastused_tabpage) : 0; - } else { - semsg(_(e_invexpr2), arg); - } - } - } else { - nr = tabpage_index(curtab); - } - rettv->vval.v_number = nr; -} - -/// Common code for tabpagewinnr() and winnr(). -static int get_winnr(tabpage_T *tp, typval_T *argvar) -{ - int nr = 1; - - win_T *twin = (tp == curtab) ? curwin : tp->tp_curwin; - if (argvar->v_type != VAR_UNKNOWN) { - bool invalid_arg = false; - const char *const arg = tv_get_string_chk(argvar); - if (arg == NULL) { - nr = 0; // Type error; errmsg already given. - } else if (strcmp(arg, "$") == 0) { - twin = (tp == curtab) ? lastwin : tp->tp_lastwin; - } else if (strcmp(arg, "#") == 0) { - twin = (tp == curtab) ? prevwin : tp->tp_prevwin; - if (twin == NULL) { - nr = 0; - } - } else { - // Extract the window count (if specified). e.g. winnr('3j') - char *endp; - long count = strtol((char *)arg, &endp, 10); - if (count <= 0) { - // if count is not specified, default to 1 - count = 1; - } - if (endp != NULL && *endp != '\0') { - if (strequal(endp, "j")) { - twin = win_vert_neighbor(tp, twin, false, count); - } else if (strequal(endp, "k")) { - twin = win_vert_neighbor(tp, twin, true, count); - } else if (strequal(endp, "h")) { - twin = win_horz_neighbor(tp, twin, true, count); - } else if (strequal(endp, "l")) { - twin = win_horz_neighbor(tp, twin, false, count); - } else { - invalid_arg = true; - } - } else { - invalid_arg = true; - } - } - - if (invalid_arg) { - semsg(_(e_invexpr2), arg); - nr = 0; - } - } - - if (nr > 0) { - for (win_T *wp = (tp == curtab) ? firstwin : tp->tp_firstwin; - wp != twin; wp = wp->w_next) { - if (wp == NULL) { - // didn't find it in this tabpage - nr = 0; - break; - } - nr++; - } - } - return nr; -} - -/// "tabpagewinnr()" function -static void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int nr = 1; - tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); - if (tp == NULL) { - nr = 0; - } else { - nr = get_winnr(tp, &argvars[1]); - } - rettv->vval.v_number = nr; -} - /// "tagfiles()" function static void f_tagfiles(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { @@ -9729,284 +8999,6 @@ static void f_wildmenumode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr } } -/// "win_findbuf()" function -static void f_win_findbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_list_alloc_ret(rettv, kListLenMayKnow); - win_findbuf(argvars, rettv->vval.v_list); -} - -/// "win_getid()" function -static void f_win_getid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = win_getid(argvars); -} - -/// "win_gettype(nr)" function -static void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp = curwin; - - rettv->v_type = VAR_STRING; - rettv->vval.v_string = NULL; - if (argvars[0].v_type != VAR_UNKNOWN) { - wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - rettv->vval.v_string = xstrdup("unknown"); - return; - } - } - if (wp == aucmd_win) { - rettv->vval.v_string = xstrdup("autocmd"); - } else if (wp->w_p_pvw) { - rettv->vval.v_string = xstrdup("preview"); - } else if (wp->w_floating) { - rettv->vval.v_string = xstrdup("popup"); - } else if (wp == curwin && cmdwin_type != 0) { - rettv->vval.v_string = xstrdup("command"); - } else if (bt_quickfix(wp->w_buffer)) { - rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix")); - } -} - -/// "win_gotoid()" function -static void f_win_gotoid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - int id = (int)tv_get_number(&argvars[0]); - - if (cmdwin_type != 0) { - emsg(_(e_cmdwin)); - return; - } - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp->handle == id) { - goto_tabpage_win(tp, wp); - rettv->vval.v_number = 1; - return; - } - } -} - -/// "win_id2tabwin()" function -static void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_id2tabwin(argvars, rettv); -} - -/// "win_id2win()" function -static void f_win_id2win(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = win_id2win(argvars); -} - -/// "win_move_separator()" function -static void f_win_move_separator(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = false; - - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL || wp->w_floating) { - return; - } - if (!win_valid(wp)) { - emsg(_(e_cannot_resize_window_in_another_tab_page)); - return; - } - - int offset = (int)tv_get_number(&argvars[1]); - win_drag_vsep_line(wp, offset); - rettv->vval.v_number = true; -} - -/// "win_move_statusline()" function -static void f_win_move_statusline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp; - int offset; - - rettv->vval.v_number = false; - - wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL || wp->w_floating) { - return; - } - if (!win_valid(wp)) { - emsg(_(e_cannot_resize_window_in_another_tab_page)); - return; - } - - offset = (int)tv_get_number(&argvars[1]); - win_drag_status_line(wp, offset); - rettv->vval.v_number = true; -} - -/// "winbufnr(nr)" function -static void f_winbufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - rettv->vval.v_number = -1; - } else { - rettv->vval.v_number = wp->w_buffer->b_fnum; - } -} - -/// "wincol()" function -static void f_wincol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - validate_cursor(); - rettv->vval.v_number = curwin->w_wcol + 1; -} - -/// "winheight(nr)" function -static void f_winheight(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - rettv->vval.v_number = -1; - } else { - rettv->vval.v_number = wp->w_height_inner; - } -} - -/// "winlayout()" function -static void f_winlayout(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tabpage_T *tp; - - tv_list_alloc_ret(rettv, 2); - - if (argvars[0].v_type == VAR_UNKNOWN) { - tp = curtab; - } else { - tp = find_tabpage((int)tv_get_number(&argvars[0])); - if (tp == NULL) { - return; - } - } - - get_framelayout(tp->tp_topframe, rettv->vval.v_list, true); -} - -/// "winline()" function -static void f_winline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - validate_cursor(); - rettv->vval.v_number = curwin->w_wrow + 1; -} - -/// "winnr()" function -static void f_winnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - rettv->vval.v_number = get_winnr(curtab, &argvars[0]); -} - -/// "winrestcmd()" function -static void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - char_u buf[50]; - - garray_T ga; - ga_init(&ga, (int)sizeof(char), 70); - - // Do this twice to handle some window layouts properly. - for (int i = 0; i < 2; i++) { - int winnr = 1; - FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - snprintf((char *)buf, sizeof(buf), "%dresize %d|", winnr, - wp->w_height); - ga_concat(&ga, (char *)buf); - snprintf((char *)buf, sizeof(buf), "vert %dresize %d|", winnr, - wp->w_width); - ga_concat(&ga, (char *)buf); - winnr++; - } - } - ga_append(&ga, NUL); - - rettv->vval.v_string = ga.ga_data; - rettv->v_type = VAR_STRING; -} - -/// "winrestview()" function -static void f_winrestview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - dict_T *dict = argvars[0].vval.v_dict; - - if (argvars[0].v_type != VAR_DICT || dict == NULL) { - emsg(_(e_invarg)); - } else { - dictitem_T *di; - if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { - curwin->w_cursor.lnum = (linenr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { - curwin->w_cursor.col = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { - curwin->w_cursor.coladd = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { - curwin->w_curswant = (colnr_T)tv_get_number(&di->di_tv); - curwin->w_set_curswant = false; - } - if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { - set_topline(curwin, (linenr_T)tv_get_number(&di->di_tv)); - } - if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { - curwin->w_topfill = (int)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { - curwin->w_leftcol = (colnr_T)tv_get_number(&di->di_tv); - } - if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { - curwin->w_skipcol = (colnr_T)tv_get_number(&di->di_tv); - } - - check_cursor(); - win_new_height(curwin, curwin->w_height); - win_new_width(curwin, curwin->w_width); - changed_window_setting(); - - if (curwin->w_topline <= 0) { - curwin->w_topline = 1; - } - if (curwin->w_topline > curbuf->b_ml.ml_line_count) { - curwin->w_topline = curbuf->b_ml.ml_line_count; - } - check_topfill(curwin, true); - } -} - -/// "winsaveview()" function -static void f_winsaveview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - tv_dict_alloc_ret(rettv); - dict_T *dict = rettv->vval.v_dict; - - tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)curwin->w_cursor.lnum); - tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)curwin->w_cursor.col); - tv_dict_add_nr(dict, S_LEN("coladd"), (varnumber_T)curwin->w_cursor.coladd); - update_curswant(); - tv_dict_add_nr(dict, S_LEN("curswant"), (varnumber_T)curwin->w_curswant); - - tv_dict_add_nr(dict, S_LEN("topline"), (varnumber_T)curwin->w_topline); - tv_dict_add_nr(dict, S_LEN("topfill"), (varnumber_T)curwin->w_topfill); - tv_dict_add_nr(dict, S_LEN("leftcol"), (varnumber_T)curwin->w_leftcol); - tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol); -} - -/// "winwidth(nr)" function -static void f_winwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) -{ - win_T *wp = find_win_by_nr_or_id(&argvars[0]); - if (wp == NULL) { - rettv->vval.v_number = -1; - } else { - rettv->vval.v_number = wp->w_width_inner; - } -} - /// "windowsversion()" function static void f_windowsversion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index a08d37511e..5459eac5bf 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -22,6 +22,7 @@ #include "nvim/eval/typval_defs.h" #include "nvim/eval/userfunc.h" #include "nvim/eval/vars.h" +#include "nvim/eval/window.h" #include "nvim/ex_cmds.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c new file mode 100644 index 0000000000..d6c761bc66 --- /dev/null +++ b/src/nvim/eval/window.c @@ -0,0 +1,945 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +// eval/window.c: Window related builtin functions + +#include +#include +#include +#include +#include + +#include "nvim/ascii.h" +#include "nvim/autocmd.h" +#include "nvim/buffer.h" +#include "nvim/cursor.h" +#include "nvim/eval/funcs.h" +#include "nvim/eval/typval.h" +#include "nvim/eval/typval_defs.h" +#include "nvim/eval/window.h" +#include "nvim/garray.h" +#include "nvim/gettext.h" +#include "nvim/globals.h" +#include "nvim/macros.h" +#include "nvim/memline_defs.h" +#include "nvim/memory.h" +#include "nvim/message.h" +#include "nvim/move.h" +#include "nvim/option_defs.h" +#include "nvim/pos.h" +#include "nvim/types.h" +#include "nvim/vim.h" +#include "nvim/window.h" + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/window.c.generated.h" +#endif + +static char *e_invalwindow = N_("E957: Invalid window number"); +static char e_cannot_resize_window_in_another_tab_page[] + = N_("E1308: Cannot resize a window in another tab page"); + +static int win_getid(typval_T *argvars) +{ + if (argvars[0].v_type == VAR_UNKNOWN) { + return curwin->handle; + } + int winnr = (int)tv_get_number(&argvars[0]); + win_T *wp; + if (winnr > 0) { + if (argvars[1].v_type == VAR_UNKNOWN) { + wp = firstwin; + } else { + tabpage_T *tp = NULL; + int tabnr = (int)tv_get_number(&argvars[1]); + FOR_ALL_TABS(tp2) { + if (--tabnr == 0) { + tp = tp2; + break; + } + } + if (tp == NULL) { + return -1; + } + if (tp == curtab) { + wp = firstwin; + } else { + wp = tp->tp_firstwin; + } + } + for (; wp != NULL; wp = wp->w_next) { + if (--winnr == 0) { + return wp->handle; + } + } + } + return 0; +} + +static void win_id2tabwin(typval_T *const argvars, typval_T *const rettv) +{ + handle_T id = (handle_T)tv_get_number(&argvars[0]); + + int winnr = 1; + int tabnr = 1; + win_get_tabwin(id, &tabnr, &winnr); + + list_T *const list = tv_list_alloc_ret(rettv, 2); + tv_list_append_number(list, tabnr); + tv_list_append_number(list, winnr); +} + +win_T *win_id2wp(int id) +{ + return win_id2wp_tp(id, NULL); +} + +/// Return the window and tab pointer of window "id". +win_T *win_id2wp_tp(int id, tabpage_T **tpp) +{ + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->handle == id) { + if (tpp != NULL) { + *tpp = tp; + } + return wp; + } + } + + return NULL; +} + +static int win_id2win(typval_T *argvars) +{ + int nr = 1; + int id = (int)tv_get_number(&argvars[0]); + + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + if (wp->handle == id) { + return nr; + } + nr++; + } + return 0; +} + +void win_findbuf(typval_T *argvars, list_T *list) +{ + int bufnr = (int)tv_get_number(&argvars[0]); + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->w_buffer->b_fnum == bufnr) { + tv_list_append_number(list, wp->handle); + } + } +} + +/// Find window specified by "vp" in tabpage "tp". +/// +/// @param tp NULL for current tab page +win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp) +{ + int nr = (int)tv_get_number_chk(vp, NULL); + + if (nr < 0) { + return NULL; + } + + if (nr == 0) { + return curwin; + } + + // This method accepts NULL as an alias for curtab. + if (tp == NULL) { + tp = curtab; + } + + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + if (nr >= LOWEST_WIN_ID) { + if (wp->handle == nr) { + return wp; + } + } else if (--nr <= 0) { + return wp; + } + } + return NULL; +} + +/// Find a window: When using a Window ID in any tab page, when using a number +/// in the current tab page. +win_T *find_win_by_nr_or_id(typval_T *vp) +{ + int nr = (int)tv_get_number_chk(vp, NULL); + + if (nr >= LOWEST_WIN_ID) { + return win_id2wp((int)tv_get_number(vp)); + } + + return find_win_by_nr(vp, NULL); +} + +/// Find window specified by "wvp" in tabpage "tvp". +win_T *find_tabwin(typval_T *wvp, typval_T *tvp) +{ + win_T *wp = NULL; + tabpage_T *tp = NULL; + + if (wvp->v_type != VAR_UNKNOWN) { + if (tvp->v_type != VAR_UNKNOWN) { + long n = tv_get_number(tvp); + if (n >= 0) { + tp = find_tabpage((int)n); + } + } else { + tp = curtab; + } + + if (tp != NULL) { + wp = find_win_by_nr(wvp, tp); + } + } else { + wp = curwin; + } + + return wp; +} + +/// Get the layout of the given tab page for winlayout(). +static void get_framelayout(const frame_T *fr, list_T *l, bool outer) +{ + if (fr == NULL) { + return; + } + + list_T *fr_list; + if (outer) { + // outermost call from f_winlayout() + fr_list = l; + } else { + fr_list = tv_list_alloc(2); + tv_list_append_list(l, fr_list); + } + + if (fr->fr_layout == FR_LEAF) { + if (fr->fr_win != NULL) { + tv_list_append_string(fr_list, "leaf", -1); + tv_list_append_number(fr_list, fr->fr_win->handle); + } + } else { + tv_list_append_string(fr_list, fr->fr_layout == FR_ROW ? "row" : "col", -1); + + list_T *const win_list = tv_list_alloc(kListLenUnknown); + tv_list_append_list(fr_list, win_list); + const frame_T *child = fr->fr_child; + while (child != NULL) { + get_framelayout(child, win_list, false); + child = child->fr_next; + } + } +} + +/// Common code for tabpagewinnr() and winnr(). +static int get_winnr(tabpage_T *tp, typval_T *argvar) +{ + int nr = 1; + + win_T *twin = (tp == curtab) ? curwin : tp->tp_curwin; + if (argvar->v_type != VAR_UNKNOWN) { + bool invalid_arg = false; + const char *const arg = tv_get_string_chk(argvar); + if (arg == NULL) { + nr = 0; // Type error; errmsg already given. + } else if (strcmp(arg, "$") == 0) { + twin = (tp == curtab) ? lastwin : tp->tp_lastwin; + } else if (strcmp(arg, "#") == 0) { + twin = (tp == curtab) ? prevwin : tp->tp_prevwin; + if (twin == NULL) { + nr = 0; + } + } else { + // Extract the window count (if specified). e.g. winnr('3j') + char *endp; + long count = strtol((char *)arg, &endp, 10); + if (count <= 0) { + // if count is not specified, default to 1 + count = 1; + } + if (endp != NULL && *endp != '\0') { + if (strequal(endp, "j")) { + twin = win_vert_neighbor(tp, twin, false, count); + } else if (strequal(endp, "k")) { + twin = win_vert_neighbor(tp, twin, true, count); + } else if (strequal(endp, "h")) { + twin = win_horz_neighbor(tp, twin, true, count); + } else if (strequal(endp, "l")) { + twin = win_horz_neighbor(tp, twin, false, count); + } else { + invalid_arg = true; + } + } else { + invalid_arg = true; + } + } + + if (invalid_arg) { + semsg(_(e_invexpr2), arg); + nr = 0; + } + } + + if (nr > 0) { + for (win_T *wp = (tp == curtab) ? firstwin : tp->tp_firstwin; + wp != twin; wp = wp->w_next) { + if (wp == NULL) { + // didn't find it in this tabpage + nr = 0; + break; + } + nr++; + } + } + return nr; +} + +/// @return information about a window as a dictionary. +static dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr) +{ + dict_T *const dict = tv_dict_alloc(); + + // make sure w_botline is valid + validate_botline(wp); + + tv_dict_add_nr(dict, S_LEN("tabnr"), tpnr); + tv_dict_add_nr(dict, S_LEN("winnr"), winnr); + tv_dict_add_nr(dict, S_LEN("winid"), wp->handle); + tv_dict_add_nr(dict, S_LEN("height"), wp->w_height_inner); + tv_dict_add_nr(dict, S_LEN("winrow"), wp->w_winrow + 1); + tv_dict_add_nr(dict, S_LEN("topline"), wp->w_topline); + tv_dict_add_nr(dict, S_LEN("botline"), wp->w_botline - 1); + tv_dict_add_nr(dict, S_LEN("winbar"), wp->w_winbar_height); + tv_dict_add_nr(dict, S_LEN("width"), wp->w_width_inner); + tv_dict_add_nr(dict, S_LEN("bufnr"), wp->w_buffer->b_fnum); + tv_dict_add_nr(dict, S_LEN("wincol"), wp->w_wincol + 1); + tv_dict_add_nr(dict, S_LEN("textoff"), win_col_off(wp)); + tv_dict_add_nr(dict, S_LEN("terminal"), bt_terminal(wp->w_buffer)); + tv_dict_add_nr(dict, S_LEN("quickfix"), bt_quickfix(wp->w_buffer)); + tv_dict_add_nr(dict, S_LEN("loclist"), + (bt_quickfix(wp->w_buffer) && wp->w_llist_ref != NULL)); + + // Add a reference to window variables + tv_dict_add_dict(dict, S_LEN("variables"), wp->w_vars); + + return dict; +} + +/// @return information (variables, options, etc.) about a tab page +/// as a dictionary. +static dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx) +{ + dict_T *const dict = tv_dict_alloc(); + + tv_dict_add_nr(dict, S_LEN("tabnr"), tp_idx); + + list_T *const l = tv_list_alloc(kListLenMayKnow); + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + tv_list_append_number(l, (varnumber_T)wp->handle); + } + tv_dict_add_list(dict, S_LEN("windows"), l); + + // Make a reference to tabpage variables + tv_dict_add_dict(dict, S_LEN("variables"), tp->tp_vars); + + return dict; +} + +/// "gettabinfo()" function +void f_gettabinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tabpage_T *tparg = NULL; + + tv_list_alloc_ret(rettv, (argvars[0].v_type == VAR_UNKNOWN + ? 1 + : kListLenMayKnow)); + + if (argvars[0].v_type != VAR_UNKNOWN) { + // Information about one tab page + tparg = find_tabpage((int)tv_get_number_chk(&argvars[0], NULL)); + if (tparg == NULL) { + return; + } + } + + // Get information about a specific tab page or all tab pages + int tpnr = 0; + FOR_ALL_TABS(tp) { + tpnr++; + if (tparg != NULL && tp != tparg) { + continue; + } + dict_T *const d = get_tabpage_info(tp, tpnr); + tv_list_append_dict(rettv->vval.v_list, d); + if (tparg != NULL) { + return; + } + } +} + +/// "getwininfo()" function +void f_getwininfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wparg = NULL; + + tv_list_alloc_ret(rettv, kListLenMayKnow); + + if (argvars[0].v_type != VAR_UNKNOWN) { + wparg = win_id2wp((int)tv_get_number(&argvars[0])); + if (wparg == NULL) { + return; + } + } + + // Collect information about either all the windows across all the tab + // pages or one particular window. + int16_t tabnr = 0; + FOR_ALL_TABS(tp) { + tabnr++; + int16_t winnr = 0; + FOR_ALL_WINDOWS_IN_TAB(wp, tp) { + winnr++; + if (wparg != NULL && wp != wparg) { + continue; + } + dict_T *const d = get_win_info(wp, tabnr, winnr); + tv_list_append_dict(rettv->vval.v_list, d); + if (wparg != NULL) { + // found information about a specific window + return; + } + } + } +} + +/// "getwinpos({timeout})" function +void f_getwinpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, 2); + tv_list_append_number(rettv->vval.v_list, -1); + tv_list_append_number(rettv->vval.v_list, -1); +} + +/// "getwinposx()" function +void f_getwinposx(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; +} + +/// "getwinposy()" function +void f_getwinposy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = -1; +} + +/// "tabpagenr()" function +void f_tabpagenr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + int nr = 1; + + if (argvars[0].v_type != VAR_UNKNOWN) { + const char *const arg = tv_get_string_chk(&argvars[0]); + nr = 0; + if (arg != NULL) { + if (strcmp(arg, "$") == 0) { + nr = tabpage_index(NULL) - 1; + } else if (strcmp(arg, "#") == 0) { + nr = valid_tabpage(lastused_tabpage) ? tabpage_index(lastused_tabpage) : 0; + } else { + semsg(_(e_invexpr2), arg); + } + } + } else { + nr = tabpage_index(curtab); + } + rettv->vval.v_number = nr; +} + +/// "tabpagewinnr()" function +void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + int nr = 1; + tabpage_T *const tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { + nr = 0; + } else { + nr = get_winnr(tp, &argvars[1]); + } + rettv->vval.v_number = nr; +} + +/// "win_execute(win_id, command)" function +void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + // Return an empty string if something fails. + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + + int id = (int)tv_get_number(argvars); + tabpage_T *tp; + win_T *wp = win_id2wp_tp(id, &tp); + if (wp != NULL && tp != NULL) { + WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); + } +} + +/// "win_findbuf()" function +void f_win_findbuf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, kListLenMayKnow); + win_findbuf(argvars, rettv->vval.v_list); +} + +/// "win_getid()" function +void f_win_getid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = win_getid(argvars); +} + +/// "win_gotoid()" function +void f_win_gotoid(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + int id = (int)tv_get_number(&argvars[0]); + + if (cmdwin_type != 0) { + emsg(_(e_cmdwin)); + return; + } + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (wp->handle == id) { + goto_tabpage_win(tp, wp); + rettv->vval.v_number = 1; + return; + } + } +} + +/// "win_id2tabwin()" function +void f_win_id2tabwin(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_id2tabwin(argvars, rettv); +} + +/// "win_id2win()" function +void f_win_id2win(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = win_id2win(argvars); +} + +/// "win_move_separator()" function +void f_win_move_separator(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = false; + + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || wp->w_floating) { + return; + } + if (!win_valid(wp)) { + emsg(_(e_cannot_resize_window_in_another_tab_page)); + return; + } + + int offset = (int)tv_get_number(&argvars[1]); + win_drag_vsep_line(wp, offset); + rettv->vval.v_number = true; +} + +/// "win_move_statusline()" function +void f_win_move_statusline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp; + int offset; + + rettv->vval.v_number = false; + + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL || wp->w_floating) { + return; + } + if (!win_valid(wp)) { + emsg(_(e_cannot_resize_window_in_another_tab_page)); + return; + } + + offset = (int)tv_get_number(&argvars[1]); + win_drag_status_line(wp, offset); + rettv->vval.v_number = true; +} + +/// "win_screenpos()" function +void f_win_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_list_alloc_ret(rettv, 2); + const win_T *const wp = find_win_by_nr_or_id(&argvars[0]); + tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_winrow + 1); + tv_list_append_number(rettv->vval.v_list, wp == NULL ? 0 : wp->w_wincol + 1); +} + +/// Move the window wp into a new split of targetwin in a given direction +static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags) +{ + int height = wp->w_height; + win_T *oldwin = curwin; + + if (wp == targetwin || wp == aucmd_win) { + return; + } + + // Jump to the target window + if (curwin != targetwin) { + win_goto(targetwin); + } + + // Remove the old window and frame from the tree of frames + int dir; + (void)winframe_remove(wp, &dir, NULL); + win_remove(wp, NULL); + last_status(false); // may need to remove last status line + (void)win_comp_pos(); // recompute window positions + + // Split a window on the desired side and put the old window there + (void)win_split_ins(size, flags, wp, dir); + + // If splitting horizontally, try to preserve height + if (size == 0 && !(flags & WSP_VERT)) { + win_setheight_win(height, wp); + if (p_ea) { + win_equal(wp, true, 'v'); + } + } + + if (oldwin != curwin) { + win_goto(oldwin); + } +} + +/// "win_splitmove()" function +void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + win_T *targetwin = find_win_by_nr_or_id(&argvars[1]); + + if (wp == NULL || targetwin == NULL || wp == targetwin + || !win_valid(wp) || !win_valid(targetwin) + || win_valid_floating(wp) || win_valid_floating(targetwin)) { + emsg(_(e_invalwindow)); + rettv->vval.v_number = -1; + return; + } + + int flags = 0, size = 0; + + if (argvars[2].v_type != VAR_UNKNOWN) { + dict_T *d; + dictitem_T *di; + + if (argvars[2].v_type != VAR_DICT || argvars[2].vval.v_dict == NULL) { + emsg(_(e_invarg)); + return; + } + + d = argvars[2].vval.v_dict; + if (tv_dict_get_number(d, "vertical")) { + flags |= WSP_VERT; + } + if ((di = tv_dict_find(d, "rightbelow", -1)) != NULL) { + flags |= tv_get_number(&di->di_tv) ? WSP_BELOW : WSP_ABOVE; + } + size = (int)tv_dict_get_number(d, "size"); + } + + win_move_into_split(wp, targetwin, size, flags); +} + +/// "win_gettype(nr)" function +void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp = curwin; + + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + if (argvars[0].v_type != VAR_UNKNOWN) { + wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + rettv->vval.v_string = xstrdup("unknown"); + return; + } + } + if (wp == aucmd_win) { + rettv->vval.v_string = xstrdup("autocmd"); + } else if (wp->w_p_pvw) { + rettv->vval.v_string = xstrdup("preview"); + } else if (wp->w_floating) { + rettv->vval.v_string = xstrdup("popup"); + } else if (wp == curwin && cmdwin_type != 0) { + rettv->vval.v_string = xstrdup("command"); + } else if (bt_quickfix(wp->w_buffer)) { + rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix")); + } +} + +/// "getcmdwintype()" function +void f_getcmdwintype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->v_type = VAR_STRING; + rettv->vval.v_string = NULL; + rettv->vval.v_string = xmallocz(1); + rettv->vval.v_string[0] = (char)cmdwin_type; +} + +/// "winbufnr(nr)" function +void f_winbufnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + rettv->vval.v_number = -1; + } else { + rettv->vval.v_number = wp->w_buffer->b_fnum; + } +} + +/// "wincol()" function +void f_wincol(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + validate_cursor(); + rettv->vval.v_number = curwin->w_wcol + 1; +} + +/// "winheight(nr)" function +void f_winheight(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + rettv->vval.v_number = -1; + } else { + rettv->vval.v_number = wp->w_height_inner; + } +} + +/// "winlayout()" function +void f_winlayout(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tabpage_T *tp; + + tv_list_alloc_ret(rettv, 2); + + if (argvars[0].v_type == VAR_UNKNOWN) { + tp = curtab; + } else { + tp = find_tabpage((int)tv_get_number(&argvars[0])); + if (tp == NULL) { + return; + } + } + + get_framelayout(tp->tp_topframe, rettv->vval.v_list, true); +} + +/// "winline()" function +void f_winline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + validate_cursor(); + rettv->vval.v_number = curwin->w_wrow + 1; +} + +/// "winnr()" function +void f_winnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + rettv->vval.v_number = get_winnr(curtab, &argvars[0]); +} + +/// "winrestcmd()" function +void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + char_u buf[50]; + + garray_T ga; + ga_init(&ga, (int)sizeof(char), 70); + + // Do this twice to handle some window layouts properly. + for (int i = 0; i < 2; i++) { + int winnr = 1; + FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { + snprintf((char *)buf, sizeof(buf), "%dresize %d|", winnr, + wp->w_height); + ga_concat(&ga, (char *)buf); + snprintf((char *)buf, sizeof(buf), "vert %dresize %d|", winnr, + wp->w_width); + ga_concat(&ga, (char *)buf); + winnr++; + } + } + ga_append(&ga, NUL); + + rettv->vval.v_string = ga.ga_data; + rettv->v_type = VAR_STRING; +} + +/// "winrestview()" function +void f_winrestview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + dict_T *dict = argvars[0].vval.v_dict; + + if (argvars[0].v_type != VAR_DICT || dict == NULL) { + emsg(_(e_invarg)); + } else { + dictitem_T *di; + if ((di = tv_dict_find(dict, S_LEN("lnum"))) != NULL) { + curwin->w_cursor.lnum = (linenr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("col"))) != NULL) { + curwin->w_cursor.col = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("coladd"))) != NULL) { + curwin->w_cursor.coladd = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("curswant"))) != NULL) { + curwin->w_curswant = (colnr_T)tv_get_number(&di->di_tv); + curwin->w_set_curswant = false; + } + if ((di = tv_dict_find(dict, S_LEN("topline"))) != NULL) { + set_topline(curwin, (linenr_T)tv_get_number(&di->di_tv)); + } + if ((di = tv_dict_find(dict, S_LEN("topfill"))) != NULL) { + curwin->w_topfill = (int)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("leftcol"))) != NULL) { + curwin->w_leftcol = (colnr_T)tv_get_number(&di->di_tv); + } + if ((di = tv_dict_find(dict, S_LEN("skipcol"))) != NULL) { + curwin->w_skipcol = (colnr_T)tv_get_number(&di->di_tv); + } + + check_cursor(); + win_new_height(curwin, curwin->w_height); + win_new_width(curwin, curwin->w_width); + changed_window_setting(); + + if (curwin->w_topline <= 0) { + curwin->w_topline = 1; + } + if (curwin->w_topline > curbuf->b_ml.ml_line_count) { + curwin->w_topline = curbuf->b_ml.ml_line_count; + } + check_topfill(curwin, true); + } +} + +/// "winsaveview()" function +void f_winsaveview(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + tv_dict_alloc_ret(rettv); + dict_T *dict = rettv->vval.v_dict; + + tv_dict_add_nr(dict, S_LEN("lnum"), (varnumber_T)curwin->w_cursor.lnum); + tv_dict_add_nr(dict, S_LEN("col"), (varnumber_T)curwin->w_cursor.col); + tv_dict_add_nr(dict, S_LEN("coladd"), (varnumber_T)curwin->w_cursor.coladd); + update_curswant(); + tv_dict_add_nr(dict, S_LEN("curswant"), (varnumber_T)curwin->w_curswant); + + tv_dict_add_nr(dict, S_LEN("topline"), (varnumber_T)curwin->w_topline); + tv_dict_add_nr(dict, S_LEN("topfill"), (varnumber_T)curwin->w_topfill); + tv_dict_add_nr(dict, S_LEN("leftcol"), (varnumber_T)curwin->w_leftcol); + tv_dict_add_nr(dict, S_LEN("skipcol"), (varnumber_T)curwin->w_skipcol); +} + +/// "winwidth(nr)" function +void f_winwidth(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) +{ + win_T *wp = find_win_by_nr_or_id(&argvars[0]); + if (wp == NULL) { + rettv->vval.v_number = -1; + } else { + rettv->vval.v_number = wp->w_width_inner; + } +} + +/// Set "win" to be the curwin and "tp" to be the current tab page. +/// restore_win() MUST be called to undo, also when FAIL is returned. +/// No autocommands will be executed until restore_win() is called. +/// +/// @param no_display if true the display won't be affected, no redraw is +/// triggered, another tabpage access is limited. +/// +/// @return FAIL if switching to "win" failed. +int switch_win(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display) +{ + block_autocmds(); + return switch_win_noblock(switchwin, win, tp, no_display); +} + +// As switch_win() but without blocking autocommands. +int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool no_display) +{ + CLEAR_POINTER(switchwin); + switchwin->sw_curwin = curwin; + if (win == curwin) { + switchwin->sw_same_win = true; + } else { + // Disable Visual selection, because redrawing may fail. + switchwin->sw_visual_active = VIsual_active; + VIsual_active = false; + } + + if (tp != NULL) { + switchwin->sw_curtab = curtab; + if (no_display) { + curtab->tp_firstwin = firstwin; + curtab->tp_lastwin = lastwin; + curtab = tp; + firstwin = curtab->tp_firstwin; + lastwin = curtab->tp_lastwin; + } else { + goto_tabpage_tp(tp, false, false); + } + } + if (!win_valid(win)) { + return FAIL; + } + curwin = win; + curbuf = curwin->w_buffer; + return OK; +} + +// Restore current tabpage and window saved by switch_win(), if still valid. +// When "no_display" is true the display won't be affected, no redraw is +// triggered. +void restore_win(switchwin_T *switchwin, bool no_display) +{ + restore_win_noblock(switchwin, no_display); + unblock_autocmds(); +} + +// As restore_win() but without unblocking autocommands. +void restore_win_noblock(switchwin_T *switchwin, bool no_display) +{ + if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) { + if (no_display) { + curtab->tp_firstwin = firstwin; + curtab->tp_lastwin = lastwin; + curtab = switchwin->sw_curtab; + firstwin = curtab->tp_firstwin; + lastwin = curtab->tp_lastwin; + } else { + goto_tabpage_tp(switchwin->sw_curtab, false, false); + } + } + + if (!switchwin->sw_same_win) { + VIsual_active = switchwin->sw_visual_active; + } + + if (win_valid(switchwin->sw_curwin)) { + curwin = switchwin->sw_curwin; + curbuf = curwin->w_buffer; + } +} diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h new file mode 100644 index 0000000000..02e4457a1b --- /dev/null +++ b/src/nvim/eval/window.h @@ -0,0 +1,68 @@ +#ifndef NVIM_EVAL_WINDOW_H +#define NVIM_EVAL_WINDOW_H + +#include + +#include "nvim/buffer_defs.h" +#include "nvim/eval/typval_defs.h" + +/// Structure used by switch_win() to pass values to restore_win() +typedef struct { + win_T *sw_curwin; + tabpage_T *sw_curtab; + bool sw_same_win; ///< VIsual_active was not reset + bool sw_visual_active; +} switchwin_T; + +/// Execute a block of code in the context of window `wp` in tabpage `tp`. +/// Ensures the status line is redrawn and cursor position is valid if it is moved. +#define WIN_EXECUTE(wp, tp, block) \ + do { \ + win_T *const wp_ = (wp); \ + const pos_T curpos_ = wp_->w_cursor; \ + char cwd_[MAXPATHL]; \ + char autocwd_[MAXPATHL]; \ + bool apply_acd_ = false; \ + int cwd_status_ = FAIL; \ + /* Getting and setting directory can be slow on some systems, only do */ \ + /* this when the current or target window/tab have a local directory or */ \ + /* 'acd' is set. */ \ + if (curwin != wp \ + && (curwin->w_localdir != NULL || wp->w_localdir != NULL \ + || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \ + || p_acd)) { \ + cwd_status_ = os_dirname((char_u *)cwd_, MAXPATHL); \ + } \ + /* If 'acd' is set, check we are using that directory. If yes, then */ \ + /* apply 'acd' afterwards, otherwise restore the current directory. */ \ + if (cwd_status_ == OK && p_acd) { \ + do_autochdir(); \ + apply_acd_ = os_dirname((char_u *)autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \ + } \ + switchwin_T switchwin_; \ + if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \ + check_cursor(); \ + block; \ + } \ + restore_win_noblock(&switchwin_, true); \ + if (apply_acd_) { \ + do_autochdir(); \ + } else if (cwd_status_ == OK) { \ + os_chdir(cwd_); \ + } \ + /* Update the status line if the cursor moved. */ \ + if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \ + wp_->w_redr_status = true; \ + } \ + /* In case the command moved the cursor or changed the Visual area, */ \ + /* check it is valid. */ \ + check_cursor(); \ + if (VIsual_active) { \ + check_pos(curbuf, &VIsual); \ + } \ + } while (false) + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "eval/window.h.generated.h" +#endif +#endif // NVIM_EVAL_WINDOW_H -- cgit From 1282d6d59f085ef4d5261b8d60f3ac38d9478962 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 16:54:18 +0800 Subject: vim-patch:9.0.0910: setting lines in another buffer may not work well Problem: Setting lines in another buffer may not work well. Solution: Make sure the buffer being changed has a window. (issue vim/vim#11558) https://github.com/vim/vim/commit/c934bfa1b765505e5fc491f2ee7cc106894cafc8 Co-authored-by: Bram Moolenaar --- src/nvim/eval/buffer.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 41ba8d2e88..fbe8b23477 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -76,25 +76,35 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ { linenr_T lnum = lnum_arg + (append ? 1 : 0); long added = 0; - buf_T *curbuf_save = NULL; win_T *curwin_save = NULL; - const bool is_curbuf = buf == curbuf; + aco_save_T aco; + int using_aco = false; const bool save_VIsual_active = VIsual_active; // When using the current buffer ml_mfp will be set if needed. Useful when // setline() is used on startup. For other buffers the buffer must be // loaded. + const bool is_curbuf = buf == curbuf; if (buf == NULL || (!is_curbuf && buf->b_ml.ml_mfp == NULL) || lnum < 1) { rettv->vval.v_number = 1; // FAIL return; } if (!is_curbuf) { + // Set "curbuf" to the buffer being changed. Then make sure there is a + // window for it to handle any side effects. VIsual_active = false; - curbuf_save = curbuf; curwin_save = curwin; curbuf = buf; - find_win_for_curbuf(); + find_win_for_curbuf(); // simplest: find existing window for "buf" + + if (curwin->w_buffer != buf) { + // No existing window for this buffer. It is dangerous to have + // curwin->w_buffer differ from "curbuf", use the autocmd window. + curbuf = curwin->w_buffer; + aucmd_prepbuf(&aco, buf); + using_aco = true; + } } linenr_T append_lnum; @@ -193,8 +203,12 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ done: if (!is_curbuf) { - curbuf = curbuf_save; - curwin = curwin_save; + if (using_aco) { + aucmd_restbuf(&aco); + } else { + curwin = curwin_save; + curbuf = curwin->w_buffer; + } VIsual_active = save_VIsual_active; } } -- cgit From 05f7d2badead3ba399578c2392e1d9b790df475d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 16:55:46 +0800 Subject: vim-patch:9.0.0914: deletebufline() may move marks in the wrong window Problem: deletebufline() may move marks in the wrong window. Solution: Find a window for the buffer being changed. (closes vim/vim#11583) https://github.com/vim/vim/commit/228e422855d43965f2c3319ff0cdc26ea422c10f Cherry-pick code change from patch 9.0.0961. Co-authored-by: Bram Moolenaar --- src/nvim/eval/buffer.c | 106 ++++++++++++++++++++++++++++++------------------- 1 file changed, 65 insertions(+), 41 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index fbe8b23477..4816a955a8 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -28,6 +28,13 @@ #include "nvim/undo.h" #include "nvim/vim.h" +typedef struct { + win_T *cob_curwin_save; + aco_save_T cob_aco; + int cob_using_aco; + int cob_save_VIsual_active; +} cob_T; + #ifdef INCLUDE_GENERATED_DECLARATIONS # include "eval/buffer.c.generated.h" #endif @@ -60,14 +67,57 @@ buf_T *find_buffer(typval_T *avar) /// If there is a window for "curbuf", make it the current window. static void find_win_for_curbuf(void) { - for (wininfo_T *wip = curbuf->b_wininfo; wip != NULL; wip = wip->wi_next) { - if (wip->wi_win != NULL) { + wininfo_T *wip; + + // The b_wininfo list should have the windows that recently contained the + // buffer, going over this is faster than going over all the windows. + // Do check the buffer is still there. + FOR_ALL_BUF_WININFO(curbuf, wip) { + if (wip->wi_win != NULL && wip->wi_win->w_buffer == curbuf) { curwin = wip->wi_win; break; } } } +/// Used before making a change in "buf", which is not the current one: Make +/// "buf" the current buffer and find a window for this buffer, so that side +/// effects are done correctly (e.g., adjusting marks). +/// +/// Information is saved in "cob" and MUST be restored by calling +/// change_other_buffer_restore(). +static void change_other_buffer_prepare(cob_T *cob, buf_T *buf) +{ + CLEAR_POINTER(cob); + + // Set "curbuf" to the buffer being changed. Then make sure there is a + // window for it to handle any side effects. + cob->cob_save_VIsual_active = VIsual_active; + VIsual_active = false; + cob->cob_curwin_save = curwin; + curbuf = buf; + find_win_for_curbuf(); // simplest: find existing window for "buf" + + if (curwin->w_buffer != buf) { + // No existing window for this buffer. It is dangerous to have + // curwin->w_buffer differ from "curbuf", use the autocmd window. + curbuf = curwin->w_buffer; + aucmd_prepbuf(&cob->cob_aco, buf); + cob->cob_using_aco = true; + } +} + +static void change_other_buffer_restore(cob_T *cob) +{ + if (cob->cob_using_aco) { + aucmd_restbuf(&cob->cob_aco); + } else { + curwin = cob->cob_curwin_save; + curbuf = curwin->w_buffer; + } + VIsual_active = cob->cob_save_VIsual_active; +} + /// Set line or list of lines in buffer "buf" to "lines". /// Any type is allowed and converted to a string. static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_T *lines, @@ -76,10 +126,6 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ { linenr_T lnum = lnum_arg + (append ? 1 : 0); long added = 0; - win_T *curwin_save = NULL; - aco_save_T aco; - int using_aco = false; - const bool save_VIsual_active = VIsual_active; // When using the current buffer ml_mfp will be set if needed. Useful when // setline() is used on startup. For other buffers the buffer must be @@ -90,21 +136,11 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ return; } + // After this don't use "return", goto "cleanup"! + cob_T cob; if (!is_curbuf) { - // Set "curbuf" to the buffer being changed. Then make sure there is a - // window for it to handle any side effects. - VIsual_active = false; - curwin_save = curwin; - curbuf = buf; - find_win_for_curbuf(); // simplest: find existing window for "buf" - - if (curwin->w_buffer != buf) { - // No existing window for this buffer. It is dangerous to have - // curwin->w_buffer differ from "curbuf", use the autocmd window. - curbuf = curwin->w_buffer; - aucmd_prepbuf(&aco, buf); - using_aco = true; - } + // set "curbuf" to "buf" and find a window for this buffer + change_other_buffer_prepare(&cob, buf); } linenr_T append_lnum; @@ -127,7 +163,7 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ if (lnum > curbuf->b_ml.ml_line_count) { rettv->vval.v_number = 1; // FAIL } - goto done; + goto cleanup; } li = tv_list_first(l); } else { @@ -201,15 +237,9 @@ static void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, typval_ update_topline(curwin); } -done: +cleanup: if (!is_curbuf) { - if (using_aco) { - aucmd_restbuf(&aco); - } else { - curwin = curwin_save; - curbuf = curwin->w_buffer; - } - VIsual_active = save_VIsual_active; + change_other_buffer_restore(&cob); } } @@ -388,8 +418,6 @@ void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (buf == NULL) { return; } - const bool is_curbuf = buf == curbuf; - const bool save_VIsual_active = VIsual_active; linenr_T last; const linenr_T first = tv_get_lnum_buf(&argvars[1], buf); @@ -407,16 +435,14 @@ void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } - buf_T *curbuf_save = NULL; - win_T *curwin_save = NULL; // After this don't use "return", goto "cleanup"! + const bool is_curbuf = buf == curbuf; + cob_T cob; if (!is_curbuf) { - VIsual_active = false; - curbuf_save = curbuf; - curwin_save = curwin; - curbuf = buf; - find_win_for_curbuf(); + // set "curbuf" to "buf" and find a window for this buffer + change_other_buffer_prepare(&cob, buf); } + if (last > curbuf->b_ml.ml_line_count) { last = curbuf->b_ml.ml_line_count; } @@ -455,9 +481,7 @@ void f_deletebufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) cleanup: if (!is_curbuf) { - curbuf = curbuf_save; - curwin = curwin_save; - VIsual_active = save_VIsual_active; + change_other_buffer_restore(&cob); } } -- cgit From 273358651af6b6d172944cd1b1b41a9869d53b10 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 20:09:07 +0800 Subject: refactor: buffer_ensure_loaded() Cherry-picked from Vim patch 8.1.1612. --- src/nvim/eval/buffer.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 4816a955a8..72eb0f8d67 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -302,13 +302,8 @@ void f_bufload(typval_T *argvars, typval_T *unused, EvalFuncData fptr) { buf_T *buf = get_buf_arg(&argvars[0]); - if (buf != NULL && buf->b_ml.ml_mfp == NULL) { - aco_save_T aco; - - aucmd_prepbuf(&aco, buf); - swap_exists_action = SEA_NONE; - open_buffer(false, NULL, 0); - aucmd_restbuf(&aco); + if (buf != NULL) { + buffer_ensure_loaded(buf); } } -- cgit From 3173d07564e7cdf0834099a379f0faf480c76224 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 29 Nov 2022 18:20:11 +0800 Subject: vim-patch:9.0.0965: using one window for executing autocommands is insufficient Problem: Using one window for executing autocommands is insufficient. Solution: Use up to five windows for executing autocommands. https://github.com/vim/vim/commit/e76062c078debed0df818f70e4db14ad7a7cb53a N/A patches for version.c: vim-patch:9.0.0966: some compilers don't allow a declaration after a label Problem: Some compilers don't allow a declaration after a label. Solution: Move the declaration to the start of the block. (John Marriott) https://github.com/vim/vim/commit/f86490ed4fdab213a28f667abd055c023a73d645 Co-authored-by: Bram Moolenaar --- src/nvim/eval/buffer.c | 6 +++++- src/nvim/eval/vars.c | 12 +++++++----- src/nvim/eval/window.c | 4 ++-- 3 files changed, 14 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 72eb0f8d67..6ebf54ef0f 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -86,6 +86,8 @@ static void find_win_for_curbuf(void) /// /// Information is saved in "cob" and MUST be restored by calling /// change_other_buffer_restore(). +/// +/// If this fails then "curbuf" will not be equal to "buf". static void change_other_buffer_prepare(cob_T *cob, buf_T *buf) { CLEAR_POINTER(cob); @@ -103,7 +105,9 @@ static void change_other_buffer_prepare(cob_T *cob, buf_T *buf) // curwin->w_buffer differ from "curbuf", use the autocmd window. curbuf = curwin->w_buffer; aucmd_prepbuf(&cob->cob_aco, buf); - cob->cob_using_aco = true; + if (curbuf == buf) { + cob->cob_using_aco = true; + } } } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 5459eac5bf..f002071ad2 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1800,13 +1800,15 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (*varname == '&') { aco_save_T aco; - // set curbuf to be our buf, temporarily + // Set curbuf to be our buf, temporarily. aucmd_prepbuf(&aco, buf); + if (curbuf == buf) { + // Only when it worked to set "curbuf". + set_option_from_tv(varname + 1, varp); - set_option_from_tv(varname + 1, varp); - - // reset notion of buffer - aucmd_restbuf(&aco); + // reset notion of buffer + aucmd_restbuf(&aco); + } } else { const size_t varname_len = strlen(varname); char *const bufvarname = xmalloc(varname_len + 3); diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index d6c761bc66..7cb346216d 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -590,7 +590,7 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags int height = wp->w_height; win_T *oldwin = curwin; - if (wp == targetwin || wp == aucmd_win) { + if (wp == targetwin || is_aucmd_win(wp)) { return; } @@ -674,7 +674,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) return; } } - if (wp == aucmd_win) { + if (is_aucmd_win(wp)) { rettv->vval.v_string = xstrdup("autocmd"); } else if (wp->w_p_pvw) { rettv->vval.v_string = xstrdup("preview"); -- cgit From 1145a9b2485a4e5072cffe28a958da983cd59e84 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Dec 2022 20:39:24 +0800 Subject: feat(aucmd_win): allow crazy things with hidden buffers (#21250) Problem: Crash when doing crazy things with hidden buffers. Solution: Dynamically allocate the list of autocommand windows. --- src/nvim/eval/buffer.c | 6 +----- src/nvim/eval/vars.c | 10 ++++------ 2 files changed, 5 insertions(+), 11 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 6ebf54ef0f..72eb0f8d67 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -86,8 +86,6 @@ static void find_win_for_curbuf(void) /// /// Information is saved in "cob" and MUST be restored by calling /// change_other_buffer_restore(). -/// -/// If this fails then "curbuf" will not be equal to "buf". static void change_other_buffer_prepare(cob_T *cob, buf_T *buf) { CLEAR_POINTER(cob); @@ -105,9 +103,7 @@ static void change_other_buffer_prepare(cob_T *cob, buf_T *buf) // curwin->w_buffer differ from "curbuf", use the autocmd window. curbuf = curwin->w_buffer; aucmd_prepbuf(&cob->cob_aco, buf); - if (curbuf == buf) { - cob->cob_using_aco = true; - } + cob->cob_using_aco = true; } } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index f002071ad2..d37631af8c 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1802,13 +1802,11 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // Set curbuf to be our buf, temporarily. aucmd_prepbuf(&aco, buf); - if (curbuf == buf) { - // Only when it worked to set "curbuf". - set_option_from_tv(varname + 1, varp); - // reset notion of buffer - aucmd_restbuf(&aco); - } + set_option_from_tv(varname + 1, varp); + + // reset notion of buffer + aucmd_restbuf(&aco); } else { const size_t varname_len = strlen(varname); char *const bufvarname = xmalloc(varname_len + 3); -- cgit From 70ac0c9358251bf54f29a30a369880d94680ace7 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 2 Dec 2022 21:00:27 +0800 Subject: vim-patch:8.2.3889: duplicate code for translating script-local function name Problem: Duplicate code for translating script-local function name. Solution: Move the code to get_scriptlocal_funcname(). (Yegappan Lakshmanan, closes vim/vim#9393) https://github.com/vim/vim/commit/e7f4abd38b6e05100c699900c8f87281e363beb2 Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/userfunc.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 359ce08554..a37613dca9 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1930,6 +1930,40 @@ theend: return (char_u *)name; } +/// If the "funcname" starts with "s:" or "", then expands it to the +/// current script ID and returns the expanded function name. The caller should +/// free the returned name. If not called from a script context or the function +/// name doesn't start with these prefixes, then returns NULL. +/// This doesn't check whether the script-local function exists or not. +char *get_scriptlocal_funcname(char *funcname) +{ + if (funcname == NULL) { + return NULL; + } + + if (strncmp(funcname, "s:", 2) != 0 + && strncmp(funcname, "", 5) != 0) { + // The function name is not a script-local function name + return NULL; + } + + if (!SCRIPT_ID_VALID(current_sctx.sc_sid)) { + emsg(_(e_usingsid)); + return NULL; + } + + char sid_buf[25]; + // Expand s: and prefix into nr_ + snprintf(sid_buf, sizeof(sid_buf), "%" PRId64 "_", + (int64_t)current_sctx.sc_sid); + const int off = *funcname == 's' ? 2 : 5; + char *newname = xmalloc(strlen(sid_buf) + strlen(funcname + off) + 1); + STRCPY(newname, sid_buf); + STRCAT(newname, funcname + off); + + return newname; +} + /// Call trans_function_name(), except that a lambda is returned as-is. /// Returns the name in allocated memory. char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) -- cgit From 5199c333a072933d6a2bb8b9e99076761da7396a Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 6 Dec 2022 09:15:04 +0800 Subject: vim-patch:9.0.1015: without /dev/urandom srand() seed is too predictable (#21303) Problem: Without /dev/urandom srand() seed is too predictable. Solution: Use micro seconds and XOR with process ID. (Yasuhiro Matsumoto, closes vim/vim#11656) https://github.com/vim/vim/commit/f0a9c004825ab686270ee57260652cce25e61049 Co-authored-by: Yasuhiro Matsumoto --- src/nvim/eval/funcs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index ec62c583a6..017e8e502c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -5145,10 +5145,11 @@ static void init_srand(uint32_t *const x) } } if (dev_urandom_state != OK) { - // Reading /dev/urandom doesn't work, fall back to time(). + // Reading /dev/urandom doesn't work, fall back to os_hrtime() XOR with process ID #endif // uncrustify:off - *x = (uint32_t)time(NULL); + *x = (uint32_t)os_hrtime(); + *x ^= (uint32_t)os_get_pid(); #ifndef MSWIN } #endif -- cgit From 1e2cc688891c789f02699f9c7e0bffd435794310 Mon Sep 17 00:00:00 2001 From: Enan Ajmain <3nan.ajmain@gmail.com> Date: Fri, 9 Dec 2022 02:55:50 +0600 Subject: fix(chansend): sending lines to terminal in reverse order on Windows #19315 Problem: `chansend()` on Windows sends lines in reverse order. Cause: Using \n instead of \r\n for newlines on Windows. Solution: on Windows, use CRLF newline characters. Fixes #18501 --- src/nvim/eval/funcs.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 017e8e502c..8bdb91ebf1 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -648,6 +648,14 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ptrdiff_t input_len = 0; char *input = NULL; + uint64_t id = (uint64_t)argvars[0].vval.v_number; +#ifdef UNIX + bool crlf = false; +#else + Channel *chan = find_channel(id); + bool crlf = (chan != NULL && chan->term) ? true: false; +#endif + if (argvars[1].v_type == VAR_BLOB) { const blob_T *const b = argvars[1].vval.v_blob; input_len = tv_blob_len(b); @@ -655,7 +663,7 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) input = xmemdup(b->bv_ga.ga_data, (size_t)input_len); } } else { - input = save_tv_as_string(&argvars[1], &input_len, false); + input = save_tv_as_string(&argvars[1], &input_len, false, crlf); } if (!input) { @@ -663,7 +671,6 @@ static void f_chansend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // or there is no input to send. return; } - uint64_t id = (uint64_t)argvars[0].vval.v_number; const char *error = NULL; rettv->vval.v_number = (varnumber_T)channel_send(id, input, (size_t)input_len, true, &error); if (error) { -- cgit From b969844398bc8d6021f8da286819c22aa73e1535 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 17 Dec 2022 08:50:17 +0800 Subject: vim-patch:8.2.1210: using ht_used when looping through a hashtab is less reliable Problem: Using ht_used when looping through a hashtab is less reliable. Solution: Use ht_changed in a few more places. https://github.com/vim/vim/commit/1f22cc5cdb2da867d6bbf54dd371f279c38a2f56 Co-authored-by: Bram Moolenaar --- src/nvim/eval/userfunc.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index a37613dca9..69b074ab99 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1297,7 +1297,7 @@ void free_all_functions(void) ufunc_T *fp; uint64_t skipped = 0; uint64_t todo = 1; - uint64_t used; + int changed; // Clean up the current_funccal chain and the funccal stack. while (current_funccal != NULL) { @@ -1321,9 +1321,9 @@ void free_all_functions(void) if (func_name_refcount((char_u *)fp->uf_name)) { skipped++; } else { - used = func_hashtab.ht_used; + changed = func_hashtab.ht_changed; func_clear(fp, true); - if (used != func_hashtab.ht_used) { + if (changed != func_hashtab.ht_changed) { skipped = 0; break; } @@ -1993,8 +1993,8 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) /// Otherwise functions matching "regmatch". static void list_functions(regmatch_T *regmatch) { - const size_t used = func_hashtab.ht_used; - size_t todo = used; + const int changed = func_hashtab.ht_changed; + size_t todo = func_hashtab.ht_used; const hashitem_T *const ht_array = func_hashtab.ht_array; for (const hashitem_T *hi = ht_array; todo > 0 && !got_int; hi++) { @@ -2008,7 +2008,7 @@ static void list_functions(regmatch_T *regmatch) : (!isdigit(*fp->uf_name) && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { list_func_head(fp, false, false); - if (used != func_hashtab.ht_used || ht_array != func_hashtab.ht_array) { + if (changed != func_hashtab.ht_changed) { emsg(_("E454: function list was modified")); return; } @@ -2730,15 +2730,17 @@ bool function_exists(const char *const name, bool no_deref) char *get_user_func_name(expand_T *xp, int idx) { static size_t done; + static int changed; static hashitem_T *hi; ufunc_T *fp; if (idx == 0) { done = 0; hi = func_hashtab.ht_array; + changed = func_hashtab.ht_changed; } assert(hi); - if (done < func_hashtab.ht_used) { + if (changed == func_hashtab.ht_changed && done < func_hashtab.ht_used) { if (done++ > 0) { hi++; } -- cgit From 30f606fc602f835fbed869140d3d658e24129c22 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Fri, 23 Dec 2022 13:56:32 +0800 Subject: fix(options): restore exists() behavior for options (#21510) Duplicating get_option_value() logic for an obscure future refactor isn't really worthwhile, and findoption() isn't used anywhere else outside the options code. --- src/nvim/eval/funcs.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 8bdb91ebf1..eb34869fac 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1721,14 +1721,9 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) xfree(exp); } } else if (*p == '&' || *p == '+') { // Option. - bool working = (*p == '+'); // whether option needs to be working - int opt_flags; - - if (find_option_end(&p, &opt_flags) != NULL) { - int opt_idx = findoption(p); - n = (opt_idx >= 0 && (!working || get_varp_scope(get_option(opt_idx), opt_flags) != NULL)); - } else { - n = false; + n = (get_option_tv(&p, NULL, true) == OK); + if (*skipwhite(p) != NUL) { + n = false; // Trailing garbage. } } else if (*p == '*') { // Internal or user defined function. n = function_exists(p + 1, false); -- cgit From bf459641a85ff1b4f24196ba6345de7bb8159884 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 28 Dec 2022 10:05:03 +0800 Subject: refactor(f_has): remove wrong comment (#21561) Only one of "fork" and "system" should be defined. Also change the line above "win32" to match Vim. --- src/nvim/eval/funcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index eb34869fac..94c9ac7e6c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3036,7 +3036,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) #ifdef UNIX "unix", #endif -#if defined(MSWIN) +#ifdef MSWIN "win32", #endif #ifdef _WIN64 @@ -3127,7 +3127,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "spell", "syntax", #if !defined(UNIX) - "system", // TODO(SplinterOfChaos): This IS defined for UNIX! + "system", #endif "tablineat", "tag_binary", -- cgit From 4dd793a256fefb481159f9f93bf7572391e266de Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 3 Jan 2023 14:55:00 +0800 Subject: vim-patch:9.0.1132: code is indented more than needed (#21626) Problem: Code is indented more than needed. Solution: Use an early return to reduce indentation. (Yegappan Lakshmanan, closes vim/vim#11769) https://github.com/vim/vim/commit/dc4daa3a3915fba11ac87d27977240d9a5e0d47d Omit expand_autoload_callback(): only applies to Vim9 script. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 182 +++++++++++++++++++++++++++---------------------- src/nvim/eval/vars.c | 106 ++++++++++++++-------------- src/nvim/eval/window.c | 6 +- 3 files changed, 159 insertions(+), 135 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 94c9ac7e6c..d2bbdc7a96 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1216,19 +1216,21 @@ static void f_debugbreak(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int pid = (int)tv_get_number(&argvars[0]); if (pid == 0) { emsg(_(e_invarg)); - } else { + return; + } + #ifdef MSWIN - HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid); + if (hProcess == NULL) { + return; + } - if (hProcess != NULL) { - DebugBreakProcess(hProcess); - CloseHandle(hProcess); - rettv->vval.v_number = OK; - } + DebugBreakProcess(hProcess); + CloseHandle(hProcess); + rettv->vval.v_number = OK; #else - uv_kill(pid, SIGINT); + uv_kill(pid, SIGINT); #endif - } } /// "deepcopy()" function @@ -2099,14 +2101,16 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { float_T f; - if (tv_get_float_chk(argvars, &f)) { - if (f <= (float_T) - VARNUMBER_MAX + DBL_EPSILON) { - rettv->vval.v_number = -VARNUMBER_MAX; - } else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) { - rettv->vval.v_number = VARNUMBER_MAX; - } else { - rettv->vval.v_number = (varnumber_T)f; - } + if (!tv_get_float_chk(argvars, &f)) { + return; + } + + if (f <= (float_T) - VARNUMBER_MAX + DBL_EPSILON) { + rettv->vval.v_number = -VARNUMBER_MAX; + } else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) { + rettv->vval.v_number = VARNUMBER_MAX; + } else { + rettv->vval.v_number = (varnumber_T)f; } } @@ -3435,33 +3439,36 @@ static void f_index(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) emsg(_(e_listblobreq)); return; } + list_T *const l = argvars[0].vval.v_list; - if (l != NULL) { - listitem_T *item = tv_list_first(l); - if (argvars[2].v_type != VAR_UNKNOWN) { - bool error = false; + if (l == NULL) { + return; + } - // Start at specified item. - idx = tv_list_uidx(l, (int)tv_get_number_chk(&argvars[2], &error)); - if (error || idx == -1) { + listitem_T *item = tv_list_first(l); + if (argvars[2].v_type != VAR_UNKNOWN) { + bool error = false; + + // Start at specified item. + idx = tv_list_uidx(l, (int)tv_get_number_chk(&argvars[2], &error)); + if (error || idx == -1) { + item = NULL; + } else { + item = tv_list_find(l, (int)idx); + assert(item != NULL); + } + if (argvars[3].v_type != VAR_UNKNOWN) { + ic = !!tv_get_number_chk(&argvars[3], &error); + if (error) { item = NULL; - } else { - item = tv_list_find(l, (int)idx); - assert(item != NULL); - } - if (argvars[3].v_type != VAR_UNKNOWN) { - ic = !!tv_get_number_chk(&argvars[3], &error); - if (error) { - item = NULL; - } } } + } - for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { - if (tv_equal(TV_LIST_ITEM_TV(item), &argvars[1], ic, false)) { - rettv->vval.v_number = idx; - break; - } + for (; item != NULL; item = TV_LIST_ITEM_NEXT(l, item), idx++) { + if (tv_equal(TV_LIST_ITEM_TV(item), &argvars[1], ic, false)) { + rettv->vval.v_number = idx; + break; } } } @@ -5311,13 +5318,16 @@ static void f_range(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (stride == 0) { emsg(_("E726: Stride is zero")); - } else if (stride > 0 ? end + 1 < start : end - 1 > start) { + return; + } + if (stride > 0 ? end + 1 < start : end - 1 > start) { emsg(_("E727: Start past end")); - } else { - tv_list_alloc_ret(rettv, (end - start) / stride); - for (varnumber_T i = start; stride > 0 ? i <= end : i >= end; i += stride) { - tv_list_append_number(rettv->vval.v_list, i); - } + return; + } + + tv_list_alloc_ret(rettv, (end - start) / stride); + for (varnumber_T i = start; stride > 0 ? i <= end : i >= end; i += stride) { + tv_list_append_number(rettv->vval.v_list, i); } } @@ -7009,31 +7019,35 @@ static void set_position(typval_T *argvars, typval_T *rettv, bool charpos) rettv->vval.v_number = -1; const char *const name = tv_get_string_chk(argvars); - if (name != NULL) { - pos_T pos; - int fnum; - if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) == OK) { - if (pos.col != MAXCOL && --pos.col < 0) { - pos.col = 0; - } - if (name[0] == '.' && name[1] == NUL) { - // set cursor; "fnum" is ignored - curwin->w_cursor = pos; - if (curswant >= 0) { - curwin->w_curswant = curswant - 1; - curwin->w_set_curswant = false; - } - check_cursor(); - rettv->vval.v_number = 0; - } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { - // set mark - if (setmark_pos((uint8_t)name[1], &pos, fnum, NULL) == OK) { - rettv->vval.v_number = 0; - } - } else { - emsg(_(e_invarg)); - } + if (name == NULL) { + return; + } + + pos_T pos; + int fnum; + if (list2fpos(&argvars[1], &pos, &fnum, &curswant, charpos) != OK) { + return; + } + + if (pos.col != MAXCOL && --pos.col < 0) { + pos.col = 0; + } + if (name[0] == '.' && name[1] == NUL) { + // set cursor; "fnum" is ignored + curwin->w_cursor = pos; + if (curswant >= 0) { + curwin->w_curswant = curswant - 1; + curwin->w_set_curswant = false; + } + check_cursor(); + rettv->vval.v_number = 0; + } else if (name[0] == '\'' && name[1] != NUL && name[2] == NUL) { + // set mark + if (setmark_pos((uint8_t)name[1], &pos, fnum, NULL) == OK) { + rettv->vval.v_number = 0; } + } else { + emsg(_(e_invarg)); } } @@ -7051,23 +7065,25 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt } dict_T *d = argvars[0].vval.v_dict; - if (d != NULL) { - char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false); - if (csearch != NULL) { - int pcc[MAX_MCO]; - const int c = utfc_ptr2char((char *)csearch, pcc); - set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch)); - } + if (d == NULL) { + return; + } - dictitem_T *di = tv_dict_find(d, S_LEN("forward")); - if (di != NULL) { - set_csearch_direction(tv_get_number(&di->di_tv) ? FORWARD : BACKWARD); - } + char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false); + if (csearch != NULL) { + int pcc[MAX_MCO]; + const int c = utfc_ptr2char((char *)csearch, pcc); + set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch)); + } - di = tv_dict_find(d, S_LEN("until")); - if (di != NULL) { - set_csearch_until(!!tv_get_number(&di->di_tv)); - } + dictitem_T *di = tv_dict_find(d, S_LEN("forward")); + if (di != NULL) { + set_csearch_direction(tv_get_number(&di->di_tv) ? FORWARD : BACKWARD); + } + + di = tv_dict_find(d, S_LEN("until")); + if (di != NULL) { + set_csearch_until(!!tv_get_number(&di->di_tv)); } } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index d37631af8c..ee7a8a0dd0 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1654,25 +1654,27 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) const char *varname = tv_get_string_chk(&argvars[off + 1]); typval_T *varp = &argvars[off + 2]; - if (win != NULL && varname != NULL && varp != NULL) { - bool need_switch_win = !(tp == curtab && win == curwin); - switchwin_T switchwin; - if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) { - if (*varname == '&') { - set_option_from_tv(varname + 1, varp); - } else { - const size_t varname_len = strlen(varname); - char *const winvarname = xmalloc(varname_len + 3); - memcpy(winvarname, "w:", 2); - memcpy(winvarname + 2, varname, varname_len + 1); - set_var(winvarname, varname_len + 2, varp, true); - xfree(winvarname); - } - } - if (need_switch_win) { - restore_win(&switchwin, true); + if (win == NULL || varname == NULL || varp == NULL) { + return; + } + + bool need_switch_win = !(tp == curtab && win == curwin); + switchwin_T switchwin; + if (!need_switch_win || switch_win(&switchwin, win, tp, true) == OK) { + if (*varname == '&') { + set_option_from_tv(varname + 1, varp); + } else { + const size_t varname_len = strlen(varname); + char *const winvarname = xmalloc(varname_len + 3); + memcpy(winvarname, "w:", 2); + memcpy(winvarname + 2, varname, varname_len + 1); + set_var(winvarname, varname_len + 2, varp, true); + xfree(winvarname); } } + if (need_switch_win) { + restore_win(&switchwin, true); + } } bool var_exists(const char *var) @@ -1755,21 +1757,23 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *const varname = tv_get_string_chk(&argvars[1]); typval_T *const varp = &argvars[2]; - if (varname != NULL && tp != NULL) { - tabpage_T *const save_curtab = curtab; - goto_tabpage_tp(tp, false, false); + if (varname == NULL || tp == NULL) { + return; + } - const size_t varname_len = strlen(varname); - char *const tabvarname = xmalloc(varname_len + 3); - memcpy(tabvarname, "t:", 2); - memcpy(tabvarname + 2, varname, varname_len + 1); - set_var(tabvarname, varname_len + 2, varp, true); - xfree(tabvarname); - - // Restore current tabpage. - if (valid_tabpage(save_curtab)) { - goto_tabpage_tp(save_curtab, false, false); - } + tabpage_T *const save_curtab = curtab; + goto_tabpage_tp(tp, false, false); + + const size_t varname_len = strlen(varname); + char *const tabvarname = xmalloc(varname_len + 3); + memcpy(tabvarname, "t:", 2); + memcpy(tabvarname + 2, varname, varname_len + 1); + set_var(tabvarname, varname_len + 2, varp, true); + xfree(tabvarname); + + // Restore current tabpage. + if (valid_tabpage(save_curtab)) { + goto_tabpage_tp(save_curtab, false, false); } } @@ -1796,27 +1800,29 @@ void f_setbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) buf_T *const buf = tv_get_buf(&argvars[0], false); typval_T *varp = &argvars[2]; - if (buf != NULL && varname != NULL) { - if (*varname == '&') { - aco_save_T aco; + if (buf == NULL || varname == NULL) { + return; + } - // Set curbuf to be our buf, temporarily. - aucmd_prepbuf(&aco, buf); + if (*varname == '&') { + aco_save_T aco; - set_option_from_tv(varname + 1, varp); + // Set curbuf to be our buf, temporarily. + aucmd_prepbuf(&aco, buf); - // reset notion of buffer - aucmd_restbuf(&aco); - } else { - const size_t varname_len = strlen(varname); - char *const bufvarname = xmalloc(varname_len + 3); - buf_T *const save_curbuf = curbuf; - curbuf = buf; - memcpy(bufvarname, "b:", 2); - memcpy(bufvarname + 2, varname, varname_len + 1); - set_var(bufvarname, varname_len + 2, varp, true); - xfree(bufvarname); - curbuf = save_curbuf; - } + set_option_from_tv(varname + 1, varp); + + // reset notion of buffer + aucmd_restbuf(&aco); + } else { + const size_t varname_len = strlen(varname); + char *const bufvarname = xmalloc(varname_len + 3); + buf_T *const save_curbuf = curbuf; + curbuf = buf; + memcpy(bufvarname, "b:", 2); + memcpy(bufvarname + 2, varname, varname_len + 1); + set_var(bufvarname, varname_len + 2, varp, true); + xfree(bufvarname); + curbuf = save_curbuf; } } diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 7cb346216d..14b3d7c909 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -486,9 +486,11 @@ void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int id = (int)tv_get_number(argvars); tabpage_T *tp; win_T *wp = win_id2wp_tp(id, &tp); - if (wp != NULL && tp != NULL) { - WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); + if (wp == NULL || tp == NULL) { + return; } + + WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1)); } /// "win_findbuf()" function -- cgit From 5841a97500bffa5a2b9eed2eb41025f5587790ba Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Tue, 3 Jan 2023 10:07:43 +0000 Subject: feat!: remove hardcopy Co-authored-by: Justin M. Keyes --- src/nvim/eval/funcs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d2bbdc7a96..77e8e23ab6 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3113,8 +3113,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "packages", "path_extra", "persistent_undo", - "postscript", - "printer", "profile", "pythonx", "reltime", -- cgit From a3c92f6b6cae67ae417b05fb2b8fb61dc6c11b7c Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 3 Jan 2023 19:22:32 +0800 Subject: vim-patch:9.0.1137: some conditions are always false (#21628) Problem: Some conditions are always false. Solution: Remove the useless conditions. (closes vim/vim#11776) https://github.com/vim/vim/commit/ea720aea851e645f4c8ec3b20afb27c7ca38184c --- src/nvim/eval/vars.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index ee7a8a0dd0..62138221e6 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1654,7 +1654,7 @@ static void setwinvar(typval_T *argvars, typval_T *rettv, int off) const char *varname = tv_get_string_chk(&argvars[off + 1]); typval_T *varp = &argvars[off + 2]; - if (win == NULL || varname == NULL || varp == NULL) { + if (win == NULL || varname == NULL) { return; } -- cgit From b2295ac4ec80e141628cea33ebee81c96e168989 Mon Sep 17 00:00:00 2001 From: bfredl Date: Tue, 3 Jan 2023 15:24:41 +0100 Subject: refactor(api): do not allocate temporaries for internal events --- src/nvim/eval/funcs.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 77e8e23ab6..d377508e27 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6322,12 +6322,15 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) ADD(args, vim_to_object(tv)); } - if (!rpc_send_event((uint64_t)argvars[0].vval.v_number, - tv_get_string(&argvars[1]), args)) { + bool ok = rpc_send_event((uint64_t)argvars[0].vval.v_number, + tv_get_string(&argvars[1]), args); + + if (!ok) { semsg(_(e_invarg2), "Channel doesn't exist"); return; } + api_free_array(args); rettv->vval.v_number = 1; } -- cgit From bb7033a0338e9133765f9b2e1e6dc096847d17e3 Mon Sep 17 00:00:00 2001 From: bfredl Date: Mon, 9 Jan 2023 13:26:18 +0100 Subject: fix(rpc): don't free args on error in rpc_send_event fixup #21631 fixes #21690 --- src/nvim/eval/funcs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d377508e27..86bc3b2092 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6325,12 +6325,12 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) bool ok = rpc_send_event((uint64_t)argvars[0].vval.v_number, tv_get_string(&argvars[1]), args); + api_free_array(args); + if (!ok) { semsg(_(e_invarg2), "Channel doesn't exist"); return; } - - api_free_array(args); rettv->vval.v_number = 1; } -- cgit From 149209400383c673fdb4fdd1c9a7639139f17936 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 9 Jan 2023 14:13:06 +0100 Subject: refactor: replace char_u with char 17 - remove STRLCPY (#21235) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 6 +++--- src/nvim/eval/userfunc.c | 18 +++++++++--------- src/nvim/eval/window.h | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d377508e27..d21d92d844 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -822,7 +822,7 @@ static void f_chdir(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // Return the current directory char *cwd = xmalloc(MAXPATHL); - if (os_dirname((char_u *)cwd, MAXPATHL) != FAIL) { + if (os_dirname(cwd, MAXPATHL) != FAIL) { #ifdef BACKSLASH_IN_FILENAME slash_adjust(cwd); #endif @@ -2517,13 +2517,13 @@ static void f_getcwd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } FALLTHROUGH; // In global directory, just need to get OS CWD. case kCdScopeInvalid: // If called without any arguments, get OS CWD. - if (os_dirname((char_u *)cwd, MAXPATHL) == FAIL) { + if (os_dirname(cwd, MAXPATHL) == FAIL) { from = ""; // Return empty string on failure. } } if (from) { - STRLCPY(cwd, from, MAXPATHL); + xstrlcpy(cwd, from, MAXPATHL); } rettv->vval.v_string = xstrdup(cwd); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 69b074ab99..9f6aa0776c 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -260,7 +260,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) int varargs; int ret; char_u *start = (char_u *)skipwhite(*arg + 1); - char_u *s, *e; + char *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; @@ -289,12 +289,12 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) // Get the start and the end of the expression. *arg = skipwhite((*arg) + 1); - s = (char_u *)(*arg); + s = *arg; ret = skip_expr(arg); if (ret == FAIL) { goto errret; } - e = (char_u *)(*arg); + e = *arg; *arg = skipwhite(*arg); if (**arg != '}') { semsg(_("E451: Expected }: %s"), *arg); @@ -304,7 +304,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) if (evaluate) { int flags = 0; - char_u *p; + char *p; garray_T newlines; char *name = (char *)get_lambda_name(); @@ -317,11 +317,11 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) // Add "return " before the expression. size_t len = (size_t)(7 + e - s + 1); - p = (char_u *)xmalloc(len); - ((char **)(newlines.ga_data))[newlines.ga_len++] = (char *)p; + p = xmalloc(len); + ((char **)(newlines.ga_data))[newlines.ga_len++] = p; STRCPY(p, "return "); - STRLCPY(p + 7, s, e - s + 1); - if (strstr((char *)p + 7, "a:") == NULL) { + xstrlcpy(p + 7, s, (size_t)(e - s) + 1); + if (strstr(p + 7, "a:") == NULL) { // No a: variables are used for sure. flags |= FC_NOARGS; } @@ -3214,7 +3214,7 @@ char *get_return_cmd(void *rettv) } STRCPY(IObuff, ":return "); - STRLCPY(IObuff + 8, s, IOSIZE - 8); + xstrlcpy(IObuff + 8, s, IOSIZE - 8); if (strlen(s) + 8 >= IOSIZE) { STRCPY(IObuff + IOSIZE - 4, "..."); } diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 02e4457a1b..682a794113 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -31,13 +31,13 @@ typedef struct { && (curwin->w_localdir != NULL || wp->w_localdir != NULL \ || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \ || p_acd)) { \ - cwd_status_ = os_dirname((char_u *)cwd_, MAXPATHL); \ + cwd_status_ = os_dirname(cwd_, MAXPATHL); \ } \ /* If 'acd' is set, check we are using that directory. If yes, then */ \ /* apply 'acd' afterwards, otherwise restore the current directory. */ \ if (cwd_status_ == OK && p_acd) { \ do_autochdir(); \ - apply_acd_ = os_dirname((char_u *)autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \ + apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \ } \ switchwin_T switchwin_; \ if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \ -- cgit From 50f03773f4b9f4638489ccfd0503dc9e39e5de78 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Mon, 9 Jan 2023 15:37:34 +0100 Subject: refactor: replace char_u with char 18 (#21237) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/encode.c | 16 +++---- src/nvim/eval/funcs.c | 114 +++++++++++++++++++++++------------------------ src/nvim/eval/userfunc.c | 54 +++++++++++----------- 3 files changed, 92 insertions(+), 92 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index b7ef109f06..03d4862550 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -141,9 +141,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, 1))->hi_key }, }; char *const key = encode_tv2string(&key_tv, NULL); - vim_snprintf((char *)IObuff, IOSIZE, key_msg, key); + vim_snprintf(IObuff, IOSIZE, key_msg, key); xfree(key); - ga_concat(&msg_ga, (char *)IObuff); + ga_concat(&msg_ga, IObuff); break; } case kMPConvPairs: @@ -163,8 +163,8 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, || li == NULL || (TV_LIST_ITEM_TV(li)->v_type != VAR_LIST && tv_list_len(TV_LIST_ITEM_TV(li)->vval.v_list) <= 0)) { - vim_snprintf((char *)IObuff, IOSIZE, idx_msg, idx); - ga_concat(&msg_ga, (char *)IObuff); + vim_snprintf(IObuff, IOSIZE, idx_msg, idx); + ga_concat(&msg_ga, IObuff); } else { assert(li != NULL); listitem_T *const first_item = @@ -172,9 +172,9 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, assert(first_item != NULL); typval_T key_tv = *TV_LIST_ITEM_TV(first_item); char *const key = encode_tv2echo(&key_tv, NULL); - vim_snprintf((char *)IObuff, IOSIZE, key_pair_msg, key, idx); + vim_snprintf(IObuff, IOSIZE, key_pair_msg, key, idx); xfree(key); - ga_concat(&msg_ga, (char *)IObuff); + ga_concat(&msg_ga, IObuff); } break; } @@ -193,8 +193,8 @@ static int conv_error(const char *const msg, const MPConvStack *const mpstack, break; case kMPConvPartialList: { const int idx = (int)(v.data.a.arg - v.data.a.argv) - 1; - vim_snprintf((char *)IObuff, IOSIZE, partial_arg_i_msg, idx); - ga_concat(&msg_ga, (char *)IObuff); + vim_snprintf(IObuff, IOSIZE, partial_arg_i_msg, idx); + ga_concat(&msg_ga, IObuff); break; } } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index b79a69bc6e..5cb4dc2631 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -169,13 +169,13 @@ char *get_function_name(expand_T *xp, int idx) intidx = -1; } if (intidx < 0) { - char_u *name = (char_u *)get_user_func_name(xp, idx); + char *name = get_user_func_name(xp, idx); if (name != NULL) { if (*name != NUL && *name != '<' && strncmp("g:", xp->xp_pattern, 2) == 0) { - return cat_prefix_varname('g', (char *)name); + return cat_prefix_varname('g', name); } - return (char *)name; + return name; } } @@ -192,7 +192,7 @@ char *get_function_name(expand_T *xp, int idx) } else { IObuff[key_len + 1] = NUL; } - return (char *)IObuff; + return IObuff; } /// Function given to ExpandGeneric() to obtain the list of internal or @@ -205,9 +205,9 @@ char *get_expr_name(expand_T *xp, int idx) intidx = -1; } if (intidx < 0) { - char_u *name = (char_u *)get_function_name(xp, idx); + char *name = get_function_name(xp, idx); if (name != NULL) { - return (char *)name; + return name; } } return get_user_var_name(xp, ++intidx); @@ -548,19 +548,19 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } bool owned = false; - char_u *func; + char *func; partial_T *partial = NULL; if (argvars[0].v_type == VAR_FUNC) { - func = (char_u *)argvars[0].vval.v_string; + func = argvars[0].vval.v_string; } else if (argvars[0].v_type == VAR_PARTIAL) { partial = argvars[0].vval.v_partial; - func = (char_u *)partial_name(partial); + func = partial_name(partial); } else if (nlua_is_table_from_lua(&argvars[0])) { // TODO(tjdevries): UnifiedCallback - func = nlua_register_table_as_callable(&argvars[0]); + func = (char *)nlua_register_table_as_callable(&argvars[0]); owned = true; } else { - func = (char_u *)tv_get_string(&argvars[0]); + func = (char *)tv_get_string(&argvars[0]); } if (*func == NUL) { @@ -572,16 +572,16 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[2].v_type != VAR_DICT) { emsg(_(e_dictreq)); if (owned) { - func_unref(func); + func_unref((char_u *)func); } return; } selfdict = argvars[2].vval.v_dict; } - func_call(func, &argvars[1], partial, selfdict, rettv); + func_call((char_u *)func, &argvars[1], partial, selfdict, rettv); if (owned) { - func_unref(func); + func_unref((char_u *)func); } } @@ -949,7 +949,7 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[0].v_type == VAR_STRING) { const char *expr = tv_get_string_chk(&argvars[1]); - const char_u *p = (char_u *)argvars[0].vval.v_string; + const char *p = argvars[0].vval.v_string; if (!error && expr != NULL && *expr != NUL && p != NULL) { if (ic) { @@ -964,8 +964,8 @@ static void f_count(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } } else { - char_u *next; - while ((next = (char_u *)strstr((char *)p, (char *)expr)) != NULL) { + char *next; + while ((next = strstr((char *)p, (char *)expr)) != NULL) { n++; p = next + strlen(expr); } @@ -1531,14 +1531,14 @@ static void f_escape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "getenv()" function static void f_getenv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char_u *p = (char_u *)vim_getenv(tv_get_string(&argvars[0])); + char *p = vim_getenv(tv_get_string(&argvars[0])); if (p == NULL) { rettv->v_type = VAR_SPECIAL; rettv->vval.v_special = kSpecialVarNull; return; } - rettv->vval.v_string = (char *)p; + rettv->vval.v_string = p; rettv->v_type = VAR_STRING; } @@ -1771,7 +1771,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } size_t len; char *errormsg = NULL; - char_u *result = eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); + char *result = (char *)eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); if (p_verbose == 0) { emsg_off--; } else if (errormsg != NULL) { @@ -1784,7 +1784,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } XFREE_CLEAR(result); } else { - rettv->vval.v_string = (char *)result; + rettv->vval.v_string = result; } } else { // When the optional second argument is non-zero, don't remove matches @@ -2022,8 +2022,8 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { - char_u *fresult = NULL; - char_u *path = *curbuf->b_p_path == NUL ? p_path : (char_u *)curbuf->b_p_path; + char *fresult = NULL; + char *path = *curbuf->b_p_path == NUL ? (char *)p_path : curbuf->b_p_path; int count = 1; bool first = true; bool error = false; @@ -2040,7 +2040,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) error = true; } else { if (*p != NUL) { - path = (char_u *)p; + path = (char *)p; } if (argvars[2].v_type != VAR_UNKNOWN) { @@ -2058,13 +2058,13 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) if (rettv->v_type == VAR_STRING || rettv->v_type == VAR_LIST) { xfree(fresult); } - fresult = (char_u *)find_file_in_path_option(first ? (char *)fname : NULL, - first ? strlen(fname) : 0, - 0, first, (char *)path, - find_what, curbuf->b_ffname, - (find_what == FINDFILE_DIR - ? "" - : curbuf->b_p_sua)); + fresult = find_file_in_path_option(first ? (char *)fname : NULL, + first ? strlen(fname) : 0, + 0, first, path, + find_what, curbuf->b_ffname, + (find_what == FINDFILE_DIR + ? "" + : curbuf->b_p_sua)); first = false; if (fresult != NULL && rettv->v_type == VAR_LIST) { @@ -2074,7 +2074,7 @@ static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) } if (rettv->v_type == VAR_STRING) { - rettv->vval.v_string = (char *)fresult; + rettv->vval.v_string = fresult; } } @@ -2138,7 +2138,7 @@ static void f_fnameescape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "fnamemodify({fname}, {mods})" function static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char_u *fbuf = NULL; + char *fbuf = NULL; size_t len = 0; char buf[NUMBUFLEN]; const char *fname = tv_get_string_chk(&argvars[0]); @@ -2150,7 +2150,7 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (*mods != NUL) { size_t usedlen = 0; (void)modify_fname((char *)mods, false, &usedlen, - (char **)&fname, (char **)&fbuf, &len); + (char **)&fname, &fbuf, &len); } } @@ -2545,7 +2545,7 @@ static void f_getfontname(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_getfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char *perm = NULL; - char_u flags[] = "rwx"; + char flags[] = "rwx"; const char *filename = tv_get_string(&argvars[0]); int32_t file_perm = os_getperm(filename); @@ -2553,7 +2553,7 @@ static void f_getfperm(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) perm = xstrdup("---------"); for (int i = 0; i < 9; i++) { if (file_perm & (1 << (8 - i))) { - perm[i] = (char)flags[i % 3]; + perm[i] = flags[i % 3]; } } } @@ -6780,14 +6780,14 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir // Make two search patterns: start/end (pat2, for in nested pairs) and // start/middle/end (pat3, for the top pair). const size_t pat2_len = strlen(spat) + strlen(epat) + 17; - char_u *pat2 = xmalloc(pat2_len); + char *pat2 = xmalloc(pat2_len); const size_t pat3_len = strlen(spat) + strlen(mpat) + strlen(epat) + 25; - char_u *pat3 = xmalloc(pat3_len); - snprintf((char *)pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); + char *pat3 = xmalloc(pat3_len); + snprintf(pat2, pat2_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat); if (*mpat == NUL) { STRCPY(pat3, pat2); } else { - snprintf((char *)pat3, pat3_len, + snprintf(pat3, pat3_len, "\\m\\(%s\\m\\)\\|\\(%s\\m\\)\\|\\(%s\\m\\)", spat, epat, mpat); } if (flags & SP_START) { @@ -6804,14 +6804,14 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir clearpos(&firstpos); pos_T foundpos; clearpos(&foundpos); - char_u *pat = pat3; + char *pat = pat3; for (;;) { searchit_arg_T sia = { .sa_stop_lnum = lnum_stop, .sa_tm = &tm, }; - int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L, + int n = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1L, options, RE_SEARCH, &sia); if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) { // didn't find it or found the first match again: FAIL @@ -7755,10 +7755,10 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) static void f_str2list(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { tv_list_alloc_ret(rettv, kListLenUnknown); - const char_u *p = (const char_u *)tv_get_string(&argvars[0]); + const char *p = tv_get_string(&argvars[0]); - for (; *p != NUL; p += utf_ptr2len((char *)p)) { - tv_list_append_number(rettv->vval.v_list, utf_ptr2char((char *)p)); + for (; *p != NUL; p += utf_ptr2len(p)) { + tv_list_append_number(rettv->vval.v_list, utf_ptr2char(p)); } } @@ -7779,10 +7779,10 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } - char_u *p = (char_u *)skipwhite(tv_get_string(&argvars[0])); + char *p = skipwhite(tv_get_string(&argvars[0])); bool isneg = (*p == '-'); if (*p == '+' || *p == '-') { - p = (char_u *)skipwhite((char *)p + 1); + p = skipwhite(p + 1); } switch (base) { case 2: @@ -7796,7 +7796,7 @@ static void f_str2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) break; } varnumber_T n; - vim_str2nr((char *)p, NULL, NULL, what, &n, NULL, 0, false); + vim_str2nr(p, NULL, NULL, what, &n, NULL, 0, false); // Text after the number is silently ignored. if (isneg) { rettv->vval.v_number = -n; @@ -8372,7 +8372,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr int syntax_flags = 0; int cchar; int matchid = 0; - char_u str[NUMBUFLEN]; + char str[NUMBUFLEN]; tv_list_set_ret(rettv, NULL); @@ -8396,7 +8396,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr : curwin->w_p_lcs_chars.conceal; } if (cchar != NUL) { - utf_char2bytes(cchar, (char *)str); + utf_char2bytes(cchar, str); } } } @@ -8404,7 +8404,7 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr tv_list_alloc_ret(rettv, 3); tv_list_append_number(rettv->vval.v_list, (syntax_flags & HL_CONCEAL) != 0); // -1 to auto-determine strlen - tv_list_append_string(rettv->vval.v_list, (const char *)str, -1); + tv_list_append_string(rettv->vval.v_list, str, -1); tv_list_append_number(rettv->vval.v_list, matchid); } @@ -8497,7 +8497,7 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) fname = tv_get_string(&argvars[1]); } (void)get_tags(tv_list_alloc_ret(rettv, kListLenUnknown), - (char_u *)tag_pattern, (char_u *)fname); + (char *)tag_pattern, (char *)fname); } /// "tempname()" function @@ -8591,9 +8591,9 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int pid = chan->stream.pty.process.pid; // "./…" => "/home/foo/…" - vim_FullName(cwd, (char *)NameBuff, sizeof(NameBuff), false); + vim_FullName(cwd, NameBuff, sizeof(NameBuff), false); // "/home/foo/…" => "~/…" - size_t len = home_replace(NULL, (char *)NameBuff, (char *)IObuff, sizeof(IObuff), true); + size_t len = home_replace(NULL, NameBuff, IObuff, sizeof(IObuff), true); // Trim slash. if (len != 1 && (IObuff[len - 1] == '\\' || IObuff[len - 1] == '/')) { IObuff[len - 1] = '\0'; @@ -8606,14 +8606,14 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } // Terminal URI: "term://$CWD//$PID:$CMD" - snprintf((char *)NameBuff, sizeof(NameBuff), "term://%s//%d:%s", - (char *)IObuff, pid, cmd); + snprintf(NameBuff, sizeof(NameBuff), "term://%s//%d:%s", + IObuff, pid, cmd); // at this point the buffer has no terminal instance associated yet, so unset // the 'swapfile' option to ensure no swap file will be created curbuf->b_p_swf = false; apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf); - (void)setfname(curbuf, (char *)NameBuff, NULL, true); + (void)setfname(curbuf, NameBuff, NULL, true); apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf); // Save the job id and pid in b:terminal_job_{id,pid} diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9f6aa0776c..54c4285453 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -259,13 +259,13 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) partial_T *pt = NULL; int varargs; int ret; - char_u *start = (char_u *)skipwhite(*arg + 1); + char *start = skipwhite(*arg + 1); char *s, *e; bool *old_eval_lavars = eval_lavars_used; bool eval_lavars = false; // First, check if this is a lambda expression. "->" must exists. - ret = get_function_args((char **)&start, '-', NULL, NULL, NULL, true); + ret = get_function_args(&start, '-', NULL, NULL, NULL, true); if (ret == FAIL || *start != '>') { return NOTDONE; } @@ -2765,7 +2765,7 @@ char *get_user_func_name(expand_T *xp, int idx) STRCAT(IObuff, ")"); } } - return (char *)IObuff; + return IObuff; } return NULL; } @@ -2950,7 +2950,7 @@ static int can_free_funccal(funccall_T *fc, int copyID) /// ":return [expr]" void ex_return(exarg_T *eap) { - char_u *arg = (char_u *)eap->arg; + char *arg = eap->arg; typval_T rettv; int returning = false; @@ -2965,7 +2965,7 @@ void ex_return(exarg_T *eap) eap->nextcmd = NULL; if ((*arg != NUL && *arg != '|' && *arg != '\n') - && eval0((char *)arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { + && eval0(arg, &rettv, &eap->nextcmd, !eap->skip) != FAIL) { if (!eap->skip) { returning = do_return(eap, false, true, &rettv); } else { @@ -2988,7 +2988,7 @@ void ex_return(exarg_T *eap) if (returning) { eap->nextcmd = NULL; } else if (eap->nextcmd == NULL) { // no argument - eap->nextcmd = check_nextcmd((char *)arg); + eap->nextcmd = check_nextcmd(arg); } if (eap->skip) { @@ -2999,9 +2999,9 @@ void ex_return(exarg_T *eap) /// ":1,25call func(arg1, arg2)" function call. void ex_call(exarg_T *eap) { - char_u *arg = (char_u *)eap->arg; - char_u *startarg; - char_u *name; + char *arg = eap->arg; + char *startarg; + char *name; char *tofree; int len; typval_T rettv; @@ -3023,7 +3023,7 @@ void ex_call(exarg_T *eap) return; } - tofree = (char *)trans_function_name((char **)&arg, false, TFN_INT, &fudi, &partial); + tofree = (char *)trans_function_name(&arg, false, TFN_INT, &fudi, &partial); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. semsg(_(e_dictkey), fudi.fd_newkey); @@ -3043,11 +3043,11 @@ void ex_call(exarg_T *eap) // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). len = (int)strlen(tofree); - name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); + name = (char *)deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. - startarg = (char_u *)skipwhite((char *)arg); + startarg = skipwhite(arg); rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this. if (*startarg != '(') { @@ -3077,7 +3077,7 @@ void ex_call(exarg_T *eap) funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; - if (get_func_tv(name, -1, &rettv, (char **)&arg, &funcexe) == FAIL) { + if (get_func_tv((char_u *)name, -1, &rettv, &arg, &funcexe) == FAIL) { failed = true; break; } @@ -3114,7 +3114,7 @@ void ex_call(exarg_T *eap) semsg(_(e_trailing_arg), arg); } } else { - eap->nextcmd = check_nextcmd((char *)arg); + eap->nextcmd = check_nextcmd(arg); } } @@ -3219,7 +3219,7 @@ char *get_return_cmd(void *rettv) STRCPY(IObuff + IOSIZE - 4, "..."); } xfree(tofree); - return xstrdup((char *)IObuff); + return xstrdup(IObuff); } /// Get next function line. @@ -3296,21 +3296,21 @@ int func_has_abort(void *cookie) /// Changes "rettv" in-place. void make_partial(dict_T *const selfdict, typval_T *const rettv) { - char_u *fname; - char_u *tofree = NULL; + char *fname; + char *tofree = NULL; ufunc_T *fp; - char_u fname_buf[FLEN_FIXED + 1]; + char fname_buf[FLEN_FIXED + 1]; int error; if (rettv->v_type == VAR_PARTIAL && rettv->vval.v_partial->pt_func != NULL) { fp = rettv->vval.v_partial->pt_func; } else { fname = rettv->v_type == VAR_FUNC || rettv->v_type == VAR_STRING - ? (char_u *)rettv->vval.v_string - : (char_u *)rettv->vval.v_partial->pt_name; + ? rettv->vval.v_string + : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. - fname = (char_u *)fname_trans_sid((char *)fname, (char *)fname_buf, (char **)&tofree, &error); - fp = find_func(fname); + fname = fname_trans_sid(fname, (char *)fname_buf, &tofree, &error); + fp = find_func((char_u *)fname); xfree(tofree); } @@ -3646,17 +3646,17 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) ufunc_T *fp = fp_in; funccall_T *fc; int error = FCERR_NONE; - char_u fname_buf[FLEN_FIXED + 1]; - char_u *tofree = NULL; - char_u *fname; + char fname_buf[FLEN_FIXED + 1]; + char *tofree = NULL; + char *fname; bool abort = false; if (name == NULL && fp_in == NULL) { return false; } if (fp_in == NULL) { - fname = (char_u *)fname_trans_sid((char *)name, (char *)fname_buf, (char **)&tofree, &error); - fp = find_func(fname); + fname = fname_trans_sid((char *)name, (char *)fname_buf, &tofree, &error); + fp = find_func((char_u *)fname); } if (fp != NULL) { for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) { -- cgit From dc7edce650bc2abbcad2fdc12cb77561b36b35af Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 10 Jan 2023 08:46:42 +0800 Subject: vim-patch:partial:9.0.1166: code is indented more than necessary (#21716) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11792) https://github.com/vim/vim/commit/1cfb14aa972ccf3235ac67f07b7db1175b7c5384 Partial port as some highlight.c changes depend on previous patches. Cherry-pick fname_match() change from patch 8.2.4959. Omit internal_func_check_arg_types(): only used for Vim9 script. N/A patches for version.c: vim-patch:9.0.1167: EditorConfig files do not have their own filetype Problem: EditorConfig files do not have their own filetype. Solution: Add the "editorconfig" filetype. (Gregory Anders, closes vim/vim#11779) https://github.com/vim/vim/commit/d41262ed06564cef98a3800e2928e6e0db91abbf Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/funcs.c | 106 +++++++++++++++++++++++++------------------------ src/nvim/eval/window.c | 66 +++++++++++++++--------------- 2 files changed, 89 insertions(+), 83 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 5cb4dc2631..180723f412 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -859,14 +859,14 @@ static void f_cindent(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) win_T *get_optional_window(typval_T *argvars, int idx) { - win_T *win = curwin; + if (argvars[idx].v_type == VAR_UNKNOWN) { + return curwin; + } - if (argvars[idx].v_type != VAR_UNKNOWN) { - win = find_win_by_nr_or_id(&argvars[idx]); - if (win == NULL) { - emsg(_(e_invalwindow)); - return NULL; - } + win_T *win = find_win_by_nr_or_id(&argvars[idx]); + if (win == NULL) { + emsg(_(e_invalwindow)); + return NULL; } return win; } @@ -6109,55 +6109,57 @@ static int get_search_arg(typval_T *varp, int *flagsp) { int dir = FORWARD; - if (varp->v_type != VAR_UNKNOWN) { - char nbuf[NUMBUFLEN]; - const char *flags = tv_get_string_buf_chk(varp, nbuf); - if (flags == NULL) { - return 0; // Type error; errmsg already given. - } - int mask; - while (*flags != NUL) { - switch (*flags) { - case 'b': - dir = BACKWARD; break; - case 'w': - p_ws = true; break; - case 'W': - p_ws = false; break; - default: - mask = 0; - if (flagsp != NULL) { - switch (*flags) { - case 'c': - mask = SP_START; break; - case 'e': - mask = SP_END; break; - case 'm': - mask = SP_RETCOUNT; break; - case 'n': - mask = SP_NOMOVE; break; - case 'p': - mask = SP_SUBPAT; break; - case 'r': - mask = SP_REPEAT; break; - case 's': - mask = SP_SETPCMARK; break; - case 'z': - mask = SP_COLUMN; break; - } - } - if (mask == 0) { - semsg(_(e_invarg2), flags); - dir = 0; - } else { - *flagsp |= mask; + if (varp->v_type == VAR_UNKNOWN) { + return FORWARD; + } + + char nbuf[NUMBUFLEN]; + const char *flags = tv_get_string_buf_chk(varp, nbuf); + if (flags == NULL) { + return 0; // Type error; errmsg already given. + } + int mask; + while (*flags != NUL) { + switch (*flags) { + case 'b': + dir = BACKWARD; break; + case 'w': + p_ws = true; break; + case 'W': + p_ws = false; break; + default: + mask = 0; + if (flagsp != NULL) { + switch (*flags) { + case 'c': + mask = SP_START; break; + case 'e': + mask = SP_END; break; + case 'm': + mask = SP_RETCOUNT; break; + case 'n': + mask = SP_NOMOVE; break; + case 'p': + mask = SP_SUBPAT; break; + case 'r': + mask = SP_REPEAT; break; + case 's': + mask = SP_SETPCMARK; break; + case 'z': + mask = SP_COLUMN; break; } } - if (dir == 0) { - break; + if (mask == 0) { + semsg(_(e_invarg2), flags); + dir = 0; + } else { + *flagsp |= mask; } - flags++; } + if (dir == 0) { + break; + } + flags++; } return dir; } diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 14b3d7c909..50b25378e4 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -46,31 +46,33 @@ static int win_getid(typval_T *argvars) } int winnr = (int)tv_get_number(&argvars[0]); win_T *wp; - if (winnr > 0) { - if (argvars[1].v_type == VAR_UNKNOWN) { + if (winnr <= 0) { + return 0; + } + + if (argvars[1].v_type == VAR_UNKNOWN) { + wp = firstwin; + } else { + tabpage_T *tp = NULL; + int tabnr = (int)tv_get_number(&argvars[1]); + FOR_ALL_TABS(tp2) { + if (--tabnr == 0) { + tp = tp2; + break; + } + } + if (tp == NULL) { + return -1; + } + if (tp == curtab) { wp = firstwin; } else { - tabpage_T *tp = NULL; - int tabnr = (int)tv_get_number(&argvars[1]); - FOR_ALL_TABS(tp2) { - if (--tabnr == 0) { - tp = tp2; - break; - } - } - if (tp == NULL) { - return -1; - } - if (tp == curtab) { - wp = firstwin; - } else { - wp = tp->tp_firstwin; - } + wp = tp->tp_firstwin; } - for (; wp != NULL; wp = wp->w_next) { - if (--winnr == 0) { - return wp->handle; - } + } + for (; wp != NULL; wp = wp->w_next) { + if (--winnr == 0) { + return wp->handle; } } return 0; @@ -288,16 +290,18 @@ static int get_winnr(tabpage_T *tp, typval_T *argvar) } } - if (nr > 0) { - for (win_T *wp = (tp == curtab) ? firstwin : tp->tp_firstwin; - wp != twin; wp = wp->w_next) { - if (wp == NULL) { - // didn't find it in this tabpage - nr = 0; - break; - } - nr++; + if (nr <= 0) { + return 0; + } + + for (win_T *wp = (tp == curtab) ? firstwin : tp->tp_firstwin; + wp != twin; wp = wp->w_next) { + if (wp == NULL) { + // didn't find it in this tabpage + nr = 0; + break; } + nr++; } return nr; } -- cgit From ef6750332008b7b61dde9eeab0da454bf3323ebb Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 10 Jan 2023 03:28:01 +0100 Subject: refactor: replace char_u with char 19 (#21241) * refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 30 ++++++++++++++---------------- src/nvim/eval/userfunc.c | 2 +- 2 files changed, 15 insertions(+), 17 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 180723f412..a87698a9f9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -226,11 +226,11 @@ const EvalFuncDef *find_internal_func(const char *const name) return index >= 0 ? &functions[index] : NULL; } -int call_internal_func(const char_u *const fname, const int argcount, typval_T *const argvars, +int call_internal_func(const char *const fname, const int argcount, typval_T *const argvars, typval_T *const rettv) FUNC_ATTR_NONNULL_ALL { - const EvalFuncDef *const fdef = find_internal_func((const char *)fname); + const EvalFuncDef *const fdef = find_internal_func(fname); if (fdef == NULL) { return FCERR_UNKNOWN; } else if (argcount < fdef->min_argc) { @@ -2751,19 +2751,19 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// Returns zero on error. static int getreg_get_regname(typval_T *argvars) { - const char_u *strregname; + const char *strregname; if (argvars[0].v_type != VAR_UNKNOWN) { - strregname = (const char_u *)tv_get_string_chk(&argvars[0]); + strregname = tv_get_string_chk(&argvars[0]); if (strregname == NULL) { // type error; errmsg already given return 0; } } else { // Default to v:register - strregname = (char_u *)get_vim_var_str(VV_REG); + strregname = get_vim_var_str(VV_REG); } - return *strregname == 0 ? '"' : *strregname; + return *strregname == 0 ? '"' : (uint8_t)(*strregname); } /// "getreg()" function @@ -3365,13 +3365,11 @@ static void f_iconv(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *const str = tv_get_string(&argvars[0]); char buf1[NUMBUFLEN]; - char_u *const from = - (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[1], buf1))); + char *const from = enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[1], buf1))); char buf2[NUMBUFLEN]; - char_u *const to = - (char_u *)enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[2], buf2))); + char *const to = enc_canonize(enc_skip((char *)tv_get_string_buf(&argvars[2], buf2))); vimconv.vc_type = CONV_NONE; - convert_setup(&vimconv, (char *)from, (char *)to); + convert_setup(&vimconv, from, to); // If the encodings are equal, no conversion needed. if (vimconv.vc_type == CONV_NONE) { @@ -3646,11 +3644,11 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) lval_T lv; rettv->vval.v_number = -1; - const char_u *const end = (char_u *)get_lval((char *)tv_get_string(&argvars[0]), - NULL, - &lv, false, false, - GLV_NO_AUTOLOAD|GLV_READ_ONLY, - FNE_CHECK_START); + const char *const end = get_lval((char *)tv_get_string(&argvars[0]), + NULL, + &lv, false, false, + GLV_NO_AUTOLOAD|GLV_READ_ONLY, + FNE_CHECK_START); if (end != NULL && lv.ll_name != NULL) { if (*end != NUL) { semsg(_(e_trailing_arg), end); diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 54c4285453..9078050067 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1618,7 +1618,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t funcexe->fe_basetv); } else { // Find the function name in the table, call its implementation. - error = call_internal_func((char_u *)fname, argcount, argvars, rettv); + error = call_internal_func(fname, argcount, argvars, rettv); } // The function call (or "FuncUndefined" autocommand sequence) might // have been aborted by an error, an interrupt, or an explicitly thrown -- cgit From f2141de9e462ed8976b2a59337c32a0fcba2a11d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Fri, 13 Jan 2023 00:35:39 +0100 Subject: refactor: replace char_u with char 20 (#21714) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 9 ++-- src/nvim/eval/userfunc.c | 134 ++++++++++++++++++++++------------------------- src/nvim/eval/userfunc.h | 2 +- src/nvim/eval/vars.c | 4 +- src/nvim/eval/window.c | 10 ++-- 5 files changed, 76 insertions(+), 83 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index a87698a9f9..7820b837da 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1522,9 +1522,8 @@ static void f_escape(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { char buf[NUMBUFLEN]; - rettv->vval.v_string = (char *)vim_strsave_escaped((const char_u *)tv_get_string(&argvars[0]), - (const char_u *)tv_get_string_buf(&argvars[1], - buf)); + rettv->vval.v_string = vim_strsave_escaped(tv_get_string(&argvars[0]), + tv_get_string_buf(&argvars[1], buf)); rettv->v_type = VAR_STRING; } @@ -2245,7 +2244,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *const what = tv_get_string(&argvars[1]); if (strcmp(what, "func") == 0 || strcmp(what, "name") == 0) { - const char *name = (const char *)partial_name(pt); + const char *name = partial_name(pt); rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); assert(name != NULL); if (rettv->v_type == VAR_FUNC) { @@ -2253,7 +2252,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } if (*what == 'n' && pt->pt_name == NULL && pt->pt_func != NULL) { // use instead of the byte code - name = (const char *)printable_func_name(pt->pt_func); + name = printable_func_name(pt->pt_func); } rettv->vval.v_string = xstrdup(name); } else if (strcmp(what, "dict") == 0) { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 9078050067..1c0fe20248 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -93,10 +93,10 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int int i; if (newargs != NULL) { - ga_init(newargs, (int)sizeof(char_u *), 3); + ga_init(newargs, (int)sizeof(char *), 3); } if (default_args != NULL) { - ga_init(default_args, (int)sizeof(char_u *), 3); + ga_init(default_args, (int)sizeof(char *), 3); } if (varargs != NULL) { @@ -312,7 +312,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); pt = xcalloc(1, sizeof(partial_T)); - ga_init(&newlines, (int)sizeof(char_u *), 1); + ga_init(&newlines, (int)sizeof(char *), 1); ga_grow(&newlines, 1); // Add "return " before the expression. @@ -330,7 +330,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) set_ufunc_name(fp, name); hash_add(&func_hashtab, UF2HIKEY(fp)); fp->uf_args = newargs; - ga_init(&fp->uf_def_args, (int)sizeof(char_u *), 1); + ga_init(&fp->uf_def_args, (int)sizeof(char *), 1); fp->uf_lines = newlines; if (current_funccal != NULL && eval_lavars) { flags |= FC_CLOSURE; @@ -383,7 +383,7 @@ errret: /// was not found. /// /// @return name of the function. -char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload) +char *deref_func_name(const char *name, int *lenp, partial_T **const partialp, bool no_autoload) FUNC_ATTR_NONNULL_ARG(1, 2) { if (partialp != NULL) { @@ -394,10 +394,10 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, if (v != NULL && v->di_tv.v_type == VAR_FUNC) { if (v->di_tv.vval.v_string == NULL) { // just in case *lenp = 0; - return (char_u *)""; + return ""; } *lenp = (int)strlen(v->di_tv.vval.v_string); - return (char_u *)v->di_tv.vval.v_string; + return v->di_tv.vval.v_string; } if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) { @@ -405,31 +405,31 @@ char_u *deref_func_name(const char *name, int *lenp, partial_T **const partialp, if (pt == NULL) { // just in case *lenp = 0; - return (char_u *)""; + return ""; } if (partialp != NULL) { *partialp = pt; } char *s = partial_name(pt); *lenp = (int)strlen(s); - return (char_u *)s; + return s; } - return (char_u *)name; + return (char *)name; } /// Give an error message with a function name. Handle things. /// /// @param ermsg must be passed without translation (use N_() instead of _()). /// @param name function name -void emsg_funcname(char *ermsg, const char_u *name) +void emsg_funcname(char *ermsg, const char *name) { - char_u *p; + char *p; - if (*name == K_SPECIAL) { - p = (char_u *)concat_str("", (char *)name + 3); + if ((uint8_t)(*name) == K_SPECIAL) { + p = concat_str("", name + 3); } else { - p = (char_u *)name; + p = (char *)name; } semsg(_(ermsg), p); @@ -447,7 +447,7 @@ void emsg_funcname(char *ermsg, const char_u *name) /// @param funcexe various values /// /// @return OK or FAIL. -int get_func_tv(const char_u *name, int len, typval_T *rettv, char **arg, funcexe_T *funcexe) +int get_func_tv(const char *name, int len, typval_T *rettv, char **arg, funcexe_T *funcexe) { char *argp; int ret = OK; @@ -491,7 +491,7 @@ int get_func_tv(const char_u *name, int len, typval_T *rettv, char **arg, funcex ((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i]; } } - ret = call_func((char *)name, len, rettv, argcount, argvars, funcexe); + ret = call_func(name, len, rettv, argcount, argvars, funcexe); funcargs.ga_len -= i; } else if (!aborting()) { @@ -593,7 +593,7 @@ ufunc_T *find_func(const char_u *name) /// Copy the function name of "fp" to buffer "buf". /// "buf" must be able to hold the function name plus three bytes. /// Takes care of script-local function names. -static void cat_func_name(char_u *buf, ufunc_T *fp) +static void cat_func_name(char *buf, ufunc_T *fp) { if ((uint8_t)fp->uf_name[0] == K_SPECIAL) { STRCPY(buf, ""); @@ -1439,28 +1439,25 @@ static void user_func_error(int error, const char_u *name) { switch (error) { case FCERR_UNKNOWN: - emsg_funcname(N_("E117: Unknown function: %s"), name); + emsg_funcname(N_("E117: Unknown function: %s"), (char *)name); break; case FCERR_NOTMETHOD: - emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); + emsg_funcname(N_("E276: Cannot use function as a method: %s"), (char *)name); break; case FCERR_DELETED: - emsg_funcname(N_("E933: Function was deleted: %s"), name); + emsg_funcname(N_("E933: Function was deleted: %s"), (char *)name); break; case FCERR_TOOMANY: - emsg_funcname(_(e_toomanyarg), name); + emsg_funcname(_(e_toomanyarg), (char *)name); break; case FCERR_TOOFEW: - emsg_funcname(N_("E119: Not enough arguments for function: %s"), - name); + emsg_funcname(N_("E119: Not enough arguments for function: %s"), (char *)name); break; case FCERR_SCRIPT: - emsg_funcname(N_("E120: Using not in a script context: %s"), - name); + emsg_funcname(N_("E120: Using not in a script context: %s"), (char *)name); break; case FCERR_DICT: - emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), - name); + emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), (char *)name); break; } } @@ -1652,9 +1649,9 @@ theend: return ret; } -char_u *printable_func_name(ufunc_T *fp) +char *printable_func_name(ufunc_T *fp) { - return fp->uf_name_exp != NULL ? fp->uf_name_exp : (char_u *)fp->uf_name; + return fp->uf_name_exp != NULL ? (char *)fp->uf_name_exp : fp->uf_name; } /// List the head of the function: "name(arg1, arg2)". @@ -1730,8 +1727,8 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa FUNC_ATTR_NONNULL_ARG(1) { char *name = NULL; - const char_u *start; - const char_u *end; + const char *start; + const char *end; int lead; int len; lval_T lv; @@ -1739,7 +1736,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa if (fdp != NULL) { CLEAR_POINTER(fdp); } - start = (char_u *)(*pp); + start = *pp; // Check for hard coded : already translated function ID (from a user // command). @@ -1752,14 +1749,14 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa // A name starting with "" or "" is local to a script. But // don't skip over "s:", get_lval() needs it for "s:dict.func". - lead = eval_fname_script((const char *)start); + lead = eval_fname_script(start); if (lead > 2) { start += lead; } // Note that TFN_ flags use the same values as GLV_ flags. - end = (char_u *)get_lval((char *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, - lead > 2 ? 0 : FNE_CHECK_START); + end = get_lval((char *)start, NULL, &lv, false, skip, flags | GLV_READ_ONLY, + lead > 2 ? 0 : FNE_CHECK_START); if (end == start) { if (!skip) { emsg(_("E129: Function name required")); @@ -1783,7 +1780,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa if (lv.ll_tv != NULL) { if (fdp != NULL) { fdp->fd_dict = lv.ll_dict; - fdp->fd_newkey = (char_u *)lv.ll_newkey; + fdp->fd_newkey = lv.ll_newkey; lv.ll_newkey = NULL; fdp->fd_di = lv.ll_di; } @@ -1793,7 +1790,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa } else if (lv.ll_tv->v_type == VAR_PARTIAL && lv.ll_tv->vval.v_partial != NULL) { if (is_luafunc(lv.ll_tv->vval.v_partial) && *end == '.') { - len = check_luafunc_name((const char *)end + 1, true); + len = check_luafunc_name(end + 1, true); if (len == 0) { semsg(e_invexpr2, "v:lua"); goto theend; @@ -1830,15 +1827,14 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa // Check if the name is a Funcref. If so, use the value. if (lv.ll_exp_name != NULL) { len = (int)strlen(lv.ll_exp_name); - name = (char *)deref_func_name(lv.ll_exp_name, &len, partial, - flags & TFN_NO_AUTOLOAD); + name = deref_func_name(lv.ll_exp_name, &len, partial, + flags & TFN_NO_AUTOLOAD); if ((const char *)name == lv.ll_exp_name) { name = NULL; } } else if (!(flags & TFN_NO_DEREF)) { - len = (int)(end - (char_u *)(*pp)); - name = (char *)deref_func_name((const char *)(*pp), &len, partial, - flags & TFN_NO_AUTOLOAD); + len = (int)(end - *pp); + name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD); if (name == *pp) { name = NULL; } @@ -1873,7 +1869,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa lv.ll_name += 2; lv.ll_name_len -= 2; } - len = (int)((const char *)end - lv.ll_name); + len = (int)(end - lv.ll_name); } size_t sid_buf_len = 0; @@ -1904,7 +1900,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa } if (!skip && !(flags & TFN_QUIET) && !(flags & TFN_NO_DEREF)) { - char_u *cp = xmemrchr(lv.ll_name, ':', lv.ll_name_len); + char *cp = xmemrchr(lv.ll_name, ':', lv.ll_name_len); if (cp != NULL && cp < end) { semsg(_("E884: Function name cannot contain a colon: %s"), start); @@ -2162,7 +2158,7 @@ void ex_function(exarg_T *eap) msg_puts(eap->forceit ? "endfunction" : " endfunction"); } } else { - emsg_funcname(N_("E123: Undefined function: %s"), (char_u *)name); + emsg_funcname(N_("E123: Undefined function: %s"), name); } } goto ret_free; @@ -2182,8 +2178,8 @@ void ex_function(exarg_T *eap) } p = skipwhite(p + 1); - ga_init(&newargs, (int)sizeof(char_u *), 3); - ga_init(&newlines, (int)sizeof(char_u *), 3); + ga_init(&newargs, (int)sizeof(char *), 3); + ga_init(&newlines, (int)sizeof(char *), 3); if (!eap->skip) { // Check the name of the function. Unless it's a dictionary function @@ -2191,7 +2187,7 @@ void ex_function(exarg_T *eap) if (name != NULL) { arg = name; } else { - arg = (char *)fudi.fd_newkey; + arg = fudi.fd_newkey; } if (arg != NULL && (fudi.fd_di == NULL || !tv_is_func(fudi.fd_di->di_tv))) { int j = ((uint8_t)(*arg) == K_SPECIAL) ? 3 : 0; @@ -2199,7 +2195,7 @@ void ex_function(exarg_T *eap) j++; } if (arg[j] != NUL) { - emsg_funcname((char *)e_invarg2, (char_u *)arg); + emsg_funcname((char *)e_invarg2, arg); } } // Disallow using the g: dict. @@ -2235,7 +2231,7 @@ void ex_function(exarg_T *eap) p += 7; if (current_funccal == NULL) { emsg_funcname(N_("E932: Closure function should not be at top level: %s"), - name == NULL ? (char_u *)"" : (char_u *)name); + name == NULL ? "" : name); goto erret; } } else { @@ -2260,7 +2256,7 @@ void ex_function(exarg_T *eap) if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) { emsg(_(e_funcdict)); } else if (name != NULL && find_func((char_u *)name) != NULL) { - emsg_funcname(e_funcexts, (char_u *)name); + emsg_funcname(e_funcexts, name); } } @@ -2509,8 +2505,7 @@ void ex_function(exarg_T *eap) if (fudi.fd_dict == NULL) { v = find_var((const char *)name, strlen(name), &ht, false); if (v != NULL && v->di_tv.v_type == VAR_FUNC) { - emsg_funcname(N_("E707: Function name conflicts with variable: %s"), - (char_u *)name); + emsg_funcname(N_("E707: Function name conflicts with variable: %s"), name); goto erret; } @@ -2521,12 +2516,11 @@ void ex_function(exarg_T *eap) if (!eap->forceit && (fp->uf_script_ctx.sc_sid != current_sctx.sc_sid || fp->uf_script_ctx.sc_seq == current_sctx.sc_seq)) { - emsg_funcname(e_funcexts, (char_u *)name); + emsg_funcname(e_funcexts, name); goto erret; } if (fp->uf_calls > 0) { - emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), - (char_u *)name); + emsg_funcname(N_("E127: Cannot redefine function %s: It is in use"), name); goto erret; } if (fp->uf_refcount > 1) { @@ -2577,13 +2571,13 @@ void ex_function(exarg_T *eap) if (fp == NULL) { if (fudi.fd_dict == NULL && vim_strchr(name, AUTOLOAD_CHAR) != NULL) { int slen, plen; - char_u *scriptname; + char *scriptname; // Check that the autoload name matches the script name. int j = FAIL; if (SOURCING_NAME != NULL) { - scriptname = (char_u *)autoload_name((const char *)name, strlen(name)); - p = vim_strchr((char *)scriptname, '/'); + scriptname = autoload_name(name, strlen(name)); + p = vim_strchr(scriptname, '/'); plen = (int)strlen(p); slen = (int)strlen(SOURCING_NAME); if (slen > plen && path_fnamecmp(p, SOURCING_NAME + slen - plen) == 0) { @@ -2706,7 +2700,7 @@ bool translated_function_exists(const char *name) /// @return true if it exists, false otherwise. bool function_exists(const char *const name, bool no_deref) { - const char_u *nm = (const char_u *)name; + const char *nm = name; bool n = false; int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD; @@ -2714,7 +2708,7 @@ bool function_exists(const char *const name, bool no_deref) flag |= TFN_NO_DEREF; } char *const p = (char *)trans_function_name((char **)&nm, false, flag, NULL, NULL); - nm = (char_u *)skipwhite((char *)nm); + nm = skipwhite(nm); // Only accept "funcname", "funcname ", "funcname (..." and // "funcname(...", not "funcname!...". @@ -2758,7 +2752,7 @@ char *get_user_func_name(expand_T *xp, int idx) return (char *)fp->uf_name; // Prevent overflow. } - cat_func_name((char_u *)IObuff, fp); + cat_func_name(IObuff, fp); if (xp->xp_context != EXPAND_USER_FUNC) { STRCAT(IObuff, "("); if (!fp->uf_varargs && GA_EMPTY(&fp->uf_args)) { @@ -2774,12 +2768,12 @@ char *get_user_func_name(expand_T *xp, int idx) void ex_delfunction(exarg_T *eap) { ufunc_T *fp = NULL; - char_u *p; + char *p; char_u *name; funcdict_T fudi; - p = (char_u *)eap->arg; - name = trans_function_name((char **)&p, eap->skip, 0, &fudi, NULL); + p = eap->arg; + name = trans_function_name(&p, eap->skip, 0, &fudi, NULL); xfree(fudi.fd_newkey); if (name == NULL) { if (fudi.fd_dict != NULL && !eap->skip) { @@ -2787,12 +2781,12 @@ void ex_delfunction(exarg_T *eap) } return; } - if (!ends_excmd(*skipwhite((char *)p))) { + if (!ends_excmd(*skipwhite(p))) { xfree(name); semsg(_(e_trailing_arg), p); return; } - eap->nextcmd = check_nextcmd((char *)p); + eap->nextcmd = check_nextcmd(p); if (eap->nextcmd != NULL) { *p = NUL; } @@ -3043,7 +3037,7 @@ void ex_call(exarg_T *eap) // contents. For VAR_PARTIAL get its partial, unless we already have one // from trans_function_name(). len = (int)strlen(tofree); - name = (char *)deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); + name = deref_func_name(tofree, &len, partial != NULL ? NULL : &partial, false); // Skip white space to allow ":call func ()". Not good, but required for // backward compatibility. @@ -3077,7 +3071,7 @@ void ex_call(exarg_T *eap) funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = fudi.fd_dict; - if (get_func_tv((char_u *)name, -1, &rettv, &arg, &funcexe) == FAIL) { + if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL) { failed = true; break; } diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h index 1255f86103..c8583f232c 100644 --- a/src/nvim/eval/userfunc.h +++ b/src/nvim/eval/userfunc.h @@ -36,7 +36,7 @@ struct funccal_entry; /// Structure used by trans_function_name() typedef struct { dict_T *fd_dict; ///< Dictionary used. - char_u *fd_newkey; ///< New key in "dict" in allocated memory. + char *fd_newkey; ///< New key in "dict" in allocated memory. dictitem_T *fd_di; ///< Dictionary item used. } funcdict_T; diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 62138221e6..463313efd8 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -1112,7 +1112,7 @@ int get_var_tv(const char *name, int len, typval_T *rettv, dictitem_T **dip, boo /// NULL when it doesn't exist. /// /// @see tv_get_string() for how long the pointer remains valid. -char_u *get_var_value(const char *const name) +char *get_var_value(const char *const name) { dictitem_T *v; @@ -1120,7 +1120,7 @@ char_u *get_var_value(const char *const name) if (v == NULL) { return NULL; } - return (char_u *)tv_get_string(&v->di_tv); + return (char *)tv_get_string(&v->di_tv); } /// Clean up a list of internal variables. diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 50b25378e4..4bcbc13534 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -766,7 +766,7 @@ void f_winnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "winrestcmd()" function void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char_u buf[50]; + char buf[50]; garray_T ga; ga_init(&ga, (int)sizeof(char), 70); @@ -775,12 +775,12 @@ void f_winrestcmd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) for (int i = 0; i < 2; i++) { int winnr = 1; FOR_ALL_WINDOWS_IN_TAB(wp, curtab) { - snprintf((char *)buf, sizeof(buf), "%dresize %d|", winnr, + snprintf(buf, sizeof(buf), "%dresize %d|", winnr, wp->w_height); - ga_concat(&ga, (char *)buf); - snprintf((char *)buf, sizeof(buf), "vert %dresize %d|", winnr, + ga_concat(&ga, buf); + snprintf(buf, sizeof(buf), "vert %dresize %d|", winnr, wp->w_width); - ga_concat(&ga, (char *)buf); + ga_concat(&ga, buf); winnr++; } } -- cgit From 9220755302317e8030c5bbf334357c0d64df9fa4 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 14 Jan 2023 00:48:10 +0100 Subject: build: remove clint error suppression #21782 Fix remaining clint errors and remove error suppression completely. Rename the lint targets to align with the established naming convention: - lintc-clint lints with clint.py. - lintc-uncrustify lints with uncrustify. - lintc runs both targets. lintc is also provided as a make target for convenience. After this change we can remove these files: https://github.com/neovim/doc/tree/gh-pages/reports/clint https://github.com/neovim/doc/blob/main/ci/clint-errors.sh --- src/nvim/eval/typval.h | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/typval_encode.c.h | 26 ++++++++++++-------------- 3 files changed, 14 insertions(+), 16 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 8ff7f7f43a..1ee3b5bf69 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -434,7 +434,7 @@ extern bool tv_in_free_unref_items; /// @param li Name of the variable with current listitem_T entry. /// @param code Cycle body. #define TV_LIST_ITER(l, li, code) \ - _TV_LIST_ITER_MOD( , l, li, code) + _TV_LIST_ITER_MOD( , l, li, code) // NOLINT(whitespace/parens) /// Iterate over a list /// diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index f025f21cf7..939e5d0810 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -206,7 +206,7 @@ typedef struct { struct { \ typval_T di_tv; /* Structure that holds scope dictionary itself. */ \ uint8_t di_flags; /* Flags. */ \ - char_u di_key[__VA_ARGS__]; /* Key value. */ \ + char_u di_key[__VA_ARGS__]; /* Key value. */ /* NOLINT(runtime/arrays)*/ \ } /// Structure to hold a scope dictionary diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index ff4f92e40b..6c931d3f88 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -266,7 +266,7 @@ static inline int _TYPVAL_ENCODE_CHECK_SELF_REFERENCE( const MPConvStack *const mpstack, const int copyID, const MPConvStackValType conv_type, const char *const objname) -REAL_FATTR_NONNULL_ARG(2, 3, 4, 7) REAL_FATTR_WARN_UNUSED_RESULT + REAL_FATTR_NONNULL_ARG(2, 3, 4, 7) REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE; /// Function for checking whether container references itself @@ -301,7 +301,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( MPConvStack *const mpstack, MPConvStackVal *const cur_mpsv, typval_T *const tv, const int copyID, const char *const objname) -REAL_FATTR_NONNULL_ARG(2, 4, 6) REAL_FATTR_WARN_UNUSED_RESULT; + REAL_FATTR_NONNULL_ARG(2, 4, 6) REAL_FATTR_WARN_UNUSED_RESULT; /// Convert single value /// @@ -358,7 +358,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( .pt = tv->vval.v_partial, }, }, - })); + })); break; } case VAR_LIST: { @@ -381,7 +381,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( .li = tv_list_first(tv->vval.v_list), }, }, - })); + })); TYPVAL_ENCODE_CONV_REAL_LIST_AFTER_START(tv, _mp_last(*mpstack)); break; } @@ -459,8 +459,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( const listitem_T *const highest_bits_li = ( TV_LIST_ITEM_NEXT(val_list, sign_li)); if (TV_LIST_ITEM_TV(highest_bits_li)->v_type != VAR_NUMBER - || ((highest_bits - = TV_LIST_ITEM_TV(highest_bits_li)->vval.v_number) + || ((highest_bits = TV_LIST_ITEM_TV(highest_bits_li)->vval.v_number) < 0)) { goto _convert_one_value_regular_dict; } @@ -536,7 +535,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( .li = tv_list_first(val_di->di_tv.vval.v_list), }, }, - })); + })); break; } case kMPMap: { @@ -571,7 +570,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( .li = tv_list_first(val_list), }, }, - })); + })); break; } case kMPExt: { @@ -581,8 +580,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( || tv_list_len((val_list = val_di->di_tv.vval.v_list)) != 2 || (TV_LIST_ITEM_TV(tv_list_first(val_list))->v_type != VAR_NUMBER) - || ((type - = TV_LIST_ITEM_TV(tv_list_first(val_list))->vval.v_number) + || ((type = TV_LIST_ITEM_TV(tv_list_first(val_list))->vval.v_number) > INT8_MAX) || type < INT8_MIN || (TV_LIST_ITEM_TV(tv_list_last(val_list))->v_type @@ -622,7 +620,7 @@ _convert_one_value_regular_dict: {} .todo = tv->vval.v_dict->dv_hashtab.ht_used, }, }, - })); + })); TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(tv, tv->vval.v_dict, _mp_last(*mpstack)); break; @@ -640,7 +638,7 @@ typval_encode_stop_converting_one_item: TYPVAL_ENCODE_SCOPE int _TYPVAL_ENCODE_ENCODE( TYPVAL_ENCODE_FIRST_ARG_TYPE TYPVAL_ENCODE_FIRST_ARG_NAME, typval_T *const tv, const char *const objname) -REAL_FATTR_NONNULL_ARG(2, 3) REAL_FATTR_WARN_UNUSED_RESULT; + REAL_FATTR_NONNULL_ARG(2, 3) REAL_FATTR_WARN_UNUSED_RESULT; /// Convert the whole typval /// @@ -758,7 +756,7 @@ typval_encode_stop_converting_one_item: .todo = (size_t)pt->pt_argc, }, }, - })); + })); } break; case kMPConvPartialSelf: { @@ -797,7 +795,7 @@ typval_encode_stop_converting_one_item: .todo = dict->dv_hashtab.ht_used, }, }, - })); + })); TYPVAL_ENCODE_CONV_REAL_DICT_AFTER_START(NULL, pt->pt_dict, _mp_last(mpstack)); } else { -- cgit From e89c39d6f016a4140293755250e968e839009617 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sat, 14 Jan 2023 08:58:28 +0100 Subject: refactor: replace char_u with char 21 (#21779) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 6 +++--- src/nvim/eval/userfunc.c | 12 ++++++------ src/nvim/eval/vars.c | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 7820b837da..d6b9ca20fc 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -4962,7 +4962,7 @@ static void f_pathshorten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_string = NULL; } else { rettv->vval.v_string = xstrdup(p); - shorten_dir_len((char_u *)rettv->vval.v_string, trim_len); + shorten_dir_len(rettv->vval.v_string, trim_len); } } @@ -5965,7 +5965,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) # endif #endif - simplify_filename((char_u *)rettv->vval.v_string); + simplify_filename(rettv->vval.v_string); } /// "reverse({list})" function @@ -7409,7 +7409,7 @@ static void f_simplify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { const char *const p = tv_get_string(&argvars[0]); rettv->vval.v_string = xstrdup(p); - simplify_filename((char_u *)rettv->vval.v_string); // Simplify in place. + simplify_filename(rettv->vval.v_string); // Simplify in place. rettv->v_type = VAR_STRING; } diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1c0fe20248..c70d56cd25 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -845,7 +845,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett int fixvar_idx = 0; // index in fixvar[] int ai; bool islambda = false; - char_u numbuf[NUMBUFLEN]; + char numbuf[NUMBUFLEN]; char *name; typval_T *tv_to_free[MAX_FUNC_ARGS]; int tv_to_free_len = 0; @@ -984,8 +984,8 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett break; } // "..." argument a:1, a:2, etc. - snprintf((char *)numbuf, sizeof(numbuf), "%d", ai + 1); - name = (char *)numbuf; + snprintf(numbuf, sizeof(numbuf), "%d", ai + 1); + name = numbuf; } if (fixvar_idx < FIXVAR_CNT && strlen(name) <= VAR_SHORT_LEN) { v = (dictitem_T *)&fc->fixvar[fixvar_idx++]; @@ -1524,7 +1524,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t // Make a copy of the name, if it comes from a funcref variable it could // be changed or deleted in the called function. name = xstrnsave(funcname, (size_t)len); - fname = fname_trans_sid(name, (char *)fname_buf, &tofree, &error); + fname = fname_trans_sid(name, fname_buf, &tofree, &error); } if (funcexe->fe_doesrange != NULL) { @@ -3303,7 +3303,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) ? rettv->vval.v_string : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. - fname = fname_trans_sid(fname, (char *)fname_buf, &tofree, &error); + fname = fname_trans_sid(fname, fname_buf, &tofree, &error); fp = find_func((char_u *)fname); xfree(tofree); } @@ -3649,7 +3649,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) } if (fp_in == NULL) { - fname = fname_trans_sid((char *)name, (char *)fname_buf, &tofree, &error); + fname = fname_trans_sid((char *)name, fname_buf, &tofree, &error); fp = find_func((char_u *)fname); } if (fp != NULL) { diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 463313efd8..206df03381 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -864,7 +864,7 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ int cc; if (lp->ll_tv == NULL) { - cc = (char_u)(*name_end); + cc = (uint8_t)(*name_end); *name_end = NUL; // Environment variable, normal name or expanded name. -- cgit From 2065ce877ef81bcd66132bd26e75aa4d761dca12 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 14 Jan 2023 21:36:15 +0800 Subject: vim-patch:partial:9.0.1196: code is indented more than necessary (#21796) Problem: Code is indented more than necessary. Solution: Use an early return where it makes sense. (Yegappan Lakshmanan, closes vim/vim#11813) https://github.com/vim/vim/commit/e8575988969579f9e1439181ae338b2ff74054a8 Partial port as this depends on some previous eval and 'smoothscroll' patches. Co-authored-by: Yegappan Lakshmanan --- src/nvim/eval/typval.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 1de268a9d8..7c61a2f990 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -326,10 +326,12 @@ void tv_list_free_list(list_T *const l) void tv_list_free(list_T *const l) FUNC_ATTR_NONNULL_ALL { - if (!tv_in_free_unref_items) { - tv_list_free_contents(l); - tv_list_free_list(l); + if (tv_in_free_unref_items) { + return; } + + tv_list_free_contents(l); + tv_list_free_list(l); } /// Unreference a list -- cgit From 3269902a13df3bccf8705db73488c0a47f495514 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Sun, 15 Jan 2023 14:16:33 +0100 Subject: refactor: fix IWYU mapping file and use IWYU (#21802) Also add the EXITFREE definition to main_lib rather than the nvim target, as the header generation needs the EXITFREE flag to work properly. --- src/nvim/eval/buffer.c | 1 + src/nvim/eval/encode.h | 1 + src/nvim/eval/userfunc.c | 1 + src/nvim/eval/window.c | 1 + src/nvim/eval/window.h | 10 ++++++++++ 5 files changed, 14 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index 72eb0f8d67..e8eca3f854 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -9,6 +9,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/cursor.h" #include "nvim/eval.h" diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h index e66dab1cff..41e7614fc0 100644 --- a/src/nvim/eval/encode.h +++ b/src/nvim/eval/encode.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "nvim/eval.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index c70d56cd25..1a3fd13fe3 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -45,6 +45,7 @@ #include "nvim/runtime.h" #include "nvim/search.h" #include "nvim/strings.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/vim.h" diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index 4bcbc13534..b1e1669826 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -12,6 +12,7 @@ #include "nvim/ascii.h" #include "nvim/autocmd.h" #include "nvim/buffer.h" +#include "nvim/buffer_defs.h" #include "nvim/cursor.h" #include "nvim/eval/funcs.h" #include "nvim/eval/typval.h" diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h index 682a794113..995f0a55a9 100644 --- a/src/nvim/eval/window.h +++ b/src/nvim/eval/window.h @@ -2,9 +2,19 @@ #define NVIM_EVAL_WINDOW_H #include +#include +#include "nvim/buffer.h" #include "nvim/buffer_defs.h" +#include "nvim/cursor.h" #include "nvim/eval/typval_defs.h" +#include "nvim/globals.h" +#include "nvim/mark.h" +#include "nvim/option_defs.h" +#include "nvim/os/os.h" +#include "nvim/pos.h" +#include "nvim/vim.h" +#include "nvim/window.h" /// Structure used by switch_win() to pass values to restore_win() typedef struct { -- cgit From b4d669e7acd819cd5723b387a5a79023994d438d Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 17 Jan 2023 16:53:37 +0800 Subject: vim-patch:8.2.4928: various white space and cosmetic mistakes (#21854) Problem: Various white space and cosmetic mistakes. Solution: Change spaces to tabs, improve comments. https://github.com/vim/vim/commit/6ed545e79735f23ff8e650bc2f0967e5a0baedc9 Co-authored-by: Bram Moolenaar --- src/nvim/eval/window.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c index b1e1669826..f58a0c488a 100644 --- a/src/nvim/eval/window.c +++ b/src/nvim/eval/window.c @@ -140,6 +140,8 @@ void win_findbuf(typval_T *argvars, list_T *list) /// Find window specified by "vp" in tabpage "tp". /// /// @param tp NULL for current tab page +/// @return current window if "vp" is number zero. +/// NULL if not found. win_T *find_win_by_nr(typval_T *vp, tabpage_T *tp) { int nr = (int)tv_get_number_chk(vp, NULL); -- cgit From 0344bfad0fc87d2e256ea2b80de7abd069ba1dd2 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Tue, 17 Jan 2023 14:17:40 +0100 Subject: refactor: replace char_u with char 22 (#21786) Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/executor.c | 2 +- src/nvim/eval/funcs.c | 20 ++++++++++---------- src/nvim/eval/userfunc.c | 12 ++++++------ src/nvim/eval/vars.c | 20 ++++++++++---------- 4 files changed, 27 insertions(+), 27 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 86d6063b01..831c468288 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -69,7 +69,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons if (tv2->v_type == VAR_LIST) { break; } - if (vim_strchr("+-*/%", *op) != NULL) { + if (vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { // nr += nr or nr -= nr, nr *= nr, nr /= nr, nr %= nr varnumber_T n = tv_get_number(tv1); if (tv2->v_type == VAR_FLOAT) { diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d6b9ca20fc..25e026706c 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -1770,7 +1770,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } size_t len; char *errormsg = NULL; - char *result = (char *)eval_vars((char_u *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); + char *result = (char *)eval_vars((char *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); if (p_verbose == 0) { emsg_off--; } else if (errormsg != NULL) { @@ -4488,7 +4488,7 @@ static void find_some_match(typval_T *const argvars, typval_T *const rettv, } } - match = vim_regexec_nl(®match, (char_u *)str, startcol); + match = vim_regexec_nl(®match, str, startcol); if (match && --nth <= 0) { break; @@ -5885,7 +5885,7 @@ static void f_resolve(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) q[-1] = NUL; q = path_tail(p); } - if (q > p && !path_is_absolute((const char_u *)buf)) { + if (q > p && !path_is_absolute(buf)) { // Symlink is relative to directory of argument. Replace the // symlink with the resolved name in the same directory. const size_t p_len = strlen(p); @@ -6228,7 +6228,7 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) // Repeat until {skip} returns false. for (;;) { subpatnum - = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1, options, RE_SEARCH, &sia); + = searchit(curwin, curbuf, &pos, NULL, dir, (char *)pat, 1, options, RE_SEARCH, &sia); // finding the first match again means there is no match where {skip} // evaluates to zero. if (firstpos.lnum != 0 && equalpos(pos, firstpos)) { @@ -6810,7 +6810,7 @@ long do_searchpair(const char *spat, const char *mpat, const char *epat, int dir .sa_tm = &tm, }; - int n = searchit(curwin, curbuf, &pos, NULL, dir, (char_u *)pat, 1L, + int n = searchit(curwin, curbuf, &pos, NULL, dir, pat, 1L, options, RE_SEARCH, &sia); if (n == FAIL || (firstpos.lnum != 0 && equalpos(pos, firstpos))) { // didn't find it or found the first match again: FAIL @@ -7073,7 +7073,7 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt if (csearch != NULL) { int pcc[MAX_MCO]; const int c = utfc_ptr2char((char *)csearch, pcc); - set_last_csearch(c, csearch, utfc_ptr2len((char *)csearch)); + set_last_csearch(c, (char *)csearch, utfc_ptr2len((char *)csearch)); } dictitem_T *di = tv_dict_find(d, S_LEN("forward")); @@ -7553,7 +7553,7 @@ static void f_spellbadword(typval_T *argvars, typval_T *rettv, EvalFuncData fptr if (str != NULL) { // Check the argument for spelling. while (*str != NUL) { - len = spell_check(curwin, (char_u *)str, &attr, &capcol, false); + len = spell_check(curwin, (char *)str, &attr, &capcol, false); if (attr != HLF_COUNT) { word = str; break; @@ -7668,7 +7668,7 @@ static void f_split(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (*str == NUL) { match = false; // Empty item at the end. } else { - match = vim_regexec_nl(®match, (char_u *)str, col); + match = vim_regexec_nl(®match, (char *)str, col); } const char *end; if (match) { @@ -7930,11 +7930,11 @@ static void strchar_common(typval_T *argvars, typval_T *rettv, bool skipcc) { const char *s = tv_get_string(&argvars[0]); varnumber_T len = 0; - int (*func_mb_ptr2char_adv)(const char_u **pp); + int (*func_mb_ptr2char_adv)(const char **pp); func_mb_ptr2char_adv = skipcc ? mb_ptr2char_adv : mb_cptr2char_adv; while (*s != NUL) { - func_mb_ptr2char_adv((const char_u **)&s); + func_mb_ptr2char_adv(&s); len++; } rettv->vval.v_number = len; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1a3fd13fe3..5d3b70b414 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -118,7 +118,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int while (ASCII_ISALNUM(*p) || *p == '_') { p++; } - if (arg == p || isdigit(*arg) + if (arg == p || isdigit((uint8_t)(*arg)) || (p - arg == 9 && strncmp(arg, "firstline", 9) == 0) || (p - arg == 8 && strncmp(arg, "lastline", 8) == 0)) { if (!skip) { @@ -1228,7 +1228,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett /// looked up by name. static bool func_name_refcount(const char_u *name) { - return isdigit(*name) || *name == '<'; + return isdigit((uint8_t)(*name)) || *name == '<'; } /// Call a user function after checking the arguments. @@ -2002,7 +2002,7 @@ static void list_functions(regmatch_T *regmatch) && (regmatch == NULL ? (!message_filtered((char *)fp->uf_name) && !func_name_refcount((char_u *)fp->uf_name)) - : (!isdigit(*fp->uf_name) + : (!isdigit((uint8_t)(*fp->uf_name)) && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { list_func_head(fp, false, false); if (changed != func_hashtab.ht_changed) { @@ -2792,7 +2792,7 @@ void ex_delfunction(exarg_T *eap) *p = NUL; } - if (isdigit(*name) && fudi.fd_dict == NULL) { + if (isdigit((uint8_t)(*name)) && fudi.fd_dict == NULL) { if (!eap->skip) { semsg(_(e_invarg2), eap->arg); } @@ -2858,7 +2858,7 @@ void func_unref(char_u *name) } fp = find_func(name); - if (fp == NULL && isdigit(*name)) { + if (fp == NULL && isdigit((uint8_t)(*name))) { #ifdef EXITFREE if (!entered_free_all_mem) { internal_error("func_unref()"); @@ -2901,7 +2901,7 @@ void func_ref(char_u *name) fp = find_func(name); if (fp != NULL) { (fp->uf_refcount)++; - } else if (isdigit(*name)) { + } else if (isdigit((uint8_t)(*name))) { // Only give an error for a numbered function. // Fail silently, when named or lambda function isn't found. internal_error("func_ref()"); diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 206df03381..75af99fbd5 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -106,7 +106,7 @@ static list_T *heredoc_get(exarg_T *eap, char *cmd) return NULL; } *p = NUL; - if (islower(*marker)) { + if (islower((uint8_t)(*marker))) { emsg(_("E221: Marker cannot start with lower case letter")); return NULL; } @@ -208,7 +208,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) argend--; } expr = skipwhite(argend); - if (*expr != '=' && !((vim_strchr("+-*/%.", *expr) != NULL + if (*expr != '=' && !((vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL && expr[1] == '=') || strncmp(expr, "..=", 3) == 0)) { // ":let" without "=": list variables if (*arg == '[') { @@ -244,7 +244,7 @@ static void ex_let_const(exarg_T *eap, const bool is_const) op[0] = '='; op[1] = NUL; if (*expr != '=') { - if (vim_strchr("+-*/%.", *expr) != NULL) { + if (vim_strchr("+-*/%.", (uint8_t)(*expr)) != NULL) { op[0] = *expr; // +=, -=, *=, /=, %= or .= if (expr[0] == '.' && expr[1] == '.') { // ..= expr++; @@ -590,10 +590,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo if (len == 0) { semsg(_(e_invarg2), name - 1); } else { - if (op != NULL && vim_strchr("+-*/%", *op) != NULL) { + if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { semsg(_(e_letwrong), op); } else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg)) == NULL) { + && vim_strchr(endchars, (uint8_t)(*skipwhite(arg))) == NULL) { emsg(_(e_letunexp)); } else if (!check_secure()) { char *tofree = NULL; @@ -629,7 +629,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo char *const p = (char *)find_option_end((const char **)&arg, &scope); if (p == NULL || (endchars != NULL - && vim_strchr(endchars, *skipwhite(p)) == NULL)) { + && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) { emsg(_(e_letunexp)); } else { varnumber_T n = 0; @@ -716,10 +716,10 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo return NULL; } arg++; - if (op != NULL && vim_strchr("+-*/%", *op) != NULL) { + if (op != NULL && vim_strchr("+-*/%", (uint8_t)(*op)) != NULL) { semsg(_(e_letwrong), op); } else if (endchars != NULL - && vim_strchr(endchars, *skipwhite(arg + 1)) == NULL) { + && vim_strchr(endchars, (uint8_t)(*skipwhite(arg + 1))) == NULL) { emsg(_(e_letunexp)); } else { char *s; @@ -747,7 +747,7 @@ static char *ex_let_one(char *arg, typval_T *const tv, const bool copy, const bo char *const p = get_lval(arg, tv, &lv, false, false, 0, FNE_CHECK_START); if (p != NULL && lv.ll_name != NULL) { - if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) { + if (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL) { emsg(_(e_letunexp)); } else { set_var_lval(&lv, p, tv, copy, is_const, op); @@ -1464,7 +1464,7 @@ bool var_wrong_func_name(const char *const name, const bool new_var) { // Allow for w: b: s: and t:. // Allow autoload variable. - if (!(vim_strchr("wbst", name[0]) != NULL && name[1] == ':') + if (!(vim_strchr("wbst", (uint8_t)name[0]) != NULL && name[1] == ':') && !ASCII_ISUPPER((name[0] != NUL && name[1] == ':') ? name[2] : name[0]) && vim_strchr(name, '#') == NULL) { semsg(_("E704: Funcref variable name must start with a capital: %s"), name); -- cgit From 2c1e7242f9bed345e520e9060e5e13fe48a023eb Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 18 Jan 2023 11:52:19 +0100 Subject: refactor: replace char_u with char 23 (#21798) Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 2 +- src/nvim/eval/typval_defs.h | 2 +- src/nvim/eval/userfunc.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 25e026706c..648e101fcd 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7612,7 +7612,7 @@ static void f_spellsuggest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr maxcount = 25; } - spell_suggest_list(&ga, (char_u *)str, maxcount, need_capital, false); + spell_suggest_list(&ga, (char *)str, maxcount, need_capital, false); f_spellsuggest_return: tv_list_alloc_ret(rettv, (ptrdiff_t)ga.ga_len); diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h index 939e5d0810..4615198441 100644 --- a/src/nvim/eval/typval_defs.h +++ b/src/nvim/eval/typval_defs.h @@ -337,7 +337,7 @@ struct ufunc { ///< used for s: variables int uf_refcount; ///< reference count, see func_name_refcount() funccall_T *uf_scoped; ///< l: local variables for closure - char_u *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with + char *uf_name_exp; ///< if "uf_name[]" starts with SNR the name with ///< "" as a string, otherwise NULL char uf_name[]; ///< Name of function (actual size equals name); ///< can start with 123_ diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 5d3b70b414..41dc7d5e61 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -1652,7 +1652,7 @@ theend: char *printable_func_name(ufunc_T *fp) { - return fp->uf_name_exp != NULL ? (char *)fp->uf_name_exp : fp->uf_name; + return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name; } /// List the head of the function: "name(arg1, arg2)". @@ -2296,7 +2296,7 @@ void ex_function(exarg_T *eap) } else { xfree(line_to_free); if (eap->getline == NULL) { - theline = (char *)getcmdline(':', 0L, indent, do_concat); + theline = getcmdline(':', 0L, indent, do_concat); } else { theline = eap->getline(':', eap->cookie, indent, do_concat); } @@ -2532,7 +2532,7 @@ void ex_function(exarg_T *eap) fp = NULL; overwrite = true; } else { - char_u *exp_name = fp->uf_name_exp; + char *exp_name = fp->uf_name_exp; // redefine existing function, keep the expanded name XFREE_CLEAR(name); fp->uf_name_exp = NULL; -- cgit From 8a4285d5637c146a0ae606918a8e77063c6a5f0d Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Wed, 18 Jan 2023 14:17:11 +0100 Subject: refactor: replace char_u with char 24 (#21823) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/buffer.c | 4 +-- src/nvim/eval/funcs.c | 24 ++++++------- src/nvim/eval/typval.c | 12 +++---- src/nvim/eval/userfunc.c | 92 ++++++++++++++++++++++++------------------------ 4 files changed, 66 insertions(+), 66 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c index e8eca3f854..2f37d1ba2e 100644 --- a/src/nvim/eval/buffer.c +++ b/src/nvim/eval/buffer.c @@ -278,9 +278,9 @@ void f_appendbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) /// "bufadd(expr)" function void f_bufadd(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) { - char_u *name = (char_u *)tv_get_string(&argvars[0]); + char *name = (char *)tv_get_string(&argvars[0]); - rettv->vval.v_number = buflist_add(*name == NUL ? NULL : (char *)name, 0); + rettv->vval.v_number = buflist_add(*name == NUL ? NULL : name, 0); } /// "bufexists(expr)" function diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 648e101fcd..6a677dd675 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -244,11 +244,11 @@ int call_internal_func(const char *const fname, const int argcount, typval_T *co } /// Invoke a method for base->method(). -int call_internal_method(const char_u *const fname, const int argcount, typval_T *const argvars, +int call_internal_method(const char *const fname, const int argcount, typval_T *const argvars, typval_T *const rettv, typval_T *const basetv) FUNC_ATTR_NONNULL_ALL { - const EvalFuncDef *const fdef = find_internal_func((const char *)fname); + const EvalFuncDef *const fdef = find_internal_func(fname); if (fdef == NULL) { return FCERR_UNKNOWN; } else if (fdef->base_arg == BASE_NONE) { @@ -572,16 +572,16 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) if (argvars[2].v_type != VAR_DICT) { emsg(_(e_dictreq)); if (owned) { - func_unref((char_u *)func); + func_unref(func); } return; } selfdict = argvars[2].vval.v_dict; } - func_call((char_u *)func, &argvars[1], partial, selfdict, rettv); + func_call(func, &argvars[1], partial, selfdict, rettv); if (owned) { - func_unref((char_u *)func); + func_unref(func); } } @@ -2248,7 +2248,7 @@ static void f_get(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->v_type = (*what == 'f' ? VAR_FUNC : VAR_STRING); assert(name != NULL); if (rettv->v_type == VAR_FUNC) { - func_ref((char_u *)name); + func_ref((char *)name); } if (*what == 'n' && pt->pt_name == NULL && pt->pt_func != NULL) { // use instead of the byte code @@ -2982,7 +2982,7 @@ static void f_globpath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const char *const file = tv_get_string_buf_chk(&argvars[1], buf1); if (file != NULL && !error) { garray_T ga; - ga_init(&ga, (int)sizeof(char_u *), 10); + ga_init(&ga, (int)sizeof(char *), 10); globpath((char *)tv_get_string(&argvars[0]), (char *)file, &ga, flags); if (rettv->v_type == VAR_STRING) { @@ -6468,7 +6468,7 @@ static void f_rpcstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) // Allocate extra memory for the argument vector and the NULL pointer int argvl = argsl + 2; - char **argv = xmalloc(sizeof(char_u *) * (size_t)argvl); + char **argv = xmalloc(sizeof(char *) * (size_t)argvl); // Copy program name argv[0] = xstrdup(argvars[0].vval.v_string); @@ -6644,7 +6644,7 @@ static void f_searchdecl(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } } if (!error && name != NULL) { - rettv->vval.v_number = find_decl((char_u *)name, strlen(name), locally, + rettv->vval.v_number = find_decl((char *)name, strlen(name), locally, thisblock, SEARCH_KEEP) == FAIL; } } @@ -7069,11 +7069,11 @@ static void f_setcharsearch(typval_T *argvars, typval_T *rettv, EvalFuncData fpt return; } - char_u *const csearch = (char_u *)tv_dict_get_string(d, "char", false); + char *const csearch = tv_dict_get_string(d, "char", false); if (csearch != NULL) { int pcc[MAX_MCO]; - const int c = utfc_ptr2char((char *)csearch, pcc); - set_last_csearch(c, (char *)csearch, utfc_ptr2len((char *)csearch)); + const int c = utfc_ptr2char(csearch, pcc); + set_last_csearch(c, csearch, utfc_ptr2len(csearch)); } dictitem_T *di = tv_dict_find(d, S_LEN("forward")); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 7c61a2f990..5a356813f0 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1599,7 +1599,7 @@ void callback_free(Callback *callback) { switch (callback->type) { case kCallbackFuncref: - func_unref((char_u *)callback->data.funcref); + func_unref(callback->data.funcref); xfree(callback->data.funcref); break; case kCallbackPartial: @@ -1628,7 +1628,7 @@ void callback_put(Callback *cb, typval_T *tv) case kCallbackFuncref: tv->v_type = VAR_FUNC; tv->vval.v_string = xstrdup(cb->data.funcref); - func_ref((char_u *)cb->data.funcref); + func_ref(cb->data.funcref); break; case kCallbackLua: // TODO(tjdevries): Unified Callback. @@ -1654,7 +1654,7 @@ void callback_copy(Callback *dest, Callback *src) break; case kCallbackFuncref: dest->data.funcref = xstrdup(src->data.funcref); - func_ref((char_u *)src->data.funcref); + func_ref(src->data.funcref); break; case kCallbackLua: dest->data.luaref = api_new_luaref(src->data.luaref); @@ -3019,7 +3019,7 @@ static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun return OK; } } else { - func_unref(fun); + func_unref((char *)fun); if ((const char *)fun != tv_empty_string) { xfree(fun); } @@ -3235,7 +3235,7 @@ void tv_free(typval_T *tv) partial_unref(tv->vval.v_partial); break; case VAR_FUNC: - func_unref((char_u *)tv->vval.v_string); + func_unref(tv->vval.v_string); FALLTHROUGH; case VAR_STRING: xfree(tv->vval.v_string); @@ -3288,7 +3288,7 @@ void tv_copy(const typval_T *const from, typval_T *const to) if (from->vval.v_string != NULL) { to->vval.v_string = xstrdup(from->vval.v_string); if (from->v_type == VAR_FUNC) { - func_ref((char_u *)to->vval.v_string); + func_ref(to->vval.v_string); } } break; diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 41dc7d5e61..1d27826e7a 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -84,7 +84,7 @@ hashtab_T *func_tbl_get(void) } /// Get function arguments. -static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int *varargs, +static int get_function_args(char **argp, char endchar, garray_T *newargs, int *varargs, garray_T *default_args, bool skip) { bool mustend = false; @@ -106,7 +106,7 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int // Isolate the arguments: "arg1, arg2, ...)" bool any_default = false; - while (*p != (char)endchar) { + while (*p != endchar) { if (p[0] == '.' && p[1] == '.' && p[2] == '.') { if (varargs != NULL) { *varargs = true; @@ -188,14 +188,14 @@ static int get_function_args(char **argp, char_u endchar, garray_T *newargs, int } } p = skipwhite(p); - if (mustend && *p != (char)endchar) { + if (mustend && *p != endchar) { if (!skip) { semsg(_(e_invarg2), *argp); } break; } } - if (*p != (char)endchar) { + if (*p != endchar) { goto err_ret; } p++; // skip "endchar" @@ -229,12 +229,12 @@ static void register_closure(ufunc_T *fp) } /// @return a name for a lambda. Returned in static memory. -char_u *get_lambda_name(void) +char *get_lambda_name(void) { - static char_u name[30]; + static char name[30]; static int lambda_no = 0; - snprintf((char *)name, sizeof(name), "%d", ++lambda_no); + snprintf(name, sizeof(name), "%d", ++lambda_no); return name; } @@ -308,7 +308,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, bool evaluate) char *p; garray_T newlines; - char *name = (char *)get_lambda_name(); + char *name = get_lambda_name(); fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); pt = xcalloc(1, sizeof(partial_T)); @@ -1226,7 +1226,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett /// For the first we only count the name stored in func_hashtab as a reference, /// using function() does not count as a reference, because the function is /// looked up by name. -static bool func_name_refcount(const char_u *name) +static bool func_name_refcount(const char *name) { return isdigit((uint8_t)(*name)) || *name == '<'; } @@ -1319,7 +1319,7 @@ void free_all_functions(void) // Only free functions that are not refcounted, those are // supposed to be freed when no longer referenced. fp = HI2UF(hi); - if (func_name_refcount((char_u *)fp->uf_name)) { + if (func_name_refcount(fp->uf_name)) { skipped++; } else { changed = func_hashtab.ht_changed; @@ -1345,7 +1345,7 @@ void free_all_functions(void) // Only free functions that are not refcounted, those are // supposed to be freed when no longer referenced. fp = HI2UF(hi); - if (func_name_refcount((char_u *)fp->uf_name)) { + if (func_name_refcount(fp->uf_name)) { skipped++; } else { func_free(fp); @@ -1382,7 +1382,7 @@ static bool builtin_function(const char *name, int len) return p == NULL; } -int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv) +int func_call(char *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv) { typval_T argv[MAX_FUNC_ARGS + 1]; int argc = 0; @@ -1404,7 +1404,7 @@ int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict funcexe.fe_evaluate = true; funcexe.fe_partial = partial; funcexe.fe_selfdict = selfdict; - r = call_func((char *)name, -1, rettv, argc, argv, &funcexe); + r = call_func(name, -1, rettv, argc, argv, &funcexe); func_call_skip_call: // Free the arguments. @@ -1435,30 +1435,30 @@ varnumber_T callback_call_retnr(Callback *callback, int argcount, typval_T *argv /// Give an error message for the result of a function. /// Nothing if "error" is FCERR_NONE. -static void user_func_error(int error, const char_u *name) +static void user_func_error(int error, const char *name) FUNC_ATTR_NONNULL_ALL { switch (error) { case FCERR_UNKNOWN: - emsg_funcname(N_("E117: Unknown function: %s"), (char *)name); + emsg_funcname(N_("E117: Unknown function: %s"), name); break; case FCERR_NOTMETHOD: - emsg_funcname(N_("E276: Cannot use function as a method: %s"), (char *)name); + emsg_funcname(N_("E276: Cannot use function as a method: %s"), name); break; case FCERR_DELETED: - emsg_funcname(N_("E933: Function was deleted: %s"), (char *)name); + emsg_funcname(N_("E933: Function was deleted: %s"), name); break; case FCERR_TOOMANY: - emsg_funcname(_(e_toomanyarg), (char *)name); + emsg_funcname(_(e_toomanyarg), name); break; case FCERR_TOOFEW: - emsg_funcname(N_("E119: Not enough arguments for function: %s"), (char *)name); + emsg_funcname(N_("E119: Not enough arguments for function: %s"), name); break; case FCERR_SCRIPT: - emsg_funcname(N_("E120: Using not in a script context: %s"), (char *)name); + emsg_funcname(N_("E120: Using not in a script context: %s"), name); break; case FCERR_DICT: - emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), (char *)name); + emsg_funcname(N_("E725: Calling dict function without Dictionary: %s"), name); break; } } @@ -1612,7 +1612,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t } else if (funcexe->fe_basetv != NULL) { // expr->method(): Find the method name in the table, call its // implementation with the base as one of the arguments. - error = call_internal_method((char_u *)fname, argcount, argvars, rettv, + error = call_internal_method(fname, argcount, argvars, rettv, funcexe->fe_basetv); } else { // Find the function name in the table, call its implementation. @@ -1636,7 +1636,7 @@ theend: // Report an error unless the argument evaluation or function call has been // cancelled due to an aborting error, an interrupt, or an exception. if (!aborting()) { - user_func_error(error, (name != NULL) ? (char_u *)name : (char_u *)funcname); + user_func_error(error, (name != NULL) ? name : funcname); } // clear the copies made from the partial @@ -1724,7 +1724,7 @@ static void list_func_head(ufunc_T *fp, int indent, bool force) /// @param partial return: partial of a FuncRef /// /// @return the function name in allocated memory, or NULL for failure. -char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial) +char *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, partial_T **partial) FUNC_ATTR_NONNULL_ARG(1) { char *name = NULL; @@ -1745,7 +1745,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa && (*pp)[2] == KE_SNR) { *pp += 3; len = get_id_len((const char **)pp) + 3; - return (char_u *)xmemdupz(start, (size_t)len); + return xmemdupz(start, (size_t)len); } // A name starting with "" or "" is local to a script. But @@ -1924,7 +1924,7 @@ char_u *trans_function_name(char **pp, bool skip, int flags, funcdict_T *fdp, pa theend: clear_lval(&lv); - return (char_u *)name; + return name; } /// If the "funcname" starts with "s:" or "", then expands it to the @@ -1976,7 +1976,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi) CLEAR_POINTER(fudi); } } else { - saved = (char *)trans_function_name(&p, skip, flags, fudi, NULL); + saved = trans_function_name(&p, skip, flags, fudi, NULL); } *name = p; return saved; @@ -2001,7 +2001,7 @@ static void list_functions(regmatch_T *regmatch) if ((fp->uf_flags & FC_DEAD) == 0 && (regmatch == NULL ? (!message_filtered((char *)fp->uf_name) - && !func_name_refcount((char_u *)fp->uf_name)) + && !func_name_refcount(fp->uf_name)) : (!isdigit((uint8_t)(*fp->uf_name)) && vim_regexec(regmatch, (char *)fp->uf_name, 0)))) { list_func_head(fp, false, false); @@ -2708,7 +2708,7 @@ bool function_exists(const char *const name, bool no_deref) if (no_deref) { flag |= TFN_NO_DEREF; } - char *const p = (char *)trans_function_name((char **)&nm, false, flag, NULL, NULL); + char *const p = trans_function_name((char **)&nm, false, flag, NULL, NULL); nm = skipwhite(nm); // Only accept "funcname", "funcname ", "funcname (..." and @@ -2770,7 +2770,7 @@ void ex_delfunction(exarg_T *eap) { ufunc_T *fp = NULL; char *p; - char_u *name; + char *name; funcdict_T fudi; p = eap->arg; @@ -2800,7 +2800,7 @@ void ex_delfunction(exarg_T *eap) return; } if (!eap->skip) { - fp = find_func(name); + fp = find_func((char_u *)name); } xfree(name); @@ -2833,7 +2833,7 @@ void ex_delfunction(exarg_T *eap) // it and the refcount is more than one, it should be kept. // A numbered function or lambda should be kept if the refcount is // one or more. - if (fp->uf_refcount > (func_name_refcount((char_u *)fp->uf_name) ? 0 : 1)) { + if (fp->uf_refcount > (func_name_refcount(fp->uf_name) ? 0 : 1)) { // Function is still referenced somewhere. Don't free it but // do remove it from the hashtable. if (func_remove(fp)) { @@ -2849,7 +2849,7 @@ void ex_delfunction(exarg_T *eap) /// Unreference a Function: decrement the reference count and free it when it /// becomes zero. -void func_unref(char_u *name) +void func_unref(char *name) { ufunc_T *fp = NULL; @@ -2857,7 +2857,7 @@ void func_unref(char_u *name) return; } - fp = find_func(name); + fp = find_func((char_u *)name); if (fp == NULL && isdigit((uint8_t)(*name))) { #ifdef EXITFREE if (!entered_free_all_mem) { @@ -2891,14 +2891,14 @@ void func_ptr_unref(ufunc_T *fp) } /// Count a reference to a Function. -void func_ref(char_u *name) +void func_ref(char *name) { ufunc_T *fp; if (name == NULL || !func_name_refcount(name)) { return; } - fp = find_func(name); + fp = find_func((char_u *)name); if (fp != NULL) { (fp->uf_refcount)++; } else if (isdigit((uint8_t)(*name))) { @@ -3018,7 +3018,7 @@ void ex_call(exarg_T *eap) return; } - tofree = (char *)trans_function_name(&arg, false, TFN_INT, &fudi, &partial); + tofree = trans_function_name(&arg, false, TFN_INT, &fudi, &partial); if (fudi.fd_newkey != NULL) { // Still need to give an error message for missing key. semsg(_(e_dictkey), fudi.fd_newkey); @@ -3328,7 +3328,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) // be referenced elsewhere. if (ret_pt->pt_name != NULL) { pt->pt_name = xstrdup(ret_pt->pt_name); - func_ref((char_u *)pt->pt_name); + func_ref(pt->pt_name); } else { pt->pt_func = ret_pt->pt_func; func_ptr_ref(pt->pt_func); @@ -3349,9 +3349,9 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) } /// @return the name of the executed function. -char_u *func_name(void *cookie) +char *func_name(void *cookie) { - return (char_u *)((funccall_T *)cookie)->func->uf_name; + return ((funccall_T *)cookie)->func->uf_name; } /// @return the address holding the next breakpoint line for a funccall cookie. @@ -3610,7 +3610,7 @@ bool set_ref_in_functions(int copyID) if (!HASHITEM_EMPTY(hi)) { todo--; fp = HI2UF(hi); - if (!func_name_refcount((char_u *)fp->uf_name) + if (!func_name_refcount(fp->uf_name) && set_ref_in_func(NULL, fp, copyID)) { return true; } @@ -3636,7 +3636,7 @@ bool set_ref_in_func_args(int copyID) /// "ht_stack" is used to add hashtabs to be marked. Can be NULL. /// /// @return true if setting references failed somehow. -bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) +bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) { ufunc_T *fp = fp_in; funccall_T *fc; @@ -3650,7 +3650,7 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) } if (fp_in == NULL) { - fname = fname_trans_sid((char *)name, fname_buf, &tofree, &error); + fname = fname_trans_sid(name, fname_buf, &tofree, &error); fp = find_func((char_u *)fname); } if (fp != NULL) { @@ -3663,9 +3663,9 @@ bool set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID) } /// Registers a luaref as a lambda. -char_u *register_luafunc(LuaRef ref) +char *register_luafunc(LuaRef ref) { - char *name = (char *)get_lambda_name(); + char *name = get_lambda_name(); ufunc_T *fp = xcalloc(1, offsetof(ufunc_T, uf_name) + strlen(name) + 1); fp->uf_refcount = 1; @@ -3679,5 +3679,5 @@ char_u *register_luafunc(LuaRef ref) hash_add(&func_hashtab, UF2HIKEY(fp)); // coverity[leaked_storage] - return (char_u *)fp->uf_name; + return fp->uf_name; } -- cgit From f8669e8a181abad98229d97439a9cafe8c32fc06 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Thu, 19 Jan 2023 08:03:13 +0800 Subject: vim-patch:8.2.1698: cannot lock a variable in legacy Vim script like in Vim9 (#21883) Problem: Cannot lock a variable in legacy Vim script like in Vim9. Solution: Make ":lockvar 0" work. https://github.com/vim/vim/commit/a187c43cfe8863d48b2159d695fedcb71f8525c1 Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 30 +++++++++++------------ src/nvim/eval/typval.c | 20 ++++++++-------- src/nvim/eval/userfunc.c | 8 +++---- src/nvim/eval/vars.c | 62 ++++++++++++++++++++++++++++++++++-------------- 4 files changed, 73 insertions(+), 47 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 6a677dd675..91ab9f14ff 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -362,15 +362,15 @@ static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) rettv->vval.v_number = 1; // Default: failed. if (argvars[0].v_type == VAR_LIST) { list_T *const l = argvars[0].vval.v_list; - if (!var_check_lock(tv_list_locked(l), N_("add() argument"), - TV_TRANSLATE)) { + if (!value_check_lock(tv_list_locked(l), N_("add() argument"), + TV_TRANSLATE)) { tv_list_append_tv(l, &argvars[1]); tv_copy(&argvars[0], rettv); } } else if (argvars[0].v_type == VAR_BLOB) { blob_T *const b = argvars[0].vval.v_blob; if (b != NULL - && !var_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) { + && !value_check_lock(b->bv_lock, N_("add() argument"), TV_TRANSLATE)) { bool error = false; const varnumber_T n = tv_get_number_chk(&argvars[1], &error); @@ -1896,9 +1896,9 @@ static void f_flatten(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) list_T *list = argvars[0].vval.v_list; if (list != NULL - && !var_check_lock(tv_list_locked(list), - N_("flatten() argument"), - TV_TRANSLATE) + && !value_check_lock(tv_list_locked(list), + N_("flatten() argument"), + TV_TRANSLATE) && tv_list_flatten(list, maxdepth) == OK) { tv_copy(&argvars[0], rettv); } @@ -1915,7 +1915,7 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) list_T *const l1 = argvars[0].vval.v_list; list_T *const l2 = argvars[1].vval.v_list; - if (!var_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { + if (!value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) { listitem_T *item; if (argvars[2].v_type != VAR_UNKNOWN) { long before = (long)tv_get_number_chk(&argvars[2], &error); @@ -1944,13 +1944,13 @@ static void f_extend(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) dict_T *const d1 = argvars[0].vval.v_dict; dict_T *const d2 = argvars[1].vval.v_dict; if (d1 == NULL) { - const bool locked = var_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); + const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE); (void)locked; assert(locked == true); } else if (d2 == NULL) { // Do nothing tv_copy(&argvars[0], rettv); - } else if (!var_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { + } else if (!value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) { const char *action = "force"; // Check the third argument. if (argvars[2].v_type != VAR_UNKNOWN) { @@ -3556,8 +3556,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) blob_T *const b = argvars[0].vval.v_blob; if (b == NULL - || var_check_lock(b->bv_lock, N_("insert() argument"), - TV_TRANSLATE)) { + || value_check_lock(b->bv_lock, N_("insert() argument"), + TV_TRANSLATE)) { return; } @@ -3592,8 +3592,8 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) tv_copy(&argvars[0], rettv); } else if (argvars[0].v_type != VAR_LIST) { semsg(_(e_listblobarg), "insert()"); - } else if (!var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - N_("insert() argument"), TV_TRANSLATE)) { + } else if (!value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), + N_("insert() argument"), TV_TRANSLATE)) { long before = 0; if (argvars[2].v_type != VAR_UNKNOWN) { before = tv_get_number_chk(&argvars[2], &error); @@ -5985,8 +5985,8 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) semsg(_(e_listblobarg), "reverse()"); } else { list_T *const l = argvars[0].vval.v_list; - if (!var_check_lock(tv_list_locked(l), N_("reverse() argument"), - TV_TRANSLATE)) { + if (!value_check_lock(tv_list_locked(l), N_("reverse() argument"), + TV_TRANSLATE)) { tv_list_reverse(l); tv_list_set_ret(rettv, l); } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 5a356813f0..b48aa1372e 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -900,8 +900,8 @@ void tv_list_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) list_T *l; bool error = false; - if (var_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), - arg_errmsg, TV_TRANSLATE)) { + if (value_check_lock(tv_list_locked((l = argvars[0].vval.v_list)), + arg_errmsg, TV_TRANSLATE)) { return; } @@ -1156,7 +1156,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) semsg(_(e_listarg), sort ? "sort()" : "uniq()"); } else { list_T *const l = argvars[0].vval.v_list; - if (var_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { + if (value_check_lock(tv_list_locked(l), arg_errmsg, TV_TRANSLATE)) { goto theend; } tv_list_set_ret(rettv, l); @@ -2494,7 +2494,7 @@ void tv_dict_extend(dict_T *const d1, dict_T *const d2, const char *const action } else if (*action == 'f' && di2 != di1) { typval_T oldtv; - if (var_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) + if (value_check_lock(di1->di_tv.v_lock, arg_errmsg, arg_errmsg_len) || var_check_ro(di1->di_flags, arg_errmsg, arg_errmsg_len)) { break; } @@ -2710,7 +2710,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) { blob_T *const b = argvars[0].vval.v_blob; - if (b != NULL && var_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) { + if (b != NULL && value_check_lock(b->bv_lock, arg_errmsg, TV_TRANSLATE)) { return; } @@ -2902,7 +2902,7 @@ void tv_dict_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) if (argvars[2].v_type != VAR_UNKNOWN) { semsg(_(e_toomanyarg), "remove()"); } else if ((d = argvars[0].vval.v_dict) != NULL - && !var_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { + && !value_check_lock(d->dv_lock, arg_errmsg, TV_TRANSLATE)) { const char *key = tv_get_string_chk(&argvars[1]); if (key != NULL) { dictitem_T *di = tv_dict_find(d, key, -1); @@ -3460,12 +3460,12 @@ bool tv_check_lock(const typval_T *tv, const char *name, size_t name_len) default: break; } - return var_check_lock(tv->v_lock, name, name_len) - || (lock != VAR_UNLOCKED && var_check_lock(lock, name, name_len)); + return value_check_lock(tv->v_lock, name, name_len) + || (lock != VAR_UNLOCKED && value_check_lock(lock, name, name_len)); } -/// @return true if variable "name" is locked (immutable) -bool var_check_lock(VarLockStatus lock, const char *name, size_t name_len) +/// @return true if variable "name" has a locked (immutable) value +bool value_check_lock(VarLockStatus lock, const char *name, size_t name_len) { const char *error_message = NULL; switch (lock) { diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 1d27826e7a..74d9e30a58 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -2551,13 +2551,13 @@ void ex_function(exarg_T *eap) goto erret; } if (fudi.fd_di == NULL) { - if (var_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, - TV_CSTRING)) { + if (value_check_lock(fudi.fd_dict->dv_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't add a function to a locked dictionary goto erret; } - } else if (var_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, - TV_CSTRING)) { + } else if (value_check_lock(fudi.fd_di->di_tv.v_lock, (const char *)eap->arg, + TV_CSTRING)) { // Can't change an existing function if it is locked goto erret; } diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c index 75af99fbd5..3e593151fc 100644 --- a/src/nvim/eval/vars.c +++ b/src/nvim/eval/vars.c @@ -877,13 +877,13 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ } else if ((lp->ll_list != NULL // ll_list is not NULL when lvalue is not in a list, NULL lists // yield E689. - && var_check_lock(tv_list_locked(lp->ll_list), - lp->ll_name, - lp->ll_name_len)) + && value_check_lock(tv_list_locked(lp->ll_list), + lp->ll_name, + lp->ll_name_len)) || (lp->ll_dict != NULL - && var_check_lock(lp->ll_dict->dv_lock, - lp->ll_name, - lp->ll_name_len))) { + && value_check_lock(lp->ll_dict->dv_lock, + lp->ll_name, + lp->ll_name_len))) { return FAIL; } else if (lp->ll_range) { assert(lp->ll_list != NULL); @@ -892,9 +892,9 @@ static int do_unlet_var(lval_T *lp, char *name_end, exarg_T *eap, int deep FUNC_ listitem_T *last_li = first_li; for (;;) { listitem_T *const li = TV_LIST_ITEM_NEXT(lp->ll_list, lp->ll_li); - if (var_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, - lp->ll_name, - lp->ll_name_len)) { + if (value_check_lock(TV_LIST_ITEM_TV(lp->ll_li)->v_lock, + lp->ll_name, + lp->ll_name_len)) { return false; } lp->ll_li = li; @@ -976,11 +976,11 @@ int do_unlet(const char *const name, const size_t name_len, const bool forceit) dictitem_T *const di = TV_DICT_HI2DI(hi); if (var_check_fixed(di->di_flags, name, TV_CSTRING) || var_check_ro(di->di_flags, name, TV_CSTRING) - || var_check_lock(d->dv_lock, name, TV_CSTRING)) { + || value_check_lock(d->dv_lock, name, TV_CSTRING)) { return FAIL; } - if (var_check_lock(d->dv_lock, name, TV_CSTRING)) { + if (value_check_lock(d->dv_lock, name, TV_CSTRING)) { return FAIL; } @@ -1023,10 +1023,6 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap bool lock = eap->cmdidx == CMD_lockvar; int ret = OK; - if (deep == 0) { // Nothing to do. - return OK; - } - if (lp->ll_tv == NULL) { if (*lp->ll_name == '$') { semsg(_(e_lock_unlock), lp->ll_name); @@ -1050,9 +1046,13 @@ static int do_lock_var(lval_T *lp, char *name_end FUNC_ATTR_UNUSED, exarg_T *eap } else { di->di_flags &= (uint8_t)(~DI_FLAGS_LOCK); } - tv_item_lock(&di->di_tv, deep, lock, false); + if (deep != 0) { + tv_item_lock(&di->di_tv, deep, lock, false); + } } } + } else if (deep == 0) { + // nothing to do } else if (lp->ll_range) { listitem_T *li = lp->ll_li; @@ -1282,12 +1282,18 @@ void set_var_const(const char *name, const size_t name_len, typval_T *const tv, return; } - // existing variable, need to clear the value + // Check in this order for backwards compatibility: + // - Whether the variable is read-only + // - Whether the variable value is locked + // - Whether the variable is locked if (var_check_ro(v->di_flags, name, name_len) - || var_check_lock(v->di_tv.v_lock, name, name_len)) { + || value_check_lock(v->di_tv.v_lock, name, name_len) + || var_check_lock(v->di_flags, name, name_len)) { return; } + // existing variable, need to clear the value + // Handle setting internal v: variables separately where needed to // prevent changing the type. if (is_vimvarht(ht)) { @@ -1418,6 +1424,26 @@ bool var_check_ro(const int flags, const char *name, size_t name_len) return true; } +/// Return true if di_flags "flags" indicates variable "name" is locked. +/// Also give an error message. +bool var_check_lock(const int flags, const char *name, size_t name_len) +{ + if (!(flags & DI_FLAGS_LOCK)) { + return false; + } + + if (name_len == TV_TRANSLATE) { + name = _(name); + name_len = strlen(name); + } else if (name_len == TV_CSTRING) { + name_len = strlen(name); + } + + semsg(_("E1122: Variable is locked: %*s"), (int)name_len, name); + + return true; +} + /// Check whether variable is fixed (DI_FLAGS_FIX) /// /// Also gives an error message. -- cgit From 4c531714ff24d82bf1a85decf0e0c63c5785e686 Mon Sep 17 00:00:00 2001 From: dundargoc <33953936+dundargoc@users.noreply.github.com> Date: Thu, 19 Jan 2023 15:25:56 +0100 Subject: refactor: replace char_u with char 25 (#21838) refactor: replace char_u with char Work on https://github.com/neovim/neovim/issues/459 --- src/nvim/eval/funcs.c | 16 ++++++++-------- src/nvim/eval/typval.c | 4 ++-- src/nvim/eval/typval_encode.c.h | 4 ++-- src/nvim/eval/userfunc.c | 28 ++++++++++++++-------------- 4 files changed, 26 insertions(+), 26 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 91ab9f14ff..1b34777a46 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -557,7 +557,7 @@ static void f_call(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) func = partial_name(partial); } else if (nlua_is_table_from_lua(&argvars[0])) { // TODO(tjdevries): UnifiedCallback - func = (char *)nlua_register_table_as_callable(&argvars[0]); + func = nlua_register_table_as_callable(&argvars[0]); owned = true; } else { func = (char *)tv_get_string(&argvars[0]); @@ -1419,7 +1419,7 @@ static void f_diff_hlID(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) hlID = HLF_CHD; // Changed line. } } - rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (int)(hlID + 1); + rettv->vval.v_number = hlID == (hlf_T)0 ? 0 : (hlID + 1); } /// "empty({expr})" function @@ -1695,7 +1695,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) #ifdef BACKSLASH_IN_FILENAME if (path != NULL) { - slash_adjust((char_u *)path); + slash_adjust(path); } #endif @@ -1749,7 +1749,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) int options = WILD_SILENT|WILD_USE_NL|WILD_LIST_NOTFOUND; bool error = false; #ifdef BACKSLASH_IN_FILENAME - char_u *p_csl_save = p_csl; + char *p_csl_save = p_csl; // avoid using 'completeslash' here p_csl = empty_option; @@ -1770,7 +1770,7 @@ static void f_expand(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } size_t len; char *errormsg = NULL; - char *result = (char *)eval_vars((char *)s, (char_u *)s, &len, NULL, &errormsg, NULL, false); + char *result = eval_vars((char *)s, s, &len, NULL, &errormsg, NULL, false); if (p_verbose == 0) { emsg_off--; } else if (errormsg != NULL) { @@ -2022,7 +2022,7 @@ static void f_filewritable(typval_T *argvars, typval_T *rettv, EvalFuncData fptr static void findfilendir(typval_T *argvars, typval_T *rettv, int find_what) { char *fresult = NULL; - char *path = *curbuf->b_p_path == NUL ? (char *)p_path : curbuf->b_p_path; + char *path = *curbuf->b_p_path == NUL ? p_path : curbuf->b_p_path; int count = 1; bool first = true; bool error = false; @@ -7827,7 +7827,7 @@ static void f_strftime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) vimconv_T conv; conv.vc_type = CONV_NONE; - char *enc = (char *)enc_locale(); + char *enc = enc_locale(); convert_setup(&conv, p_enc, enc); if (conv.vc_type != CONV_NONE) { p = string_convert(&conv, p, NULL); @@ -8097,7 +8097,7 @@ static void f_strptime(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) vimconv_T conv = { .vc_type = CONV_NONE, }; - char *enc = (char *)enc_locale(); + char *enc = enc_locale(); convert_setup(&conv, p_enc, enc); if (conv.vc_type != CONV_NONE) { fmt = string_convert(&conv, fmt, NULL); diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index b48aa1372e..9ffc4d4696 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -3007,7 +3007,7 @@ void tv_blob_copy(typval_T *const from, typval_T *const to) (tv)->v_lock = VAR_UNLOCKED; \ } while (0) -static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun) +static inline int _nothing_conv_func_start(typval_T *const tv, char *const fun) FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ARG(1) { tv->v_lock = VAR_UNLOCKED; @@ -3019,7 +3019,7 @@ static inline int _nothing_conv_func_start(typval_T *const tv, char_u *const fun return OK; } } else { - func_unref((char *)fun); + func_unref(fun); if ((const char *)fun != tv_empty_string) { xfree(fun); } diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h index 6c931d3f88..6d29286a58 100644 --- a/src/nvim/eval/typval_encode.c.h +++ b/src/nvim/eval/typval_encode.c.h @@ -339,7 +339,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( tv_blob_len(tv->vval.v_blob)); break; case VAR_FUNC: - TYPVAL_ENCODE_CONV_FUNC_START(tv, (char_u *)tv->vval.v_string); + TYPVAL_ENCODE_CONV_FUNC_START(tv, tv->vval.v_string); TYPVAL_ENCODE_CONV_FUNC_BEFORE_ARGS(tv, 0); TYPVAL_ENCODE_CONV_FUNC_BEFORE_SELF(tv, -1); TYPVAL_ENCODE_CONV_FUNC_END(tv); @@ -347,7 +347,7 @@ static int _TYPVAL_ENCODE_CONVERT_ONE_VALUE( case VAR_PARTIAL: { partial_T *const pt = tv->vval.v_partial; (void)pt; - TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : (char_u *)partial_name(pt))); // -V547 + TYPVAL_ENCODE_CONV_FUNC_START(tv, (pt == NULL ? NULL : partial_name(pt))); // -V547 _mp_push(*mpstack, ((MPConvStackVal) { // -V779 .type = kMPConvPartial, .tv = tv, diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c index 74d9e30a58..22c5b1954d 100644 --- a/src/nvim/eval/userfunc.c +++ b/src/nvim/eval/userfunc.c @@ -582,9 +582,9 @@ static char *fname_trans_sid(const char *const name, char *const fname_buf, char /// Find a function by name, return pointer to it in ufuncs. /// /// @return NULL for unknown function. -ufunc_T *find_func(const char_u *name) +ufunc_T *find_func(const char *name) { - hashitem_T *hi = hash_find(&func_hashtab, (char *)name); + hashitem_T *hi = hash_find(&func_hashtab, name); if (!HASHITEM_EMPTY(hi)) { return HI2UF(hi); } @@ -1580,7 +1580,7 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t } else if (fp != NULL || !builtin_function((const char *)rfname, -1)) { // User defined function. if (fp == NULL) { - fp = find_func((char_u *)rfname); + fp = find_func(rfname); } // Trigger FuncUndefined event, may load the function. @@ -1588,13 +1588,13 @@ int call_func(const char *funcname, int len, typval_T *rettv, int argcount_in, t && apply_autocmds(EVENT_FUNCUNDEFINED, rfname, rfname, true, NULL) && !aborting()) { // executed an autocommand, search for the function again - fp = find_func((char_u *)rfname); + fp = find_func(rfname); } // Try loading a package. if (fp == NULL && script_autoload((const char *)rfname, strlen(rfname), true) && !aborting()) { // Loaded a package, search for the function again. - fp = find_func((char_u *)rfname); + fp = find_func(rfname); } if (fp != NULL && (fp->uf_flags & FC_DELETED)) { @@ -2133,7 +2133,7 @@ void ex_function(exarg_T *eap) *p = NUL; } if (!eap->skip && !got_int) { - fp = find_func((char_u *)name); + fp = find_func(name); if (fp != NULL) { list_func_head(fp, !eap->forceit, eap->forceit); for (int j = 0; j < fp->uf_lines.ga_len && !got_int; j++) { @@ -2256,7 +2256,7 @@ void ex_function(exarg_T *eap) if (!eap->skip && !eap->forceit) { if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL) { emsg(_(e_funcdict)); - } else if (name != NULL && find_func((char_u *)name) != NULL) { + } else if (name != NULL && find_func(name) != NULL) { emsg_funcname(e_funcexts, name); } } @@ -2510,7 +2510,7 @@ void ex_function(exarg_T *eap) goto erret; } - fp = find_func((char_u *)name); + fp = find_func(name); if (fp != NULL) { // Function can be replaced with "function!" and when sourcing the // same script again, but only once. @@ -2690,7 +2690,7 @@ bool translated_function_exists(const char *name) if (builtin_function(name, -1)) { return find_internal_func((char *)name) != NULL; } - return find_func((const char_u *)name) != NULL; + return find_func(name) != NULL; } /// Check whether function with the given name exists @@ -2800,7 +2800,7 @@ void ex_delfunction(exarg_T *eap) return; } if (!eap->skip) { - fp = find_func((char_u *)name); + fp = find_func(name); } xfree(name); @@ -2857,7 +2857,7 @@ void func_unref(char *name) return; } - fp = find_func((char_u *)name); + fp = find_func(name); if (fp == NULL && isdigit((uint8_t)(*name))) { #ifdef EXITFREE if (!entered_free_all_mem) { @@ -2898,7 +2898,7 @@ void func_ref(char *name) if (name == NULL || !func_name_refcount(name)) { return; } - fp = find_func((char_u *)name); + fp = find_func(name); if (fp != NULL) { (fp->uf_refcount)++; } else if (isdigit((uint8_t)(*name))) { @@ -3305,7 +3305,7 @@ void make_partial(dict_T *const selfdict, typval_T *const rettv) : rettv->vval.v_partial->pt_name; // Translate "s:func" to the stored function name. fname = fname_trans_sid(fname, fname_buf, &tofree, &error); - fp = find_func((char_u *)fname); + fp = find_func(fname); xfree(tofree); } @@ -3651,7 +3651,7 @@ bool set_ref_in_func(char *name, ufunc_T *fp_in, int copyID) if (fp_in == NULL) { fname = fname_trans_sid(name, fname_buf, &tofree, &error); - fp = find_func((char_u *)fname); + fp = find_func(fname); } if (fp != NULL) { for (fc = fp->uf_scoped; fc != NULL; fc = fc->func->uf_scoped) { -- cgit From e86d2734a93e159d44df8132dee6b994e5922d18 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Sat, 21 Jan 2023 09:24:09 +0800 Subject: refactor: use uint8_t for blobs and ga_append() (#21916) A blob is used as a sequence of bytes and usually accessed individually, not as as a NUL-terminuated string, so uint8_t should be better. Not sure about ga_append(), but using uint8_t leads to fewer casts. --- src/nvim/eval/encode.c | 2 +- src/nvim/eval/executor.c | 2 +- src/nvim/eval/funcs.c | 8 ++++---- src/nvim/eval/typval.c | 7 +++---- src/nvim/eval/typval.h | 12 ++++++------ 5 files changed, 15 insertions(+), 16 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c index 03d4862550..c2f1eae8af 100644 --- a/src/nvim/eval/encode.c +++ b/src/nvim/eval/encode.c @@ -309,7 +309,7 @@ int encode_read_from_list(ListReaderState *const state, char *const buf, const s if (buf_[i_] == '\'') { \ ga_append(gap, '\''); \ } \ - ga_append(gap, buf_[i_]); \ + ga_append(gap, (uint8_t)buf_[i_]); \ } \ ga_append(gap, '\''); \ } \ diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c index 831c468288..9caea2fef1 100644 --- a/src/nvim/eval/executor.c +++ b/src/nvim/eval/executor.c @@ -51,7 +51,7 @@ int eexe_mod_op(typval_T *const tv1, const typval_T *const tv2, const char *cons blob_T *const b1 = tv1->vval.v_blob; blob_T *const b2 = tv2->vval.v_blob; for (int i = 0; i < tv_blob_len(b2); i++) { - ga_append(&b1->bv_ga, (char)tv_blob_get(b2, i)); + ga_append(&b1->bv_ga, tv_blob_get(b2, i)); } } return OK; diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 1b34777a46..4692035dd9 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -375,7 +375,7 @@ static void f_add(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const varnumber_T n = tv_get_number_chk(&argvars[1], &error); if (!error) { - ga_append(&b->bv_ga, (char)n); + ga_append(&b->bv_ga, (uint8_t)n); tv_copy(&argvars[0], rettv); } } @@ -3584,9 +3584,9 @@ static void f_insert(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) } ga_grow(&b->bv_ga, 1); - char_u *const p = (char_u *)b->bv_ga.ga_data; + uint8_t *const p = (uint8_t *)b->bv_ga.ga_data; memmove(p + before + 1, p + before, (size_t)(len - before)); - *(p + before) = (char_u)val; + *(p + before) = (uint8_t)val; b->bv_ga.ga_len++; tv_copy(&argvars[0], rettv); @@ -5976,7 +5976,7 @@ static void f_reverse(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) const int len = tv_blob_len(b); for (int i = 0; i < len / 2; i++) { - const char_u tmp = tv_blob_get(b, i); + const uint8_t tmp = tv_blob_get(b, i); tv_blob_set(b, i, tv_blob_get(b, len - i - 1)); tv_blob_set(b, len - i - 1, tmp); } diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index 9ffc4d4696..05b4737206 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -2730,7 +2730,7 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) } if (argvars[2].v_type == VAR_UNKNOWN) { // Remove one item, return its value. - char_u *const p = (char_u *)b->bv_ga.ga_data; + uint8_t *const p = (uint8_t *)b->bv_ga.ga_data; rettv->vval.v_number = (varnumber_T)(*(p + idx)); memmove(p + idx, p + idx + 1, (size_t)(len - idx - 1)); b->bv_ga.ga_len--; @@ -2752,9 +2752,8 @@ void tv_blob_remove(typval_T *argvars, typval_T *rettv, const char *arg_errmsg) blob->bv_ga.ga_len = (int)(end - idx + 1); ga_grow(&blob->bv_ga, (int)(end - idx + 1)); - char_u *const p = (char_u *)b->bv_ga.ga_data; - memmove((char_u *)blob->bv_ga.ga_data, p + idx, - (size_t)(end - idx + 1)); + uint8_t *const p = (uint8_t *)b->bv_ga.ga_data; + memmove(blob->bv_ga.ga_data, p + idx, (size_t)(end - idx + 1)); tv_blob_set_ret(rettv, blob); if (len - end - 1 > 0) { diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h index 1ee3b5bf69..3f59cd3547 100644 --- a/src/nvim/eval/typval.h +++ b/src/nvim/eval/typval.h @@ -358,7 +358,7 @@ static inline int tv_blob_len(const blob_T *const b) return b->bv_ga.ga_len; } -static inline char_u tv_blob_get(const blob_T *b, int idx) +static inline uint8_t tv_blob_get(const blob_T *b, int idx) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT; /// Get the byte at index `idx` in the blob. @@ -367,12 +367,12 @@ static inline char_u tv_blob_get(const blob_T *b, int idx) /// @param[in] idx Index in a blob. Must be valid. /// /// @return Byte value at the given index. -static inline char_u tv_blob_get(const blob_T *const b, int idx) +static inline uint8_t tv_blob_get(const blob_T *const b, int idx) { - return ((char_u *)b->bv_ga.ga_data)[idx]; + return ((uint8_t *)b->bv_ga.ga_data)[idx]; } -static inline void tv_blob_set(blob_T *b, int idx, char_u c) +static inline void tv_blob_set(blob_T *b, int idx, uint8_t c) REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL; /// Store the byte `c` at index `idx` in the blob. @@ -380,9 +380,9 @@ static inline void tv_blob_set(blob_T *b, int idx, char_u c) /// @param[in] b Blob to index. Cannot be NULL. /// @param[in] idx Index in a blob. Must be valid. /// @param[in] c Value to store. -static inline void tv_blob_set(blob_T *const b, int idx, char_u c) +static inline void tv_blob_set(blob_T *const b, int idx, uint8_t c) { - ((char_u *)b->bv_ga.ga_data)[idx] = c; + ((uint8_t *)b->bv_ga.ga_data)[idx] = c; } /// Initialize VimL object -- cgit From 0f633ff494b5b39b5ca410e75ea3357c79657bcd Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Mon, 23 Jan 2023 07:36:01 +0800 Subject: vim-patch:9.0.1233: search() loops forever if "skip" is TRUE for all matches (#21956) Problem: search() loops forever if "skip" is TRUE for all matches. Solution: Keep the position of the first match. https://github.com/vim/vim/commit/3d79f0a4309995956bd8889940cca22f7a15881d Co-authored-by: Bram Moolenaar --- src/nvim/eval/funcs.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index 4692035dd9..c64aad659f 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -6239,7 +6239,9 @@ static int search_cmn(typval_T *argvars, pos_T *match_pos, int *flagsp) // didn't find it or no skip argument break; } - firstpos = pos; + if (firstpos.lnum == 0) { + firstpos = pos; + } // If the skip expression matches, ignore this match. { -- cgit From f08051c2e61f63b2088a42d641393253b8ca1ca1 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Mon, 23 Jan 2023 16:33:45 +0000 Subject: feat!: make iconv a non-optional dep --- src/nvim/eval/funcs.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'src/nvim/eval') diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index c64aad659f..5a31288ecd 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -3082,9 +3082,7 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr) "fork", #endif "gettext", -#if defined(HAVE_ICONV) "iconv", -#endif "insert_expand", "jumplist", "keymap", -- cgit