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.c1054
1 files changed, 330 insertions, 724 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 5911a93099..2dbaa2f8ac 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1,24 +1,18 @@
// 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.c: Expression evaluation.
- */
+// eval.c: Expression evaluation.
#include <math.h>
#include <stdlib.h>
-#include "auto/config.h"
-
-#ifdef HAVE_LOCALE_H
-# include <locale.h>
-#endif
-
#include "nvim/ascii.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/change.h"
#include "nvim/channel.h"
#include "nvim/charset.h"
+#include "nvim/cmdhist.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
@@ -28,23 +22,29 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h"
#include "nvim/eval/vars.h"
+#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
+#include "nvim/ex_docmd.h"
+#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/ex_session.h"
-#include "nvim/fileio.h"
#include "nvim/getchar.h"
#include "nvim/highlight_group.h"
+#include "nvim/locale.h"
#include "nvim/lua/executor.h"
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/os/shell.h"
#include "nvim/path.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/sign.h"
@@ -71,19 +71,15 @@ static char * const namespace_char = "abglstvw";
/// Variable used for g:
static ScopeDictDictItem globvars_var;
-/*
- * Old Vim variables such as "v:version" are also available without the "v:".
- * Also in functions. We need a special hashtable for them.
- */
+/// Old Vim variables such as "v:version" are also available without the "v:".
+/// Also in functions. We need a special hashtable for them.
static hashtab_T compat_hashtab;
/// Used for checking if local variables or arguments used in a lambda.
bool *eval_lavars_used = NULL;
-/*
- * Array to hold the hashtab with variables local to each sourced script.
- * Each item holds a variable (nameless) that points to the dict_T.
- */
+/// Array to hold the hashtab with variables local to each sourced script.
+/// Each item holds a variable (nameless) that points to the dict_T.
typedef struct {
ScopeDictDictItem sv_var;
dict_T sv_dict;
@@ -98,11 +94,9 @@ static int echo_attr = 0; // attributes used for ":echo"
// The names of packages that once were loaded are remembered.
static garray_T ga_loaded = { 0, 0, sizeof(char *), 4, NULL };
-/*
- * Info used by a ":for" loop.
- */
+/// Info used by a ":for" loop.
typedef struct {
- int fi_semicolon; // TRUE if ending in '; var]'
+ int fi_semicolon; // true if ending in '; var]'
int fi_varcount; // nr of variables in the list
listwatch_T fi_lw; // keep an eye on the item used.
list_T *fi_list; // list being used
@@ -356,8 +350,6 @@ void eval_init(void)
{
vimvars[VV_VERSION].vv_nr = VIM_VERSION_100;
- struct vimvar *p;
-
init_var_dict(&globvardict, &globvars_var, VAR_DEF_SCOPE);
init_var_dict(&vimvardict, &vimvars_var, VAR_SCOPE);
vimvardict.dv_lock = VAR_FIXED;
@@ -365,7 +357,7 @@ void eval_init(void)
func_init();
for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) {
- p = &vimvars[i];
+ struct vimvar *p = &vimvars[i];
assert(STRLEN(p->vv_name) <= VIMVAR_KEY_LEN);
STRCPY(p->vv_di.di_key, p->vv_name);
if (p->vv_flags & VV_RO) {
@@ -447,10 +439,8 @@ void eval_init(void)
#if defined(EXITFREE)
void eval_clear(void)
{
- struct vimvar *p;
-
for (size_t i = 0; i < ARRAY_SIZE(vimvars); i++) {
- p = &vimvars[i];
+ struct vimvar *p = &vimvars[i];
if (p->vv_di.di_tv.v_type == VAR_STRING) {
XFREE_CLEAR(p->vv_str);
} else if (p->vv_di.di_tv.v_type == VAR_LIST) {
@@ -473,13 +463,13 @@ void eval_clear(void)
// autoloaded script names
ga_clear_strings(&ga_loaded);
- /* Script-local variables. First clear all the variables and in a second
- * loop free the scriptvar_T, because a variable in one script might hold
- * a reference to the whole scope of another script. */
- for (int i = 1; i <= ga_scripts.ga_len; ++i) {
+ // Script-local variables. First clear all the variables and in a second
+ // loop free the scriptvar_T, because a variable in one script might hold
+ // a reference to the whole scope of another script.
+ for (int i = 1; i <= ga_scripts.ga_len; i++) {
vars_clear(&SCRIPT_VARS(i));
}
- for (int i = 1; i <= ga_scripts.ga_len; ++i) {
+ for (int i = 1; i <= ga_scripts.ga_len; i++) {
xfree(SCRIPT_SV(i));
}
ga_clear(&ga_scripts);
@@ -518,10 +508,6 @@ static char *redir_varname = NULL;
/// @return OK if successfully completed the setup. FAIL otherwise.
int var_redir_start(char *name, int append)
{
- int save_emsg;
- int err;
- typval_T tv;
-
// Catch a bad name early.
if (!eval_isnamec1(*name)) {
emsg(_(e_invarg));
@@ -553,10 +539,11 @@ int var_redir_start(char *name, int append)
return FAIL;
}
- /* check if we can write to the variable: set it to or append an empty
- * string */
- save_emsg = did_emsg;
- did_emsg = FALSE;
+ // check if we can write to the variable: set it to or append an empty
+ // string
+ int save_emsg = did_emsg;
+ did_emsg = false;
+ typval_T tv;
tv.v_type = VAR_STRING;
tv.vval.v_string = "";
if (append) {
@@ -565,7 +552,7 @@ int var_redir_start(char *name, int append)
set_var_lval(redir_lval, redir_endp, &tv, true, false, "=");
}
clear_lval(redir_lval);
- err = did_emsg;
+ int err = did_emsg;
did_emsg |= save_emsg;
if (err) {
redir_endp = NULL; // don't store a value, only cleanup
@@ -585,12 +572,11 @@ int var_redir_start(char *name, int append)
/// :redir END
void var_redir_str(char *value, int value_len)
{
- int len;
-
if (redir_lval == NULL) {
return;
}
+ int len;
if (value_len == -1) {
len = (int)STRLEN(value); // Append the entire string
} else {
@@ -606,12 +592,11 @@ void var_redir_str(char *value, int value_len)
/// Frees the allocated memory.
void var_redir_stop(void)
{
- typval_T tv;
-
if (redir_lval != NULL) {
// If there was no error: assign the text to the variable.
if (redir_endp != NULL) {
ga_append(&redir_ga, NUL); // Append the trailing NUL.
+ typval_T tv;
tv.v_type = VAR_STRING;
tv.vval.v_string = redir_ga.ga_data;
// Call get_lval() again, if it's inside a Dict or List it may
@@ -641,7 +626,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to,
set_vim_var_string(VV_CC_TO, enc_to, -1);
set_vim_var_string(VV_FNAME_IN, fname_from, -1);
set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
- if (eval_to_bool((char *)p_ccv, &err, NULL, false)) {
+ if (eval_to_bool(p_ccv, &err, NULL, false)) {
err = true;
}
set_vim_var_string(VV_CC_FROM, NULL, -1);
@@ -661,7 +646,7 @@ int eval_printexpr(const char *const fname, const char *const args)
set_vim_var_string(VV_FNAME_IN, fname, -1);
set_vim_var_string(VV_CMDARG, args, -1);
- if (eval_to_bool((char *)p_pexpr, &err, NULL, false)) {
+ if (eval_to_bool(p_pexpr, &err, NULL, false)) {
err = true;
}
set_vim_var_string(VV_FNAME_IN, NULL, -1);
@@ -681,7 +666,7 @@ void eval_diff(const char *const origfile, const char *const newfile, const char
set_vim_var_string(VV_FNAME_IN, origfile, -1);
set_vim_var_string(VV_FNAME_NEW, newfile, -1);
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
- (void)eval_to_bool((char *)p_dex, &err, NULL, false);
+ (void)eval_to_bool(p_dex, &err, NULL, false);
set_vim_var_string(VV_FNAME_IN, NULL, -1);
set_vim_var_string(VV_FNAME_NEW, NULL, -1);
set_vim_var_string(VV_FNAME_OUT, NULL, -1);
@@ -701,11 +686,11 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch
}
/// Top level evaluation function, returning a boolean.
-/// Sets "error" to TRUE if there was an error.
+/// Sets "error" to true if there was an error.
///
/// @param skip only parse, don't execute
///
-/// @return TRUE or FALSE.
+/// @return true or false.
int eval_to_bool(char *arg, bool *error, char **nextcmd, int skip)
{
typval_T tv;
@@ -905,7 +890,7 @@ char *eval_to_string(char *arg, char **nextcmd, bool convert)
/// Call eval_to_string() without using current local variables and using
/// textlock.
///
-/// @param use_sandbox when TRUE, use the sandbox.
+/// @param use_sandbox when true, use the sandbox.
char *eval_to_string_safe(char *arg, char **nextcmd, int use_sandbox)
{
char *retval;
@@ -935,7 +920,7 @@ varnumber_T eval_to_number(char *expr)
varnumber_T retval;
char *p = skipwhite(expr);
- ++emsg_off;
+ emsg_off++;
if (eval1(&p, &rettv, true) == FAIL) {
retval = -1;
@@ -943,7 +928,7 @@ varnumber_T eval_to_number(char *expr)
retval = tv_get_number_chk(&rettv, NULL);
tv_clear(&rettv);
}
- --emsg_off;
+ emsg_off--;
return retval;
}
@@ -1000,11 +985,9 @@ void prepare_vimvar(int idx, typval_T *save_tv)
/// When no longer defined, remove the variable from the v: hashtable.
void restore_vimvar(int idx, typval_T *save_tv)
{
- hashitem_T *hi;
-
vimvars[idx].vv_tv = *save_tv;
if (vimvars[idx].vv_type == VAR_UNKNOWN) {
- hi = hash_find(&vimvarht, (char *)vimvars[idx].vv_di.di_key);
+ hashitem_T *hi = hash_find(&vimvarht, (char *)vimvars[idx].vv_di.di_key);
if (HASHITEM_EMPTY(hi)) {
internal_error("restore_vimvar()");
} else {
@@ -1040,7 +1023,7 @@ list_T *eval_spell_expr(char *badword, char *expr)
vimvars[VV_VAL].vv_type = VAR_STRING;
vimvars[VV_VAL].vv_str = badword;
if (p_verbose == 0) {
- ++emsg_off;
+ emsg_off++;
}
if (eval1(&p, &rettv, true) == OK) {
@@ -1052,7 +1035,7 @@ list_T *eval_spell_expr(char *badword, char *expr)
}
if (p_verbose == 0) {
- --emsg_off;
+ emsg_off--;
}
restore_vimvar(VV_VAL, &save_val);
@@ -1134,12 +1117,11 @@ varnumber_T call_func_retnr(const char *func, int argc, typval_T *argv)
FUNC_ATTR_NONNULL_ALL
{
typval_T rettv;
- varnumber_T retval;
if (call_vim_function((char *)func, argc, argv, &rettv) == FAIL) {
return -1;
}
- retval = tv_get_number_chk(&rettv, NULL);
+ varnumber_T retval = tv_get_number_chk(&rettv, NULL);
tv_clear(&rettv);
return retval;
}
@@ -1191,42 +1173,6 @@ void *call_func_retlist(const char *func, int argc, typval_T *argv)
return rettv.vval.v_list;
}
-/// Prepare profiling for entering a child or something else that is not
-/// counted for the script/function itself.
-/// Should always be called in pair with prof_child_exit().
-///
-/// @param tm place to store waittime
-void prof_child_enter(proftime_T *tm)
-{
- funccall_T *fc = get_current_funccal();
-
- if (fc != NULL && fc->func->uf_profiling) {
- fc->prof_child = profile_start();
- }
-
- script_prof_save(tm);
-}
-
-/// Take care of time spent in a child.
-/// Should always be called after prof_child_enter().
-///
-/// @param tm where waittime was stored
-void prof_child_exit(proftime_T *tm)
-{
- funccall_T *fc = get_current_funccal();
-
- if (fc != NULL && fc->func->uf_profiling) {
- fc->prof_child = profile_end(fc->prof_child);
- // don't count waiting time
- fc->prof_child = profile_sub_wait(*tm, fc->prof_child);
- fc->func->uf_tm_children =
- profile_add(fc->func->uf_tm_children, fc->prof_child);
- fc->func->uf_tml_children =
- profile_add(fc->func->uf_tml_children, fc->prof_child);
- }
- script_prof_restore(tm);
-}
-
/// Evaluate 'foldexpr'. Returns the foldlevel, and any character preceding
/// it in "*cp". Doesn't give error messages.
int eval_foldexpr(char *arg, int *cp)
@@ -1235,11 +1181,11 @@ int eval_foldexpr(char *arg, int *cp)
varnumber_T retval;
int use_sandbox = was_set_insecurely(curwin, "foldexpr", OPT_LOCAL);
- ++emsg_off;
+ emsg_off++;
if (use_sandbox) {
- ++sandbox;
+ sandbox++;
}
- ++textlock;
+ textlock++;
*cp = NUL;
if (eval0(arg, &tv, NULL, true) == FAIL) {
retval = 0;
@@ -1260,11 +1206,11 @@ int eval_foldexpr(char *arg, int *cp)
}
tv_clear(&tv);
}
- --emsg_off;
+ emsg_off--;
if (use_sandbox) {
- --sandbox;
+ sandbox--;
}
- --textlock;
+ textlock--;
return (int)retval;
}
@@ -1298,16 +1244,11 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
const bool skip, const int flags, const int fne_flags)
FUNC_ATTR_NONNULL_ARG(1, 3)
{
- dictitem_T *v;
- typval_T var1;
- typval_T var2;
- int empty1 = FALSE;
- listitem_T *ni;
- hashtab_T *ht = NULL;
+ bool empty1 = false;
int quiet = flags & GLV_QUIET;
// Clear everything in "lp".
- memset(lp, 0, sizeof(lval_T));
+ CLEAR_POINTER(lp);
if (skip) {
// When skipping just find the end of the name.
@@ -1355,11 +1296,13 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
return p;
}
+ hashtab_T *ht = NULL;
+
// Only pass &ht when we would write to the variable, it prevents autoload
// as well.
- v = find_var(lp->ll_name, lp->ll_name_len,
- (flags & GLV_READ_ONLY) ? NULL : &ht,
- flags & GLV_NO_AUTOLOAD);
+ dictitem_T *v = find_var(lp->ll_name, lp->ll_name_len,
+ (flags & GLV_READ_ONLY) ? NULL : &ht,
+ flags & GLV_NO_AUTOLOAD);
if (v == NULL && !quiet) {
semsg(_("E121: Undefined variable: %.*s"),
(int)lp->ll_name_len, lp->ll_name);
@@ -1370,7 +1313,9 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
// Loop until no more [idx] or .key is following.
lp->ll_tv = &v->di_tv;
+ typval_T var1;
var1.v_type = VAR_UNKNOWN;
+ typval_T var2;
var2.v_type = VAR_UNKNOWN;
while (*p == '[' || (*p == '.' && lp->ll_tv->v_type == VAR_DICT)) {
if (!(lp->ll_tv->v_type == VAR_LIST && lp->ll_tv->vval.v_list != NULL)
@@ -1612,7 +1557,7 @@ char *get_lval(char *const name, typval_T *const rettv, lval_T *const lp, const
lp->ll_n2 = (long)tv_get_number(&var2); // Is number or string.
tv_clear(&var2);
if (lp->ll_n2 < 0) {
- ni = tv_list_find(lp->ll_list, (int)lp->ll_n2);
+ listitem_T *ni = tv_list_find(lp->ll_list, (int)lp->ll_n2);
if (ni == NULL) {
if (!quiet) {
semsg(_(e_listidx), (int64_t)lp->ll_n2);
@@ -1765,9 +1710,7 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
ll_n1++;
}
- /*
- * Assign the List values to the list items.
- */
+ // Assign the List values to the list items.
for (ri = tv_list_first(rettv->vval.v_list); ri != NULL;) {
if (op != NULL && *op != '=') {
eexe_mod_op(TV_LIST_ITEM_TV(lp->ll_li), TV_LIST_ITEM_TV(ri), op);
@@ -1864,7 +1807,7 @@ notify:
/// Evaluate the expression used in a ":for var in expr" command.
/// "arg" points to "var".
///
-/// @param[out] *errp set to TRUE for an error, FALSE otherwise;
+/// @param[out] *errp set to true for an error, false otherwise;
///
/// @return a pointer that holds the info. Null when there is an error.
void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
@@ -1888,7 +1831,7 @@ void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
}
if (skip) {
- ++emsg_skip;
+ emsg_skip++;
}
if (eval0(skipwhite(expr + 2), &tv, nextcmdp, !skip) == OK) {
*errp = false;
@@ -1930,7 +1873,7 @@ void *eval_for_line(const char *arg, bool *errp, char **nextcmdp, int skip)
}
}
if (skip) {
- --emsg_skip;
+ emsg_skip--;
}
return fi;
@@ -2009,7 +1952,7 @@ void free_for_info(void *fi_void)
void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
FUNC_ATTR_NONNULL_ALL
{
- int got_eq = FALSE;
+ bool got_eq = false;
int c;
char *p;
@@ -2035,7 +1978,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
if (c == '&') {
c = (uint8_t)xp->xp_pattern[1];
if (c == '&') {
- ++xp->xp_pattern;
+ xp->xp_pattern++;
xp->xp_context = cmdidx != CMD_let || got_eq
? EXPAND_EXPRESSION : EXPAND_NOTHING;
} else if (c != ' ') {
@@ -2048,7 +1991,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
// environment variable
xp->xp_context = EXPAND_ENV_VARS;
} else if (c == '=') {
- got_eq = TRUE;
+ got_eq = true;
xp->xp_context = EXPAND_EXPRESSION;
} else if (c == '#'
&& xp->xp_context == EXPAND_EXPRESSION) {
@@ -2073,7 +2016,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
xp->xp_context = EXPAND_NOTHING;
} else if (c == '|') {
if (xp->xp_pattern[1] == '|') {
- ++xp->xp_pattern;
+ xp->xp_pattern++;
xp->xp_context = EXPAND_EXPRESSION;
} else {
xp->xp_context = EXPAND_COMMANDS;
@@ -2099,7 +2042,7 @@ void set_context_for_expression(expand_T *xp, char *arg, cmdidx_T cmdidx)
|| cmdidx == CMD_echomsg)
&& xp->xp_context == EXPAND_EXPRESSION) {
for (;;) {
- char *const n = (char *)skiptowhite((char_u *)arg);
+ char *const n = skiptowhite(arg);
if (n == arg || ascii_iswhite_or_nul(*skipwhite(n))) {
break;
@@ -2123,11 +2066,9 @@ void del_menutrans_vars(void)
hash_unlock(&globvarht);
}
-/*
- * Local string buffer for the next two functions to store a variable name
- * with its prefix. Allocated in cat_prefix_varname(), freed later in
- * get_user_var_name().
- */
+/// Local string buffer for the next two functions to store a variable name
+/// with its prefix. Allocated in cat_prefix_varname(), freed later in
+/// get_user_var_name().
static char *varnamebuf = NULL;
static size_t varnamebuflen = 0;
@@ -2171,10 +2112,10 @@ char *get_user_var_name(expand_T *xp, int idx)
if (gdone++ == 0) {
hi = globvarht.ht_array;
} else {
- ++hi;
+ hi++;
}
while (HASHITEM_EMPTY(hi)) {
- ++hi;
+ hi++;
}
if (STRNCMP("g:", xp->xp_pattern, 2) == 0) {
return cat_prefix_varname('g', (char *)hi->hi_key);
@@ -2188,10 +2129,10 @@ char *get_user_var_name(expand_T *xp, int idx)
if (bdone++ == 0) {
hi = ht->ht_array;
} else {
- ++hi;
+ hi++;
}
while (HASHITEM_EMPTY(hi)) {
- ++hi;
+ hi++;
}
return cat_prefix_varname('b', (char *)hi->hi_key);
}
@@ -2202,10 +2143,10 @@ char *get_user_var_name(expand_T *xp, int idx)
if (wdone++ == 0) {
hi = ht->ht_array;
} else {
- ++hi;
+ hi++;
}
while (HASHITEM_EMPTY(hi)) {
- ++hi;
+ hi++;
}
return cat_prefix_varname('w', (char *)hi->hi_key);
}
@@ -2216,10 +2157,10 @@ char *get_user_var_name(expand_T *xp, int idx)
if (tdone++ == 0) {
hi = ht->ht_array;
} else {
- ++hi;
+ hi++;
}
while (HASHITEM_EMPTY(hi)) {
- ++hi;
+ hi++;
}
return cat_prefix_varname('t', (char *)hi->hi_key);
}
@@ -2238,7 +2179,7 @@ char *get_user_var_name(expand_T *xp, int idx)
/// Does not use 'cpo' and always uses 'magic'.
///
-/// @return TRUE if "pat" matches "text".
+/// @return true if "pat" matches "text".
int pattern_match(char *pat, char *text, bool ic)
{
int matches = 0;
@@ -2246,7 +2187,7 @@ int pattern_match(char *pat, char *text, bool ic)
// avoid 'l' flag in 'cpoptions'
char *save_cpo = p_cpo;
- p_cpo = "";
+ p_cpo = empty_option;
regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
regmatch.rm_ic = ic;
@@ -2291,7 +2232,7 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
funcexe.evaluate = evaluate;
funcexe.partial = partial;
funcexe.basetv = basetv;
- int ret = get_func_tv((char_u *)s, len, rettv, (char_u **)arg, &funcexe);
+ int ret = get_func_tv((char_u *)s, len, rettv, arg, &funcexe);
xfree(s);
@@ -2317,15 +2258,13 @@ static int eval_func(char **const arg, char *const name, const int name_len, typ
// TODO(ZyX-I): move to eval/expressions
-/*
- * The "evaluate" argument: When FALSE, the argument is only parsed but not
- * executed. The function may return OK, but the rettv will be of type
- * VAR_UNKNOWN. The function still returns FAIL for a syntax error.
- */
+/// The "evaluate" argument: When false, the argument is only parsed but not
+/// executed. The function may return OK, but the rettv will be of type
+/// VAR_UNKNOWN. The function still returns FAIL for a syntax error.
/// Handle zero level expression.
/// This calls eval1() and handles error message and nextcmd.
-/// Put the result in "rettv" when returning OK and "evaluate" is TRUE.
+/// Put the result in "rettv" when returning OK and "evaluate" is true.
/// Note: "rettv.v_lock" is not set.
///
/// @return OK or FAIL.
@@ -2372,18 +2311,16 @@ int eval0(char *arg, typval_T *rettv, char **nextcmd, int evaluate)
/// @return OK or FAIL.
int eval1(char **arg, typval_T *rettv, int evaluate)
{
- int result;
+ bool result;
typval_T var2;
- /*
- * Get the first variable.
- */
+ // Get the first variable.
if (eval2(arg, rettv, evaluate) == FAIL) {
return FAIL;
}
if ((*arg)[0] == '?') {
- result = FALSE;
+ result = false;
if (evaluate) {
bool error = false;
@@ -2396,17 +2333,13 @@ int eval1(char **arg, typval_T *rettv, int evaluate)
}
}
- /*
- * Get the second variable.
- */
+ // Get the second variable.
*arg = skipwhite(*arg + 1);
if (eval1(arg, rettv, evaluate && result) == FAIL) { // recursive!
return FAIL;
}
- /*
- * Check for the ":".
- */
+ // Check for the ":".
if ((*arg)[0] != ':') {
emsg(_("E109: Missing ':' after '?'"));
if (evaluate && result) {
@@ -2415,9 +2348,7 @@ int eval1(char **arg, typval_T *rettv, int evaluate)
return FAIL;
}
- /*
- * Get the third variable.
- */
+ // Get the third variable.
*arg = skipwhite(*arg + 1);
if (eval1(arg, &var2, evaluate && !result) == FAIL) { // Recursive!
if (evaluate && result) {
@@ -2445,22 +2376,16 @@ int eval1(char **arg, typval_T *rettv, int evaluate)
static int eval2(char **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
- long result;
- int first;
bool error = false;
- /*
- * Get the first variable.
- */
+ // Get the first variable.
if (eval3(arg, rettv, evaluate) == FAIL) {
return FAIL;
}
- /*
- * Repeat until there is no following "||".
- */
- first = TRUE;
- result = FALSE;
+ // Repeat until there is no following "||".
+ bool first = true;
+ bool result = false;
while ((*arg)[0] == '|' && (*arg)[1] == '|') {
if (evaluate && first) {
if (tv_get_number_chk(rettv, &error) != 0) {
@@ -2473,17 +2398,13 @@ static int eval2(char **arg, typval_T *rettv, int evaluate)
first = false;
}
- /*
- * Get the second variable.
- */
+ // Get the second variable.
*arg = skipwhite(*arg + 2);
if (eval3(arg, &var2, evaluate && !result) == FAIL) {
return FAIL;
}
- /*
- * Compute the result.
- */
+ // Compute the result.
if (evaluate && !result) {
if (tv_get_number_chk(&var2, &error) != 0) {
result = true;
@@ -2514,22 +2435,16 @@ static int eval2(char **arg, typval_T *rettv, int evaluate)
static int eval3(char **arg, typval_T *rettv, int evaluate)
{
typval_T var2;
- long result;
- int first;
bool error = false;
- /*
- * Get the first variable.
- */
+ // Get the first variable.
if (eval4(arg, rettv, evaluate) == FAIL) {
return FAIL;
}
- /*
- * Repeat until there is no following "&&".
- */
- first = TRUE;
- result = TRUE;
+ // Repeat until there is no following "&&".
+ bool first = true;
+ bool result = true;
while ((*arg)[0] == '&' && (*arg)[1] == '&') {
if (evaluate && first) {
if (tv_get_number_chk(rettv, &error) == 0) {
@@ -2542,17 +2457,13 @@ static int eval3(char **arg, typval_T *rettv, int evaluate)
first = false;
}
- /*
- * Get the second variable.
- */
+ // Get the second variable.
*arg = skipwhite(*arg + 2);
if (eval4(arg, &var2, evaluate && result) == FAIL) {
return FAIL;
}
- /*
- * Compute the result.
- */
+ // Compute the result.
if (evaluate && result) {
if (tv_get_number_chk(&var2, &error) == 0) {
result = false;
@@ -2597,9 +2508,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
int len = 2;
bool ic;
- /*
- * Get the first variable.
- */
+ // Get the first variable.
if (eval5(arg, rettv, evaluate) == FAIL) {
return FAIL;
}
@@ -2648,9 +2557,7 @@ static int eval4(char **arg, typval_T *rettv, int evaluate)
break;
}
- /*
- * If there is a comparative operator, use it.
- */
+ // If there is a comparative operator, use it.
if (type != EXPR_UNKNOWN) {
// extra question mark appended: ignore case
if (p[len] == '?') {
@@ -2701,16 +2608,12 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
float_T f1 = 0, f2 = 0;
char *p;
- /*
- * Get the first variable.
- */
- if (eval6(arg, rettv, evaluate, FALSE) == FAIL) {
+ // Get the first variable.
+ if (eval6(arg, rettv, evaluate, false) == FAIL) {
return FAIL;
}
- /*
- * Repeat computing, until no '+', '-' or '.' is following.
- */
+ // Repeat computing, until no '+', '-' or '.' is following.
for (;;) {
op = (char_u)(**arg);
if (op != '+' && op != '-' && op != '.') {
@@ -2732,9 +2635,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
}
}
- /*
- * Get the second variable.
- */
+ // Get the second variable.
if (op == '.' && *(*arg + 1) == '.') { // ..string concatenation
(*arg)++;
}
@@ -2745,9 +2646,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
}
if (evaluate) {
- /*
- * Compute the result.
- */
+ // Compute the result.
if (op == '.') {
char buf1[NUMBUFLEN];
char buf2[NUMBUFLEN];
@@ -2759,7 +2658,7 @@ static int eval5(char **arg, typval_T *rettv, int evaluate)
tv_clear(&var2);
return FAIL;
}
- p = (char *)concat_str((const char_u *)s1, (const char_u *)s2);
+ p = concat_str(s1, s2);
tv_clear(rettv);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = p;
@@ -2876,16 +2775,12 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
float_T f1 = 0, f2 = 0;
bool error = false;
- /*
- * Get the first variable.
- */
+ // Get the first variable.
if (eval7(arg, rettv, evaluate, want_string) == FAIL) {
return FAIL;
}
- /*
- * Repeat computing, until no '*', '/' or '%' is following.
- */
+ // Repeat computing, until no '*', '/' or '%' is following.
for (;;) {
op = (char_u)(**arg);
if (op != '*' && op != '/' && op != '%') {
@@ -2908,9 +2803,7 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
n1 = 0;
}
- /*
- * Get the second variable.
- */
+ // Get the second variable.
*arg = skipwhite(*arg + 1);
if (eval7(arg, &var2, evaluate, false) == FAIL) {
return FAIL;
@@ -2935,10 +2828,8 @@ static int eval6(char **arg, typval_T *rettv, int evaluate, int want_string)
}
}
- /*
- * Compute the result.
- * When either side is a float the result is a float.
- */
+ // Compute the result.
+ // When either side is a float the result is a float.
if (use_float) {
if (op == '*') {
f1 = f1 * f2;
@@ -3051,9 +2942,9 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
get_float = true;
p = skipdigits(p + 2);
if (*p == 'e' || *p == 'E') {
- ++p;
+ p++;
if (*p == '-' || *p == '+') {
- ++p;
+ p++;
}
if (!ascii_isdigit(*p)) {
get_float = false;
@@ -3147,7 +3038,7 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
// Lambda: {arg, arg -> expr}
// Dictionary: {'key': val, 'key': val}
case '{':
- ret = get_lambda_tv((char_u **)arg, rettv, evaluate);
+ ret = get_lambda_tv(arg, rettv, evaluate);
if (ret == NOTDONE) {
ret = dict_get_tv(arg, rettv, evaluate, false);
}
@@ -3164,13 +3055,13 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
// Register contents: @r.
case '@':
- ++*arg;
+ (*arg)++;
if (evaluate) {
rettv->v_type = VAR_STRING;
rettv->vval.v_string = get_reg_contents(**arg, kGRegExprSrc);
}
if (**arg != NUL) {
- ++*arg;
+ (*arg)++;
}
break;
@@ -3179,7 +3070,7 @@ static int eval7(char **arg, typval_T *rettv, int evaluate, int want_string)
*arg = skipwhite(*arg + 1);
ret = eval1(arg, rettv, evaluate); // recursive!
if (**arg == ')') {
- ++*arg;
+ (*arg)++;
} else if (ret == OK) {
emsg(_("E110: Missing ')'"));
tv_clear(rettv);
@@ -3325,7 +3216,7 @@ static int call_func_rettv(char **const arg, typval_T *const rettv, const bool e
funcexe.selfdict = selfdict;
funcexe.basetv = basetv;
const int ret = get_func_tv((char_u *)funcname, is_lua ? (int)(*arg - funcname) : -1, rettv,
- (char_u **)arg, &funcexe);
+ arg, &funcexe);
// Clear the funcref afterwards, so that deleting it while
// evaluating the arguments is possible (see test55).
@@ -3353,7 +3244,7 @@ static int eval_lambda(char **const arg, typval_T *const rettv, const bool evalu
typval_T base = *rettv;
rettv->v_type = VAR_UNKNOWN;
- int ret = get_lambda_tv((char_u **)arg, rettv, evaluate);
+ int ret = get_lambda_tv(arg, rettv, evaluate);
if (ret != OK) {
return FAIL;
} else if (**arg != '(') {
@@ -3503,9 +3394,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
typval_T var1 = TV_INITIAL_VALUE;
typval_T var2 = TV_INITIAL_VALUE;
if (**arg == '.') {
- /*
- * dict.name
- */
+ // dict.name
key = *arg + 1;
for (len = 0; ASCII_ISALNUM(key[len]) || key[len] == '_'; len++) {}
if (len == 0) {
@@ -3513,11 +3402,9 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
}
*arg = skipwhite(key + len);
} else {
- /*
- * something[idx]
- *
- * Get the (first) variable from inside the [].
- */
+ // something[idx]
+ //
+ // Get the (first) variable from inside the [].
*arg = skipwhite(*arg + 1);
if (**arg == ':') {
empty1 = true;
@@ -3529,9 +3416,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
return FAIL;
}
- /*
- * Get the second variable from inside the [:].
- */
+ // Get the second variable from inside the [:].
if (**arg == ':') {
range = true;
*arg = skipwhite(*arg + 1);
@@ -3772,11 +3657,7 @@ static int eval_index(char **arg, typval_T *rettv, int evaluate, int verbose)
int get_option_tv(const char **const arg, typval_T *const rettv, const bool evaluate)
FUNC_ATTR_NONNULL_ARG(1)
{
- long numval;
- char *stringval;
- getoption_T opt_type;
bool working = (**arg == '+'); // has("+option")
- int ret = OK;
int opt_flags;
// Isolate the option name and find its value.
@@ -3793,10 +3674,14 @@ int get_option_tv(const char **const arg, typval_T *const rettv, const bool eval
return OK;
}
+ long numval;
+ char *stringval;
+ int ret = OK;
+
char c = *option_end;
*option_end = NUL;
- opt_type = get_option_value(*arg, &numval,
- rettv == NULL ? NULL : &stringval, opt_flags);
+ getoption_T opt_type = get_option_value(*arg, &numval,
+ rettv == NULL ? NULL : &stringval, opt_flags);
if (opt_type == gov_unknown) {
if (rettv != NULL) {
@@ -3837,9 +3722,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
char *p;
unsigned int extra = 0;
- /*
- * Find the end of the string, skipping backslashed characters.
- */
+ // Find the end of the string, skipping backslashed characters.
for (p = *arg + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p)) {
if (*p == '\\' && p[1] != NUL) {
p++;
@@ -3863,10 +3746,8 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
return OK;
}
- /*
- * Copy the string into allocated memory, handling backslashed
- * characters.
- */
+ // Copy the string into allocated memory, handling backslashed
+ // characters.
const int len = (int)(p - *arg + extra);
char *name = xmalloc((size_t)len);
rettv->v_type = VAR_STRING;
@@ -3905,7 +3786,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
}
nr = 0;
while (--n >= 0 && ascii_isxdigit(p[1])) {
- ++p;
+ p++;
nr = (nr << 4) + hex2nr(*p);
}
p++;
@@ -3935,7 +3816,7 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
*name = (char)((*name << 3) + *p++ - '0');
}
}
- ++name;
+ name++;
break;
// Special key, e.g.: "\<C-W>"
@@ -3957,11 +3838,11 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
FALLTHROUGH;
default:
- mb_copy_char((const char_u **)&p, (char_u **)&name);
+ mb_copy_char((const char **)&p, &name);
break;
}
} else {
- mb_copy_char((const char_u **)&p, (char_u **)&name);
+ mb_copy_char((const char **)&p, &name);
}
}
*name = NUL;
@@ -3979,19 +3860,16 @@ static int get_string_tv(char **arg, typval_T *rettv, int evaluate)
static int get_lit_string_tv(char **arg, typval_T *rettv, int evaluate)
{
char *p;
- char *str;
int reduce = 0;
- /*
- * Find the end of the string, skipping ''.
- */
+ // Find the end of the string, skipping ''.
for (p = *arg + 1; *p != NUL; MB_PTR_ADV(p)) {
if (*p == '\'') {
if (p[1] != '\'') {
break;
}
- ++reduce;
- ++p;
+ reduce++;
+ p++;
}
}
@@ -4006,10 +3884,8 @@ static int get_lit_string_tv(char **arg, typval_T *rettv, int evaluate)
return OK;
}
- /*
- * Copy the string into allocated memory, handling '' to ' reduction.
- */
- str = xmalloc((size_t)((p - *arg) - reduce));
+ // Copy the string into allocated memory, handling '' to ' reduction.
+ char *str = xmalloc((size_t)((p - *arg) - reduce));
rettv->v_type = VAR_STRING;
rettv->vval.v_string = str;
@@ -4018,9 +3894,9 @@ static int get_lit_string_tv(char **arg, typval_T *rettv, int evaluate)
if (p[1] != '\'') {
break;
}
- ++p;
+ p++;
}
- mb_copy_char((const char_u **)&p, (char_u **)&str);
+ mb_copy_char((const char **)&p, &str);
}
*str = NUL;
*arg = p + 1;
@@ -4119,16 +3995,14 @@ failret:
/// @param ic ignore case
bool func_equal(typval_T *tv1, typval_T *tv2, bool ic)
{
- char_u *s1, *s2;
- dict_T *d1, *d2;
- int a1, a2;
-
// empty and NULL function name considered the same
- s1 = (char_u *)(tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial));
+ char_u *s1 =
+ (char_u *)(tv1->v_type == VAR_FUNC ? tv1->vval.v_string : partial_name(tv1->vval.v_partial));
if (s1 != NULL && *s1 == NUL) {
s1 = NULL;
}
- s2 = (char_u *)(tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial));
+ char_u *s2 =
+ (char_u *)(tv2->v_type == VAR_FUNC ? tv2->vval.v_string : partial_name(tv2->vval.v_partial));
if (s2 != NULL && *s2 == NUL) {
s2 = NULL;
}
@@ -4141,8 +4015,8 @@ bool func_equal(typval_T *tv1, typval_T *tv2, bool ic)
}
// empty dict and NULL dict is different
- d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
- d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
+ dict_T *d1 = tv1->v_type == VAR_FUNC ? NULL : tv1->vval.v_partial->pt_dict;
+ dict_T *d2 = tv2->v_type == VAR_FUNC ? NULL : tv2->vval.v_partial->pt_dict;
if (d1 == NULL || d2 == NULL) {
if (d1 != d2) {
return false;
@@ -4152,8 +4026,8 @@ bool func_equal(typval_T *tv1, typval_T *tv2, bool ic)
}
// empty list and no list considered the same
- a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
- a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
+ int a1 = tv1->v_type == VAR_FUNC ? 0 : tv1->vval.v_partial->pt_argc;
+ int a2 = tv2->v_type == VAR_FUNC ? 0 : tv2->vval.v_partial->pt_argc;
if (a1 != a2) {
return false;
}
@@ -4182,25 +4056,23 @@ int get_copyID(void)
return current_copyID;
}
-/*
- * Garbage collection for lists and dictionaries.
- *
- * We use reference counts to be able to free most items right away when they
- * are no longer used. But for composite items it's possible that it becomes
- * unused while the reference count is > 0: When there is a recursive
- * reference. Example:
- * :let l = [1, 2, 3]
- * :let d = {9: l}
- * :let l[1] = d
- *
- * Since this is quite unusual we handle this with garbage collection: every
- * once in a while find out which lists and dicts are not referenced from any
- * variable.
- *
- * Here is a good reference text about garbage collection (refers to Python
- * but it applies to all reference-counting mechanisms):
- * http://python.ca/nas/python/gc/
- */
+/// Garbage collection for lists and dictionaries.
+///
+/// We use reference counts to be able to free most items right away when they
+/// are no longer used. But for composite items it's possible that it becomes
+/// unused while the reference count is > 0: When there is a recursive
+/// reference. Example:
+/// :let l = [1, 2, 3]
+/// :let d = {9: l}
+/// :let l[1] = d
+///
+/// Since this is quite unusual we handle this with garbage collection: every
+/// once in a while find out which lists and dicts are not referenced from any
+/// variable.
+///
+/// Here is a good reference text about garbage collection (refers to Python
+/// but it applies to all reference-counting mechanisms):
+/// http://python.ca/nas/python/gc/
/// Do garbage collection for lists and dicts.
///
@@ -4219,6 +4091,23 @@ bool garbage_collect(bool testing)
garbage_collect_at_exit = false;
}
+ // The execution stack can grow big, limit the size.
+ if (exestack.ga_maxlen - exestack.ga_len > 500) {
+ // Keep 150% of the current size, with a minimum of the growth size.
+ int n = exestack.ga_len / 2;
+ if (n < exestack.ga_growsize) {
+ n = exestack.ga_growsize;
+ }
+
+ // Don't make it bigger though.
+ if (exestack.ga_len + n < exestack.ga_maxlen) {
+ size_t new_len = (size_t)exestack.ga_itemsize * (size_t)(exestack.ga_len + n);
+ char *pp = xrealloc(exestack.ga_data, new_len);
+ exestack.ga_maxlen = exestack.ga_len + n;
+ exestack.ga_data = pp;
+ }
+ }
+
// We advance by two (COPYID_INC) because we add one for items referenced
// through previous_funccal.
const int copyID = get_copyID();
@@ -4232,7 +4121,7 @@ bool garbage_collect(bool testing)
ABORTING(set_ref_in_previous_funccal)(copyID);
// script-local variables
- for (int i = 1; i <= ga_scripts.ga_len; ++i) {
+ for (int i = 1; i <= ga_scripts.ga_len; i++) {
ABORTING(set_ref_in_ht)(&SCRIPT_VARS(i), copyID, NULL);
}
@@ -4691,21 +4580,16 @@ static int get_literal_key(char **arg, typval_T *tv)
/// @return OK or FAIL. Returns NOTDONE for {expr}.
static int dict_get_tv(char **arg, typval_T *rettv, int evaluate, bool literal)
{
- dict_T *d = NULL;
- typval_T tvkey;
typval_T tv;
char *key = NULL;
- dictitem_T *item;
char *start = skipwhite(*arg + 1);
char buf[NUMBUFLEN];
- /*
- * First check if it's not a curly-braces thing: {expr}.
- * Must do this without evaluating, otherwise a function may be called
- * twice. Unfortunately this means we need to call eval1() twice for the
- * first item.
- * But {} is an empty Dictionary.
- */
+ // First check if it's not a curly-braces thing: {expr}.
+ // Must do this without evaluating, otherwise a function may be called
+ // twice. Unfortunately this means we need to call eval1() twice for the
+ // first item.
+ // But {} is an empty Dictionary.
if (*start != '}') {
if (eval1(&start, &tv, false) == FAIL) { // recursive!
return FAIL;
@@ -4715,9 +4599,11 @@ static int dict_get_tv(char **arg, typval_T *rettv, int evaluate, bool literal)
}
}
+ dict_T *d = NULL;
if (evaluate) {
d = tv_dict_alloc();
}
+ typval_T tvkey;
tvkey.v_type = VAR_UNKNOWN;
tv.v_type = VAR_UNKNOWN;
@@ -4750,7 +4636,7 @@ static int dict_get_tv(char **arg, typval_T *rettv, int evaluate, bool literal)
goto failret;
}
if (evaluate) {
- item = tv_dict_find(d, (const char *)key, -1);
+ dictitem_T *item = tv_dict_find(d, (const char *)key, -1);
if (item != NULL) {
semsg(_("E721: Duplicate key in Dictionary: \"%s\""), key);
tv_clear(&tvkey);
@@ -4805,8 +4691,6 @@ failret:
size_t string2float(const char *const text, float_T *const ret_value)
FUNC_ATTR_NONNULL_ALL
{
- char *s = NULL;
-
// MS-Windows does not deal with "inf" and "nan" properly
if (STRNICMP(text, "inf", 3) == 0) {
*ret_value = (float_T)INFINITY;
@@ -4820,6 +4704,7 @@ size_t string2float(const char *const text, float_T *const ret_value)
*ret_value = (float_T)NAN;
return 3;
}
+ char *s = NULL;
*ret_value = strtod(text, &s);
return (size_t)(s - text);
}
@@ -4833,23 +4718,18 @@ size_t string2float(const char *const text, float_T *const ret_value)
/// @return FAIL if the name is invalid.
static int get_env_tv(char **arg, typval_T *rettv, int evaluate)
{
- char *name;
- char *string = NULL;
- int len;
- int cc;
-
- ++*arg;
- name = *arg;
- len = get_env_len((const char **)arg);
+ (*arg)++;
+ char *name = *arg;
+ int len = get_env_len((const char **)arg);
if (evaluate) {
if (len == 0) {
return FAIL; // Invalid empty name.
}
- cc = (char_u)name[len];
+ int cc = (int)name[len];
name[len] = NUL;
// First try vim_getenv(), fast for normal environment vars.
- string = vim_getenv(name);
+ char *string = vim_getenv(name);
if (string == NULL || *string == NUL) {
xfree(string);
@@ -4867,18 +4747,6 @@ static int get_env_tv(char **arg, typval_T *rettv, int evaluate)
return OK;
}
-/// Get the argument list for a given window
-void get_arglist_as_rettv(aentry_T *arglist, int argcount, typval_T *rettv)
-{
- tv_list_alloc_ret(rettv, argcount);
- if (arglist != NULL) {
- for (int idx = 0; idx < argcount; idx++) {
- tv_list_append_string(rettv->vval.v_list,
- (const char *)alist_name(&arglist[idx]), -1);
- }
- }
-}
-
/// Add an assert error to v:errors.
void assert_error(garray_T *gap)
{
@@ -4908,17 +4776,10 @@ win_T *find_win_by_nr_or_id(typval_T *vp)
/// Implementation of map() and filter().
void filter_map(typval_T *argvars, typval_T *rettv, int map)
{
- typval_T *expr;
list_T *l = NULL;
- dictitem_T *di;
- hashtab_T *ht;
- hashitem_T *hi;
dict_T *d = NULL;
- typval_T save_val;
- typval_T save_key;
blob_T *b = NULL;
int rem = false;
- int todo;
char *ermsg = map ? "map()" : "filter()";
const char *const arg_errmsg = (map
? N_("map() argument")
@@ -4949,18 +4810,20 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
return;
}
- expr = &argvars[1];
+ typval_T *expr = &argvars[1];
// On type errors, the preceding call has already displayed an error
// message. Avoid a misleading error message for an empty string that
// was not passed as argument.
if (expr->v_type != VAR_UNKNOWN) {
+ typval_T save_val;
prepare_vimvar(VV_VAL, &save_val);
// We reset "did_emsg" to be able to detect whether an error
// occurred during evaluation of the expression.
save_did_emsg = did_emsg;
- did_emsg = FALSE;
+ did_emsg = false;
+ typval_T save_key;
prepare_vimvar(VV_KEY, &save_key);
if (argvars[0].v_type == VAR_DICT) {
vimvars[VV_KEY].vv_type = VAR_STRING;
@@ -4969,14 +4832,14 @@ void filter_map(typval_T *argvars, typval_T *rettv, int map)
if (map && d->dv_lock == VAR_UNLOCKED) {
d->dv_lock = VAR_LOCKED;
}
- ht = &d->dv_hashtab;
+ hashtab_T *ht = &d->dv_hashtab;
hash_lock(ht);
- todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; ++hi) {
+ int todo = (int)ht->ht_used;
+ for (hashitem_T *hi = ht->ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
- --todo;
+ todo--;
- di = TV_DICT_HI2DI(hi);
+ dictitem_T *di = TV_DICT_HI2DI(hi);
if (map
&& (var_check_lock(di->di_tv.v_lock, arg_errmsg, TV_TRANSLATE)
|| var_check_ro(di->di_flags, arg_errmsg, TV_TRANSLATE))) {
@@ -5100,7 +4963,7 @@ theend:
return retval;
}
-void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr fptr)
+void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
{
char *s;
char *name;
@@ -5125,7 +4988,7 @@ void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref, FunPtr
if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref) {
name = s;
- trans_name = (char *)trans_function_name((char_u **)&name, false,
+ trans_name = (char *)trans_function_name(&name, false,
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD
| TFN_NO_DEREF, NULL, NULL);
if (*name != NUL) {
@@ -5329,29 +5192,6 @@ linenr_T tv_get_lnum_buf(const typval_T *const tv, const buf_T *const buf)
return (linenr_T)tv_get_number_chk(tv, NULL);
}
-void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
-{
- if (what_arg->v_type == VAR_UNKNOWN) {
- tv_list_alloc_ret(rettv, kListLenMayKnow);
- if (is_qf || wp != NULL) {
- (void)get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
- }
- } else {
- tv_dict_alloc_ret(rettv);
- if (is_qf || wp != NULL) {
- if (what_arg->v_type == VAR_DICT) {
- dict_T *d = what_arg->vval.v_dict;
-
- if (d != NULL) {
- qf_get_properties(wp, d, rettv->vval.v_dict);
- }
- } else {
- emsg(_(e_dictreq));
- }
- }
- }
-}
-
/// @return information (variables, options, etc.) about a tab page
/// as a dictionary.
dict_T *get_tabpage_info(tabpage_T *tp, int tp_idx)
@@ -5383,12 +5223,12 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
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);
+ 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);
+ 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));
@@ -5688,11 +5528,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
FUNC_ATTR_NONNULL_ARG(4, 5)
{
linenr_T lnum = lnum_arg + (append ? 1 : 0);
- const char *line = NULL;
- list_T *l = NULL;
- listitem_T *li = NULL;
long added = 0;
- linenr_T append_lnum;
buf_T *curbuf_save = NULL;
win_T *curwin_save = NULL;
const bool is_curbuf = buf == curbuf;
@@ -5714,6 +5550,7 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
find_win_for_curbuf();
}
+ linenr_T append_lnum;
if (append) {
// appendbufline() uses the line number below which we insert
append_lnum = lnum - 1;
@@ -5723,6 +5560,9 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
append_lnum = curbuf->b_ml.ml_line_count;
}
+ list_T *l = NULL;
+ listitem_T *li = NULL;
+ const char *line = NULL;
if (lines->v_type == VAR_LIST) {
l = lines->vval.v_list;
li = tv_list_first(l);
@@ -5806,7 +5646,6 @@ void set_buffer_lines(buf_T *buf, linenr_T lnum_arg, bool append, const typval_T
void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
FUNC_ATTR_NONNULL_ALL
{
- const void *iter = NULL;
list_T *const list = tv_list_alloc(kListLenShouldKnow);
rettv->v_type = VAR_LIST;
rettv->vval.v_list = list;
@@ -5815,6 +5654,7 @@ void get_xdg_var_list(const XDGVarType xdg, typval_T *rettv)
if (dirs == NULL) {
return;
}
+ const void *iter = NULL;
do {
size_t dir_len;
const char *dir;
@@ -5924,9 +5764,9 @@ void get_system_output_as_rettv(typval_T *argvars, typval_T *rettv, bool retlist
#ifdef USE_CRNL
// translate <CR><NL> into <NL>
char *d = res;
- for (char *s = res; *s; ++s) {
+ for (char *s = res; *s; s++) {
if (s[0] == CAR && s[1] == NL) {
- ++s;
+ s++;
}
*d++ = *s;
@@ -5999,7 +5839,17 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
switch (callback->type) {
case kCallbackFuncref:
name = callback->data.funcref;
- partial = NULL;
+ int len = (int)STRLEN(name);
+ if (len >= 6 && !memcmp(name, "v:lua.", 6)) {
+ name += 6;
+ len = check_luafunc_name(name, false);
+ if (len == 0) {
+ return false;
+ }
+ partial = vvlua_partial;
+ } else {
+ partial = NULL;
+ }
break;
case kCallbackPartial:
@@ -6135,7 +5985,7 @@ void timer_due_cb(TimeWatcher *tw, void *data)
// Handle error message
if (called_emsg > called_emsg_before && did_emsg) {
timer->emsg_count++;
- if (current_exception != NULL) {
+ if (did_throw) {
discard_current_exception();
}
}
@@ -6498,12 +6348,9 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
// Argument can be [lnum, col, coladd].
if (tv->v_type == VAR_LIST) {
- list_T *l;
- int len;
bool error = false;
- listitem_T *li;
- l = tv->vval.v_list;
+ list_T *l = tv->vval.v_list;
if (l == NULL) {
return NULL;
}
@@ -6520,6 +6367,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
if (error) {
return NULL;
}
+ int len;
if (charcol) {
len = mb_charlen(ml_get(pos.lnum));
} else {
@@ -6527,7 +6375,7 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
}
// We accept "$" for the column number: last column.
- li = tv_list_find(l, 1L);
+ listitem_T *li = tv_list_find(l, 1L);
if (li != NULL && TV_LIST_ITEM_TV(li)->v_type == VAR_STRING
&& TV_LIST_ITEM_TV(li)->vval.v_string != NULL
&& STRCMP(TV_LIST_ITEM_TV(li)->vval.v_string, "$") == 0) {
@@ -6627,8 +6475,6 @@ pos_T *var2fpos(const typval_T *const tv, const bool dollar_lnum, int *const ret
int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool charcol)
{
list_T *l;
- int i = 0;
- long n;
// List must be: [fnum, lnum, col, coladd, curswant], where "fnum" is only
// there when "fnump" isn't NULL; "coladd" and "curswant" are optional.
@@ -6639,6 +6485,8 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c
return FAIL;
}
+ int i = 0;
+ long n;
if (fnump != NULL) {
n = tv_list_find_nr(l, i++, NULL); // fnum
if (n < 0) {
@@ -6691,15 +6539,13 @@ int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp, bool c
/// @return 0 for error.
int get_env_len(const char **arg)
{
- int len;
-
const char *p;
for (p = *arg; vim_isIDc(*p); p++) {}
if (p == *arg) { // No name found.
return 0;
}
- len = (int)(p - *arg);
+ int len = (int)(p - *arg);
*arg = p;
return len;
}
@@ -6747,8 +6593,6 @@ int get_id_len(const char **const arg)
/// 0 if something else is wrong.
int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbose)
{
- int len;
-
*alias = NULL; // default to no alias
if ((*arg)[0] == (char)K_SPECIAL && (*arg)[1] == (char)KS_EXTRA
@@ -6757,7 +6601,7 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo
*arg += 3;
return get_id_len(arg) + 3;
}
- len = eval_fname_script(*arg);
+ int len = eval_fname_script(*arg);
if (len > 0) {
// literal "<SID>", "s:" or "<SNR>"
*arg += len;
@@ -6775,10 +6619,8 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo
return len;
}
- /*
- * Include any <SID> etc in the expanded string:
- * Thus the -len here.
- */
+ // Include any <SID> etc in the expanded string:
+ // Thus the -len here.
char *temp_string = make_expanded_name(*arg - len, expr_start, expr_end, (char *)p);
if (temp_string == NULL) {
return -1;
@@ -6810,10 +6652,6 @@ int get_name_len(const char **const arg, char **alias, bool evaluate, bool verbo
const char *find_name_end(const char *arg, const char **expr_start, const char **expr_end,
int flags)
{
- int mb_nest = 0;
- int br_nest = 0;
- int len;
-
if (expr_start != NULL) {
*expr_start = NULL;
*expr_end = NULL;
@@ -6824,6 +6662,10 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
return arg;
}
+ int mb_nest = 0;
+ int br_nest = 0;
+ int len;
+
const char *p;
for (p = arg; *p != NUL
&& (eval_isnamec(*p)
@@ -6841,7 +6683,7 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
// skip over "str\"ing" to avoid counting [ and ] inside it.
for (p = p + 1; *p != NUL && *p != '"'; MB_PTR_ADV(p)) {
if (*p == '\\' && p[1] != NUL) {
- ++p;
+ p++;
}
}
if (*p == NUL) {
@@ -6859,9 +6701,9 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
if (mb_nest == 0) {
if (*p == '[') {
- ++br_nest;
+ br_nest++;
} else if (*p == ']') {
- --br_nest;
+ br_nest--;
}
}
@@ -6897,20 +6739,19 @@ const char *find_name_end(const char *arg, const char **expr_start, const char *
static char *make_expanded_name(const char *in_start, char *expr_start, char *expr_end,
char *in_end)
{
- char c1;
- char *retval = NULL;
- char *temp_result;
- char *nextcmd = NULL;
-
if (expr_end == NULL || in_end == NULL) {
return NULL;
}
+
+ char *retval = NULL;
+ char *nextcmd = NULL;
+
*expr_start = NUL;
*expr_end = NUL;
- c1 = *in_end;
+ char c1 = *in_end;
*in_end = NUL;
- temp_result = eval_to_string(expr_start + 1, &nextcmd, false);
+ char *temp_result = eval_to_string(expr_start + 1, &nextcmd, false);
if (temp_result != NULL && nextcmd == NULL) {
retval = xmalloc(STRLEN(temp_result) + (size_t)(expr_start - in_start)
+ (size_t)(in_end - expr_end) + 1);
@@ -6940,14 +6781,14 @@ static char *make_expanded_name(const char *in_start, char *expr_start, char *ex
return retval;
}
-/// @return TRUE if character "c" can be used in a variable or function name.
+/// @return true if character "c" can be used in a variable or function name.
/// Does not include '{' or '}' for magic braces.
int eval_isnamec(int c)
{
return ASCII_ISALNUM(c) || c == '_' || c == ':' || c == AUTOLOAD_CHAR;
}
-/// @return TRUE if character "c" can be used as the first character in a
+/// @return true if character "c" can be used as the first character in a
/// variable or function name (excluding '{' and '}').
int eval_isnamec1(int c)
{
@@ -7000,7 +6841,7 @@ void set_vim_var_char(int c)
/// Set v:count to "count" and v:count1 to "count1".
///
-/// @param set_prevcount if TRUE, first set v:prevcount from v:count.
+/// @param set_prevcount if true, first set v:prevcount from v:count.
void set_vcount(long count, long count1, int set_prevcount)
{
if (set_prevcount) {
@@ -7353,7 +7194,7 @@ int handle_subscript(const char **const arg, typval_T *rettv, int evaluate, int
if (rettv->v_type == VAR_DICT) {
selfdict = rettv->vval.v_dict;
if (selfdict != NULL) {
- ++selfdict->dv_refcount;
+ selfdict->dv_refcount++;
}
} else {
selfdict = NULL;
@@ -7430,8 +7271,6 @@ dictitem_T *find_var_in_ht(hashtab_T *const ht, int htname, const char *const va
const size_t varname_len, int no_autoload)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- hashitem_T *hi;
-
if (varname_len == 0) {
// Must be something like "s:", otherwise "ht" would be NULL.
switch (htname) {
@@ -7455,7 +7294,7 @@ dictitem_T *find_var_in_ht(hashtab_T *const ht, int htname, const char *const va
return NULL;
}
- hi = hash_find_len(ht, varname, varname_len);
+ hashitem_T *hi = hash_find_len(ht, varname, varname_len);
if (HASHITEM_EMPTY(hi)) {
// For global variables we may try auto-loading the script. If it
// worked find the variable again. Don't auto-load a script if it was
@@ -7490,7 +7329,6 @@ dictitem_T *find_var_in_ht(hashtab_T *const ht, int htname, const char *const va
hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char **varname,
dict_T **d)
{
- hashitem_T *hi;
funccall_T *funccal = get_funccal();
*d = NULL;
@@ -7506,7 +7344,7 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char
*varname = name;
// "version" is "v:version" in all scopes
- hi = hash_find_len(&compat_hashtab, name, name_len);
+ hashitem_T *hi = hash_find_len(&compat_hashtab, name, name_len);
if (!HASHITEM_EMPTY(hi)) {
return &compat_hashtab;
}
@@ -7562,7 +7400,7 @@ hashtab_T *find_var_ht_dict(const char *name, const size_t name_len, const char
bool should_free;
// should_free is ignored as script_sctx will be resolved to a fnmae
// & new_script_item will consume it.
- char *sc_name = (char *)get_scriptname(last_set, &should_free);
+ char *sc_name = get_scriptname(last_set, &should_free);
new_script_item(sc_name, &current_sctx.sc_sid);
}
}
@@ -7595,28 +7433,26 @@ hashtab_T *find_var_ht(const char *name, const size_t name_len, const char **var
/// sourcing this script and when executing functions defined in the script.
void new_script_vars(scid_T id)
{
- hashtab_T *ht;
scriptvar_T *sv;
ga_grow(&ga_scripts, id - ga_scripts.ga_len);
- {
- /* Re-allocating ga_data means that an ht_array pointing to
- * ht_smallarray becomes invalid. We can recognize this: ht_mask is
- * at its init value. Also reset "v_dict", it's always the same. */
- for (int i = 1; i <= ga_scripts.ga_len; ++i) {
- ht = &SCRIPT_VARS(i);
- if (ht->ht_mask == HT_INIT_SIZE - 1) {
- ht->ht_array = ht->ht_smallarray;
- }
- sv = SCRIPT_SV(i);
- sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
- }
- while (ga_scripts.ga_len < id) {
- sv = SCRIPT_SV(ga_scripts.ga_len + 1) = xcalloc(1, sizeof(scriptvar_T));
- init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
- ++ga_scripts.ga_len;
+ // Re-allocating ga_data means that an ht_array pointing to
+ // ht_smallarray becomes invalid. We can recognize this: ht_mask is
+ // at its init value. Also reset "v_dict", it's always the same.
+ for (int i = 1; i <= ga_scripts.ga_len; i++) {
+ hashtab_T *ht = &SCRIPT_VARS(i);
+ if (ht->ht_mask == HT_INIT_SIZE - 1) {
+ ht->ht_array = ht->ht_smallarray;
}
+ sv = SCRIPT_SV(i);
+ sv->sv_var.di_tv.vval.v_dict = &sv->sv_dict;
+ }
+
+ while (ga_scripts.ga_len < id) {
+ sv = SCRIPT_SV(ga_scripts.ga_len + 1) = xcalloc(1, sizeof(scriptvar_T));
+ init_var_dict(&sv->sv_dict, &sv->sv_var, VAR_SCOPE);
+ ga_scripts.ga_len++;
}
}
@@ -7640,8 +7476,8 @@ void init_var_dict(dict_T *dict, ScopeDictDictItem *dict_var, ScopeType scope)
/// Unreference a dictionary initialized by init_var_dict().
void unref_var_dict(dict_T *dict)
{
- /* Now the dict needs to be freed if no one else is using it, go back to
- * normal reference counting. */
+ // Now the dict needs to be freed if no one else is using it, go back to
+ // normal reference counting.
dict->dv_refcount -= DO_NOT_FREE_CNT - 1;
tv_dict_unref(dict);
}
@@ -7673,7 +7509,7 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
emsg(_("E698: variable nested too deep for making a copy"));
return FAIL;
}
- ++recurse;
+ recurse++;
switch (from->v_type) {
case VAR_NUMBER:
@@ -7691,9 +7527,9 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
} else {
to->v_type = VAR_STRING;
to->v_lock = VAR_UNLOCKED;
- if ((to->vval.v_string = (char *)string_convert((vimconv_T *)conv,
- (char_u *)from->vval.v_string,
- NULL))
+ if ((to->vval.v_string = string_convert((vimconv_T *)conv,
+ from->vval.v_string,
+ NULL))
== NULL) {
to->vval.v_string = xstrdup(from->vval.v_string);
}
@@ -7726,7 +7562,7 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
} else if (copyID != 0 && from->vval.v_dict->dv_copyID == copyID) {
// use the copy made earlier
to->vval.v_dict = from->vval.v_dict->dv_copydict;
- ++to->vval.v_dict->dv_refcount;
+ to->vval.v_dict->dv_refcount++;
} else {
to->vval.v_dict = tv_dict_copy(conv, from->vval.v_dict, deep, copyID);
}
@@ -7738,7 +7574,7 @@ int var_item_copy(const vimconv_T *const conv, typval_T *const from, typval_T *c
internal_error("var_item_copy(UNKNOWN)");
ret = FAIL;
}
- --recurse;
+ recurse--;
return ret;
}
@@ -7755,7 +7591,7 @@ void ex_echo(exarg_T *eap)
const int called_emsg_before = called_emsg;
if (eap->skip) {
- ++emsg_skip;
+ emsg_skip++;
}
while (*arg != NUL && *arg != '|' && *arg != '\n' && !got_int) {
// If eval1() causes an error message the text from the command may
@@ -7835,12 +7671,11 @@ void ex_execute(exarg_T *eap)
typval_T rettv;
int ret = OK;
garray_T ga;
- int save_did_emsg;
ga_init(&ga, 1, 80);
if (eap->skip) {
- ++emsg_skip;
+ emsg_skip++;
}
while (*arg != NUL && *arg != '|' && *arg != '\n') {
ret = eval1_emsg(&arg, &rettv, !eap->skip);
@@ -7884,7 +7719,7 @@ void ex_execute(exarg_T *eap)
ui_flush();
} else if (eap->cmdidx == CMD_echoerr) {
// We don't want to abort following commands, restore did_emsg.
- save_did_emsg = did_emsg;
+ int save_did_emsg = did_emsg;
msg_ext_set_kind("echoerr");
emsg(ga.ga_data);
if (!force_abort) {
@@ -7898,7 +7733,7 @@ void ex_execute(exarg_T *eap)
ga_clear(&ga);
if (eap->skip) {
- --emsg_skip;
+ emsg_skip--;
}
eap->nextcmd = (char *)check_nextcmd((char_u *)arg);
@@ -7914,7 +7749,7 @@ const char *find_option_end(const char **const arg, int *const opt_flags)
{
const char *p = *arg;
- ++p;
+ p++;
if (*p == 'g' && p[1] == ':') {
*opt_flags = OPT_GLOBAL;
p += 2;
@@ -7940,174 +7775,6 @@ const char *find_option_end(const char **const arg, int *const opt_flags)
return p;
}
-/// Start profiling function "fp".
-void func_do_profile(ufunc_T *fp)
-{
- int len = fp->uf_lines.ga_len;
-
- if (!fp->uf_prof_initialized) {
- if (len == 0) {
- len = 1; // avoid getting error for allocating zero bytes
- }
- fp->uf_tm_count = 0;
- fp->uf_tm_self = profile_zero();
- fp->uf_tm_total = profile_zero();
-
- if (fp->uf_tml_count == NULL) {
- fp->uf_tml_count = xcalloc((size_t)len, sizeof(int));
- }
-
- if (fp->uf_tml_total == NULL) {
- fp->uf_tml_total = xcalloc((size_t)len, sizeof(proftime_T));
- }
-
- if (fp->uf_tml_self == NULL) {
- fp->uf_tml_self = xcalloc((size_t)len, sizeof(proftime_T));
- }
-
- fp->uf_tml_idx = -1;
- fp->uf_prof_initialized = true;
- }
-
- fp->uf_profiling = TRUE;
-}
-
-/// Dump the profiling results for all functions in file "fd".
-void func_dump_profile(FILE *fd)
-{
- hashitem_T *hi;
- int todo;
- ufunc_T *fp;
- ufunc_T **sorttab;
- int st_len = 0;
-
- todo = (int)func_hashtab.ht_used;
- if (todo == 0) {
- return; // nothing to dump
- }
-
- sorttab = xmalloc(sizeof(ufunc_T *) * (size_t)todo);
-
- for (hi = func_hashtab.ht_array; todo > 0; ++hi) {
- if (!HASHITEM_EMPTY(hi)) {
- --todo;
- fp = HI2UF(hi);
- if (fp->uf_prof_initialized) {
- sorttab[st_len++] = fp;
-
- if (fp->uf_name[0] == K_SPECIAL) {
- fprintf(fd, "FUNCTION <SNR>%s()\n", fp->uf_name + 3);
- } else {
- fprintf(fd, "FUNCTION %s()\n", fp->uf_name);
- }
- if (fp->uf_script_ctx.sc_sid != 0) {
- bool should_free;
- const LastSet last_set = (LastSet){
- .script_ctx = fp->uf_script_ctx,
- .channel_id = 0,
- };
- char *p = (char *)get_scriptname(last_set, &should_free);
- fprintf(fd, " Defined: %s:%" PRIdLINENR "\n",
- p, fp->uf_script_ctx.sc_lnum);
- if (should_free) {
- xfree(p);
- }
- }
- if (fp->uf_tm_count == 1) {
- fprintf(fd, "Called 1 time\n");
- } else {
- fprintf(fd, "Called %d times\n", fp->uf_tm_count);
- }
- fprintf(fd, "Total time: %s\n", profile_msg(fp->uf_tm_total));
- fprintf(fd, " Self time: %s\n", profile_msg(fp->uf_tm_self));
- fprintf(fd, "\n");
- fprintf(fd, "count total (s) self (s)\n");
-
- for (int i = 0; i < fp->uf_lines.ga_len; ++i) {
- if (FUNCLINE(fp, i) == NULL) {
- continue;
- }
- prof_func_line(fd, fp->uf_tml_count[i],
- &fp->uf_tml_total[i], &fp->uf_tml_self[i], TRUE);
- fprintf(fd, "%s\n", FUNCLINE(fp, i));
- }
- fprintf(fd, "\n");
- }
- }
- }
-
- if (st_len > 0) {
- qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
- prof_total_cmp);
- prof_sort_list(fd, sorttab, st_len, "TOTAL", FALSE);
- qsort((void *)sorttab, (size_t)st_len, sizeof(ufunc_T *),
- prof_self_cmp);
- prof_sort_list(fd, sorttab, st_len, "SELF", TRUE);
- }
-
- xfree(sorttab);
-}
-
-/// @param prefer_self when equal print only self time
-static void prof_sort_list(FILE *fd, ufunc_T **sorttab, int st_len, char *title, int prefer_self)
-{
- int i;
- ufunc_T *fp;
-
- fprintf(fd, "FUNCTIONS SORTED ON %s TIME\n", title);
- fprintf(fd, "count total (s) self (s) function\n");
- for (i = 0; i < 20 && i < st_len; ++i) {
- fp = sorttab[i];
- prof_func_line(fd, fp->uf_tm_count, &fp->uf_tm_total, &fp->uf_tm_self,
- prefer_self);
- if (fp->uf_name[0] == K_SPECIAL) {
- fprintf(fd, " <SNR>%s()\n", fp->uf_name + 3);
- } else {
- fprintf(fd, " %s()\n", fp->uf_name);
- }
- }
- fprintf(fd, "\n");
-}
-
-/// Print the count and times for one function or function line.
-///
-/// @param prefer_self when equal print only self time
-static void prof_func_line(FILE *fd, int count, proftime_T *total, proftime_T *self,
- int prefer_self)
-{
- if (count > 0) {
- fprintf(fd, "%5d ", count);
- if (prefer_self && profile_equal(*total, *self)) {
- fprintf(fd, " ");
- } else {
- fprintf(fd, "%s ", profile_msg(*total));
- }
- if (!prefer_self && profile_equal(*total, *self)) {
- fprintf(fd, " ");
- } else {
- fprintf(fd, "%s ", profile_msg(*self));
- }
- } else {
- fprintf(fd, " ");
- }
-}
-
-/// Compare function for total time sorting.
-static int prof_total_cmp(const void *s1, const void *s2)
-{
- ufunc_T *p1 = *(ufunc_T **)s1;
- ufunc_T *p2 = *(ufunc_T **)s2;
- return profile_cmp(p1->uf_tm_total, p2->uf_tm_total);
-}
-
-/// Compare function for self time sorting.
-static int prof_self_cmp(const void *s1, const void *s2)
-{
- ufunc_T *p1 = *(ufunc_T **)s1;
- ufunc_T *p2 = *(ufunc_T **)s2;
- return profile_cmp(p1->uf_tm_self, p2->uf_tm_self);
-}
-
/// Return the autoload script name for a function or variable name
/// Caller must make sure that "name" contains AUTOLOAD_CHAR.
///
@@ -8182,61 +7849,6 @@ bool script_autoload(const char *const name, const size_t name_len, const bool r
return ret;
}
-/// Called when starting to read a function line.
-/// "sourcing_lnum" must be correct!
-/// When skipping lines it may not actually be executed, but we won't find out
-/// until later and we need to store the time now.
-void func_line_start(void *cookie)
-{
- funccall_T *fcp = (funccall_T *)cookie;
- ufunc_T *fp = fcp->func;
-
- if (fp->uf_profiling && sourcing_lnum >= 1
- && sourcing_lnum <= fp->uf_lines.ga_len) {
- fp->uf_tml_idx = sourcing_lnum - 1;
- // Skip continuation lines.
- while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL) {
- fp->uf_tml_idx--;
- }
- fp->uf_tml_execed = false;
- fp->uf_tml_start = profile_start();
- fp->uf_tml_children = profile_zero();
- fp->uf_tml_wait = profile_get_wait();
- }
-}
-
-/// Called when actually executing a function line.
-void func_line_exec(void *cookie)
-{
- funccall_T *fcp = (funccall_T *)cookie;
- ufunc_T *fp = fcp->func;
-
- if (fp->uf_profiling && fp->uf_tml_idx >= 0) {
- fp->uf_tml_execed = TRUE;
- }
-}
-
-/// Called when done with a function line.
-void func_line_end(void *cookie)
-{
- funccall_T *fcp = (funccall_T *)cookie;
- ufunc_T *fp = fcp->func;
-
- if (fp->uf_profiling && fp->uf_tml_idx >= 0) {
- if (fp->uf_tml_execed) {
- ++fp->uf_tml_count[fp->uf_tml_idx];
- fp->uf_tml_start = profile_end(fp->uf_tml_start);
- fp->uf_tml_start = profile_sub_wait(fp->uf_tml_wait, fp->uf_tml_start);
- fp->uf_tml_total[fp->uf_tml_idx] =
- profile_add(fp->uf_tml_total[fp->uf_tml_idx], fp->uf_tml_start);
- fp->uf_tml_self[fp->uf_tml_idx] =
- profile_self(fp->uf_tml_self[fp->uf_tml_idx], fp->uf_tml_start,
- fp->uf_tml_children);
- }
- fp->uf_tml_idx = -1;
- }
-}
-
static var_flavour_T var_flavour(char *varname)
FUNC_ATTR_PURE
{
@@ -8324,11 +7936,9 @@ int store_session_globals(FILE *fd)
}
if ((fprintf(fd, "let %s = %c%s%c",
this_var->di_key,
- ((this_var->di_tv.v_type == VAR_STRING) ? '"'
- : ' '),
+ ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' '),
p,
- ((this_var->di_tv.v_type == VAR_STRING) ? '"'
- : ' ')) < 0)
+ ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' ')) < 0)
|| put_eol(fd) == FAIL) {
xfree(p);
return FAIL;
@@ -8370,7 +7980,7 @@ void option_last_set_msg(LastSet last_set)
{
if (last_set.script_ctx.sc_sid != 0) {
bool should_free;
- char *p = (char *)get_scriptname(last_set, &should_free);
+ char *p = get_scriptname(last_set, &should_free);
verbose_enter();
msg_puts(_("\n\tLast set from "));
msg_puts(p);
@@ -8413,10 +8023,8 @@ int modify_fname(char *src, bool tilde_file, size_t *usedlen, char **fnamep, cha
size_t *fnamelen)
{
int valid = 0;
- char *tail;
char *s, *p, *pbuf;
char dirname[MAXPATHL];
- int c;
bool has_fullname = false;
bool has_homerelative = false;
@@ -8469,7 +8077,7 @@ repeat:
}
// Append a path separator to a directory.
- if (os_isdir((char_u *)(*fnamep))) {
+ if (os_isdir(*fnamep)) {
// Make room for one or two extra characters.
*fnamep = xstrnsave(*fnamep, STRLEN(*fnamep) + 2);
xfree(*bufp); // free any allocated file name
@@ -8478,6 +8086,8 @@ repeat:
}
}
+ int c;
+
// ":." - path relative to the current directory
// ":~" - path relative to the home directory
// ":8" - shortname path - postponed till after
@@ -8533,6 +8143,7 @@ repeat:
// Only replace it when it starts with '~'
if (*dirname == '~') {
s = xstrdup(dirname);
+ assert(s != NULL); // suppress clang "Argument with 'nonnull' attribute passed null"
*fnamep = s;
xfree(*bufp);
*bufp = s;
@@ -8543,7 +8154,7 @@ repeat:
}
}
- tail = path_tail(*fnamep);
+ char *tail = path_tail(*fnamep);
*fnamelen = STRLEN(*fnamep);
// ":h" - head, remove "/file_name", can be repeated
@@ -8551,7 +8162,7 @@ repeat:
while (src[*usedlen] == ':' && src[*usedlen + 1] == 'h') {
valid |= VALID_HEAD;
*usedlen += 2;
- s = (char *)get_past_head((char_u *)(*fnamep));
+ s = get_past_head(*fnamep);
while (tail > s && after_pathsep(s, tail)) {
MB_PTR_BACK(*fnamep, tail);
}
@@ -8584,10 +8195,9 @@ repeat:
// ":r" - root, without extension, can be repeated
while (src[*usedlen] == ':'
&& (src[*usedlen + 1] == 'e' || src[*usedlen + 1] == 'r')) {
- /* find a '.' in the tail:
- * - for second :e: before the current fname
- * - otherwise: The last '.'
- */
+ // find a '.' in the tail:
+ // - for second :e: before the current fname
+ // - otherwise: The last '.'
const bool is_second_e = *fnamep > tail;
if (src[*usedlen + 1] == 'e' && is_second_e) {
s = (*fnamep) - 2;
@@ -8638,18 +8248,16 @@ repeat:
if (src[*usedlen] == ':'
&& (src[*usedlen + 1] == 's'
|| (src[*usedlen + 1] == 'g' && src[*usedlen + 2] == 's'))) {
- int sep;
- char *flags;
- int didit = false;
+ bool didit = false;
- flags = "";
+ char *flags = "";
s = src + *usedlen + 2;
if (src[*usedlen + 1] == 'g') {
flags = "g";
s++;
}
- sep = (char_u)(*s++);
+ int sep = (char_u)(*s++);
if (sep) {
// find end of pattern
p = vim_strchr(s, sep);
@@ -8667,7 +8275,7 @@ repeat:
*fnamelen = STRLEN(s);
xfree(*bufp);
*bufp = s;
- didit = TRUE;
+ didit = true;
xfree(sub);
xfree(str);
}
@@ -8708,26 +8316,22 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
{
int sublen;
regmatch_T regmatch;
- int do_all;
- char *tail;
- char *end;
garray_T ga;
- char *save_cpo;
char *zero_width = NULL;
// Make 'cpoptions' empty, so that the 'l' flag doesn't work here
- save_cpo = p_cpo;
- p_cpo = (char *)empty_option;
+ char *save_cpo = p_cpo;
+ p_cpo = empty_option;
ga_init(&ga, 1, 200);
- do_all = (flags[0] == 'g');
+ int do_all = (flags[0] == 'g');
regmatch.rm_ic = p_ic;
regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
if (regmatch.regprog != NULL) {
- tail = str;
- end = str + STRLEN(str);
+ char *tail = str;
+ char *end = str + STRLEN(str);
while (vim_regexec_nl(&regmatch, (char_u *)str, (colnr_T)(tail - str))) {
// Skip empty match except for first match.
if (regmatch.startp[0] == regmatch.endp[0]) {
@@ -8777,11 +8381,16 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, char *flags
char *ret = xstrdup(ga.ga_data == NULL ? str : ga.ga_data);
ga_clear(&ga);
- if ((char_u *)p_cpo == empty_option) {
+ if (p_cpo == empty_option) {
p_cpo = save_cpo;
} else {
// Darn, evaluating {sub} expression or {expr} changed the value.
- free_string_option((char_u *)save_cpo);
+ // If it's still empty it was changed and restored, need to restore in
+ // the complicated way.
+ if (*p_cpo == NUL) {
+ set_option_value_give_err("cpo", 0L, save_cpo, 0);
+ }
+ free_string_option(save_cpo);
}
return ret;
@@ -8868,8 +8477,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, boo
struct caller_scope saved_provider_caller_scope = provider_caller_scope;
provider_caller_scope = (struct caller_scope) {
.script_ctx = current_sctx,
- .sourcing_name = sourcing_name,
- .sourcing_lnum = sourcing_lnum,
+ .es_entry = ((estack_T *)exestack.ga_data)[exestack.ga_len - 1],
.autocmd_fname = autocmd_fname,
.autocmd_match = autocmd_match,
.autocmd_bufnr = autocmd_bufnr,
@@ -8968,8 +8576,8 @@ bool eval_has_provider(const char *feat)
/// Writes "<sourcing_name>:<sourcing_lnum>" to `buf[bufsize]`.
void eval_fmt_source_name_line(char *buf, size_t bufsize)
{
- if (sourcing_name) {
- snprintf(buf, bufsize, "%s:%" PRIdLINENR, sourcing_name, sourcing_lnum);
+ if (SOURCING_NAME) {
+ snprintf(buf, bufsize, "%s:%" PRIdLINENR, SOURCING_NAME, SOURCING_LNUM);
} else {
snprintf(buf, bufsize, "?");
}
@@ -8988,7 +8596,7 @@ void ex_checkhealth(exarg_T *eap)
if (vimruntime_env == NULL) {
emsg(_("E5009: $VIMRUNTIME is empty or unset"));
} else {
- bool rtp_ok = NULL != strstr((char *)p_rtp, vimruntime_env);
+ bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
if (rtp_ok) {
semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
} else {
@@ -9011,8 +8619,6 @@ void invoke_prompt_callback(void)
{
typval_T rettv;
typval_T argv[2];
- char *text;
- char *prompt;
linenr_T lnum = curbuf->b_ml.ml_line_count;
// Add a new line for the prompt before invoking the callback, so that
@@ -9024,8 +8630,8 @@ void invoke_prompt_callback(void)
if (curbuf->b_prompt_callback.type == kCallbackNone) {
return;
}
- text = (char *)ml_get(lnum);
- prompt = (char *)prompt_text();
+ char *text = (char *)ml_get(lnum);
+ char *prompt = (char *)prompt_text();
if (STRLEN(text) >= STRLEN(prompt)) {
text += STRLEN(prompt);
}