diff options
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r-- | src/nvim/eval.c | 93 |
1 files changed, 61 insertions, 32 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 498795dc38..34990a62e0 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -76,7 +76,7 @@ #include "nvim/tag.h" #include "nvim/tempfile.h" #include "nvim/term.h" -#include "nvim/ui.h" +#include "nvim/mouse.h" #include "nvim/undo.h" #include "nvim/version.h" #include "nvim/window.h" @@ -90,6 +90,7 @@ #include "nvim/api/vim.h" #include "nvim/os/dl.h" #include "nvim/os/event.h" +#include "nvim/os/input.h" #define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */ @@ -178,6 +179,8 @@ static char *e_nofunc = N_("E130: Unknown function: %s"); static char *e_illvar = N_("E461: Illegal variable name: %s"); static char *e_float_as_string = N_("E806: using Float as a String"); +static char_u * const empty_string = (char_u *)""; + static dictitem_T globvars_var; /* variable used for g: */ #define globvarht globvardict.dv_hashtab @@ -2272,6 +2275,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch if (lp->ll_li->li_next == NULL) { /* Need to add an empty item. */ list_append_number(lp->ll_list, 0); + assert(lp->ll_li->li_next); } lp->ll_li = lp->ll_li->li_next; ++lp->ll_n1; @@ -4123,7 +4127,7 @@ eval7 ( * get_func_tv, but it's needed in handle_subscript() to parse * what follows. So set it here. */ if (rettv->v_type == VAR_UNKNOWN && !evaluate && **arg == '(') { - rettv->vval.v_string = (char_u *)""; + rettv->vval.v_string = empty_string; rettv->v_type = VAR_FUNC; } @@ -5733,7 +5737,9 @@ dict_free ( dictitem_T *dictitem_alloc(char_u *key) FUNC_ATTR_NONNULL_RET { dictitem_T *di = xmalloc(sizeof(dictitem_T) + STRLEN(key)); +#ifndef __clang_analyzer__ STRCPY(di->di_key, key); +#endif di->di_flags = 0; return di; } @@ -8409,7 +8415,7 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv) } vim_feedkeys(cstr_as_string((char *)keys), - cstr_as_string((char *)flags)); + cstr_as_string((char *)flags), true); } } @@ -10268,12 +10274,6 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog) rettv->v_type = VAR_STRING; rettv->vval.v_string = NULL; -#ifdef NO_CONSOLE_INPUT - /* While starting up, there is no place to enter text. */ - if (no_console_input()) - return; -#endif - cmd_silent = FALSE; /* Want to see the prompt. */ if (prompt != NULL) { /* Only the part of the message after the last NL is considered as @@ -10368,11 +10368,6 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv) int selected; int mouse_used; -#ifdef NO_CONSOLE_INPUT - /* While starting up, there is no place to enter text. */ - if (no_console_input()) - return; -#endif if (argvars[0].v_type != VAR_LIST || argvars[0].vval.v_list == NULL) { EMSG2(_(e_listarg), "inputlist()"); return; @@ -12518,6 +12513,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv) { rettv->v_type = VAR_NUMBER; rettv->vval.v_number = 0; + const int l_provider_call_nesting = provider_call_nesting; if (check_restricted() || check_secure()) { return; @@ -12545,7 +12541,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv) int save_autocmd_fname_full, save_autocmd_bufnr; void *save_funccalp; - if (provider_call_nesting) { + if (l_provider_call_nesting) { // If this is called from a provider function, restore the scope // information of the caller. save_current_SID = current_SID; @@ -12574,7 +12570,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv) args, &err); - if (provider_call_nesting) { + if (l_provider_call_nesting) { current_SID = save_current_SID; sourcing_name = save_sourcing_name; sourcing_lnum = save_sourcing_lnum; @@ -13542,13 +13538,12 @@ static bool item_compare_numeric; static char_u *item_compare_func; static dict_T *item_compare_selfdict; static int item_compare_func_err; -static bool item_compare_keep_zero; #define ITEM_COMPARE_FAIL 999 /* * Compare functions for f_sort() and f_uniq() below. */ -static int item_compare(const void *s1, const void *s2) +static int item_compare(const void *s1, const void *s2, bool keep_zero) { sortItem_T *si1, *si2; char_u *p1, *p2; @@ -13601,7 +13596,7 @@ static int item_compare(const void *s1, const void *s2) // When the result would be zero, compare the item indexes. Makes the // sort stable. - if (res == 0 && !item_compare_keep_zero) { + if (res == 0 && !keep_zero) { res = si1->idx > si2->idx ? 1 : -1; } @@ -13610,7 +13605,17 @@ static int item_compare(const void *s1, const void *s2) return res; } -static int item_compare2(const void *s1, const void *s2) +static int item_compare_keeping_zero(const void *s1, const void *s2) +{ + return item_compare(s1, s2, true); +} + +static int item_compare_not_keeping_zero(const void *s1, const void *s2) +{ + return item_compare(s1, s2, false); +} + +static int item_compare2(const void *s1, const void *s2, bool keep_zero) { sortItem_T *si1, *si2; int res; @@ -13647,13 +13652,23 @@ static int item_compare2(const void *s1, const void *s2) // When the result would be zero, compare the pointers themselves. Makes // the sort stable. - if (res == 0 && !item_compare_keep_zero) { + if (res == 0 && !keep_zero) { res = si1->idx > si2->idx ? 1 : -1; } return res; } +static int item_compare2_keeping_zero(const void *s1, const void *s2) +{ + return item_compare2(s1, s2, true); +} + +static int item_compare2_not_keeping_zero(const void *s1, const void *s2) +{ + return item_compare2(s1, s2, false); +} + /* * "sort({list})" function */ @@ -13734,15 +13749,16 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) } item_compare_func_err = FALSE; - item_compare_keep_zero = false; // Test the compare function. if (item_compare_func != NULL - && item_compare2(&ptrs[0], &ptrs[1]) == ITEM_COMPARE_FAIL) { + && item_compare2_not_keeping_zero(&ptrs[0], &ptrs[1]) + == ITEM_COMPARE_FAIL) { EMSG(_("E702: Sort compare function failed")); } else { // Sort the array with item pointers. qsort(ptrs, (size_t)len, sizeof (sortItem_T), - item_compare_func == NULL ? item_compare : item_compare2); + item_compare_func == NULL ? item_compare_not_keeping_zero : + item_compare2_not_keeping_zero); if (!item_compare_func_err) { // Clear the list and append the items in the sorted order. @@ -13761,8 +13777,8 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) // f_uniq(): ptrs will be a stack of items to remove. item_compare_func_err = FALSE; - item_compare_keep_zero = true; - item_compare_func_ptr = item_compare_func ? item_compare2 : item_compare; + item_compare_func_ptr = item_compare_func ? item_compare2_keeping_zero : + item_compare_keeping_zero; for (li = l->lv_first; li != NULL && li->li_next != NULL; li = li->li_next) { if (item_compare_func_ptr(&li, &li->li_next) == 0) { @@ -13776,6 +13792,7 @@ static void do_sort_uniq(typval_T *argvars, typval_T *rettv, bool sort) if (!item_compare_func_err) { while (--i >= 0) { + assert(ptrs[i].item->li_next); li = ptrs[i].item->li_next; ptrs[i].item->li_next = li->li_next; if (li->li_next != NULL) { @@ -14561,8 +14578,7 @@ static void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, if (res == NULL) { if (retlist) { // return an empty list when there's no output - rettv->v_type = VAR_LIST; - rettv->vval.v_list = list_alloc(); + rettv_list_alloc(rettv); } return; } @@ -16111,7 +16127,11 @@ void clear_tv(typval_T *varp) switch (varp->v_type) { case VAR_FUNC: func_unref(varp->vval.v_string); - /*FALLTHROUGH*/ + if (varp->vval.v_string != empty_string) { + free(varp->vval.v_string); + } + varp->vval.v_string = NULL; + break; case VAR_STRING: free(varp->vval.v_string); varp->vval.v_string = NULL; @@ -17251,7 +17271,7 @@ void ex_function(exarg_T *eap) msg_putchar(' '); msg_prt_line(FUNCLINE(fp, j), FALSE); out_flush(); /* show a line at a time */ - ui_breakcheck(); + os_breakcheck(); } if (!got_int) { msg_putchar('\n'); @@ -18250,6 +18270,7 @@ char_u *get_user_func_name(expand_T *xp, int idx) done = 0; hi = func_hashtab.ht_array; } + assert(hi); if (done < func_hashtab.ht_used) { if (done++ > 0) ++hi; @@ -18465,8 +18486,10 @@ call_user_func ( /* Set l:self to "selfdict". Use "name" to avoid a warning from * some compiler that checks the destination size. */ v = &fc->fixvar[fixvar_idx++].var; +#ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "self"); +#endif v->di_flags = DI_FLAGS_RO + DI_FLAGS_FIX; hash_add(&fc->l_vars.dv_hashtab, DI2HIKEY(v)); v->di_tv.v_type = VAR_DICT; @@ -18486,8 +18509,10 @@ call_user_func ( /* Use "name" to avoid a warning from some compiler that checks the * destination size. */ v = &fc->fixvar[fixvar_idx++].var; +#ifndef __clang_analyzer__ name = v->di_key; STRCPY(name, "000"); +#endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; hash_add(&fc->l_avars.dv_hashtab, DI2HIKEY(v)); v->di_tv.v_type = VAR_LIST; @@ -18774,7 +18799,9 @@ free_funccal ( */ static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr) { +#ifndef __clang_analyzer__ STRCPY(v->di_key, name); +#endif v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX; hash_add(&dp->dv_hashtab, DI2HIKEY(v)); v->di_tv.v_type = VAR_NUMBER; @@ -18864,8 +18891,10 @@ int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv) else { /* When undoing a return in order to make it pending, get the stored * return rettv. */ - if (reanimate) + if (reanimate) { + assert(current_funccal->rettv); rettv = current_funccal->rettv; + } if (rettv != NULL) { /* Store the value of the pending return. */ @@ -19267,7 +19296,7 @@ void ex_oldfiles(exarg_T *eap) msg_outtrans(get_tv_string(&li->li_tv)); msg_putchar('\n'); out_flush(); /* output one line at a time */ - ui_breakcheck(); + os_breakcheck(); } /* Assume "got_int" was set to truncate the listing. */ got_int = FALSE; |