aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c93
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;