aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/eval.c
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-02-22 17:07:47 -0500
committerJames McCoy <jamessan@jamessan.com>2017-02-22 19:23:20 -0500
commitbc76ce2c4f26a1ceabc8ba7dc8d5ff3378648a40 (patch)
treeb5b295f6a593f77f6995e6d6478afdf37043b11d /src/nvim/eval.c
parent10c9ecc2117a69d2b83e983082f53c1779547035 (diff)
parentddab4661f7acad985096138b0c29a2b7e569022a (diff)
downloadrneovim-bc76ce2c4f26a1ceabc8ba7dc8d5ff3378648a40.tar.gz
rneovim-bc76ce2c4f26a1ceabc8ba7dc8d5ff3378648a40.tar.bz2
rneovim-bc76ce2c4f26a1ceabc8ba7dc8d5ff3378648a40.zip
Merge remote-tracking branch 'origin/master' into lambda
Diffstat (limited to 'src/nvim/eval.c')
-rw-r--r--src/nvim/eval.c1356
1 files changed, 739 insertions, 617 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 49ce9f3144..57c2368523 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -1422,13 +1422,13 @@ void ex_let(exarg_T *eap)
if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
&& expr[1] == '=')) {
// ":let" without "=": list variables
- if (*arg == '[')
+ if (*arg == '[') {
EMSG(_(e_invarg));
- else if (!ends_excmd(*arg))
- /* ":let var1 var2" */
- arg = list_arg_vars(eap, arg, &first);
- else if (!eap->skip) {
- /* ":let" */
+ } else if (!ends_excmd(*arg)) {
+ // ":let var1 var2"
+ arg = (char_u *)list_arg_vars(eap, (const char *)arg, &first);
+ } else if (!eap->skip) {
+ // ":let"
list_glob_vars(&first);
list_buf_vars(&first);
list_win_vars(&first);
@@ -1612,7 +1612,8 @@ static char_u *skip_var_one(char_u *arg)
* List variables for hashtab "ht" with prefix "prefix".
* If "empty" is TRUE also list NULL strings as empty strings.
*/
-static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first)
+static void list_hashtable_vars(hashtab_T *ht, const char *prefix, int empty,
+ int *first)
{
hashitem_T *hi;
dictitem_T *di;
@@ -1621,11 +1622,12 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f
todo = (int)ht->ht_used;
for (hi = ht->ht_array; todo > 0 && !got_int; ++hi) {
if (!HASHITEM_EMPTY(hi)) {
- --todo;
+ todo--;
di = HI2DI(hi);
if (empty || di->di_tv.v_type != VAR_STRING
- || di->di_tv.vval.v_string != NULL)
+ || di->di_tv.vval.v_string != NULL) {
list_one_var(di, prefix, first);
+ }
}
}
}
@@ -1635,7 +1637,7 @@ static void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *f
*/
static void list_glob_vars(int *first)
{
- list_hashtable_vars(&globvarht, (char_u *)"", TRUE, first);
+ list_hashtable_vars(&globvarht, "", true, first);
}
/*
@@ -1643,14 +1645,13 @@ static void list_glob_vars(int *first)
*/
static void list_buf_vars(int *first)
{
- char_u numbuf[NUMBUFLEN];
+ char numbuf[NUMBUFLEN];
- list_hashtable_vars(&curbuf->b_vars->dv_hashtab, (char_u *)"b:",
- TRUE, first);
+ list_hashtable_vars(&curbuf->b_vars->dv_hashtab, "b:", true, first);
- sprintf((char *)numbuf, "%" PRId64, (int64_t)curbuf->b_changedtick);
- list_one_var_a((char_u *)"b:", (char_u *)"changedtick", VAR_NUMBER,
- numbuf, first);
+ snprintf(numbuf, sizeof(numbuf), "%d", curbuf->b_changedtick);
+ list_one_var_a("b:", "changedtick", sizeof("changedtick") - 1, VAR_NUMBER,
+ numbuf, first);
}
/*
@@ -1658,8 +1659,7 @@ static void list_buf_vars(int *first)
*/
static void list_win_vars(int *first)
{
- list_hashtable_vars(&curwin->w_vars->dv_hashtab,
- (char_u *)"w:", TRUE, first);
+ list_hashtable_vars(&curwin->w_vars->dv_hashtab, "w:", true, first);
}
/*
@@ -1667,8 +1667,7 @@ static void list_win_vars(int *first)
*/
static void list_tab_vars(int *first)
{
- list_hashtable_vars(&curtab->tp_vars->dv_hashtab,
- (char_u *)"t:", TRUE, first);
+ list_hashtable_vars(&curtab->tp_vars->dv_hashtab, "t:", true, first);
}
/*
@@ -1676,7 +1675,7 @@ static void list_tab_vars(int *first)
*/
static void list_vim_vars(int *first)
{
- list_hashtable_vars(&vimvarht, (char_u *)"v:", FALSE, first);
+ list_hashtable_vars(&vimvarht, "v:", false, first);
}
/*
@@ -1684,9 +1683,9 @@ static void list_vim_vars(int *first)
*/
static void list_script_vars(int *first)
{
- if (current_SID > 0 && current_SID <= ga_scripts.ga_len)
- list_hashtable_vars(&SCRIPT_VARS(current_SID),
- (char_u *)"s:", FALSE, first);
+ if (current_SID > 0 && current_SID <= ga_scripts.ga_len) {
+ list_hashtable_vars(&SCRIPT_VARS(current_SID), "s:", false, first);
+ }
}
/*
@@ -1694,36 +1693,37 @@ static void list_script_vars(int *first)
*/
static void list_func_vars(int *first)
{
- if (current_funccal != NULL)
- list_hashtable_vars(&current_funccal->l_vars.dv_hashtab,
- (char_u *)"l:", FALSE, first);
+ if (current_funccal != NULL) {
+ list_hashtable_vars(&current_funccal->l_vars.dv_hashtab, "l:", false,
+ first);
+ }
}
/*
* List variables in "arg".
*/
-static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
+static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
{
int error = FALSE;
int len;
- char_u *name;
- char_u *name_start;
- char_u *arg_subsc;
- char_u *tofree;
+ const char *name;
+ const char *name_start;
typval_T tv;
while (!ends_excmd(*arg) && !got_int) {
if (error || eap->skip) {
- arg = find_name_end(arg, NULL, NULL, FNE_INCL_BR | FNE_CHECK_START);
+ arg = (const char *)find_name_end((char_u *)arg, NULL, NULL,
+ FNE_INCL_BR | FNE_CHECK_START);
if (!ascii_iswhite(*arg) && !ends_excmd(*arg)) {
emsg_severe = TRUE;
EMSG(_(e_trailing));
break;
}
} else {
- /* get_name_len() takes care of expanding curly braces */
+ // get_name_len() takes care of expanding curly braces
name_start = name = arg;
- len = get_name_len(&arg, &tofree, TRUE, TRUE);
+ char *tofree;
+ len = get_name_len(&arg, &tofree, true, true);
if (len <= 0) {
/* This is mainly to keep test 49 working: when expanding
* curly braces fails overrule the exception error message. */
@@ -1737,14 +1737,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
if (tofree != NULL) {
name = tofree;
}
- if (get_var_tv(name, len, &tv, NULL, true, false) == FAIL) {
+ if (get_var_tv((const char *)name, len, &tv, NULL, true, false)
+ == FAIL) {
error = true;
} else {
// handle d.key, l[idx], f(expr)
- arg_subsc = arg;
- if (handle_subscript(&arg, &tv, TRUE, TRUE) == FAIL)
- error = TRUE;
- else {
+ const char *const arg_subsc = arg;
+ if (handle_subscript(&arg, &tv, true, true) == FAIL) {
+ error = true;
+ } else {
if (arg == arg_subsc && len == 2 && name[1] == ':') {
switch (*name) {
case 'g': list_glob_vars(first); break;
@@ -1758,17 +1759,15 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
EMSG2(_("E738: Can't list variables for %s"), name);
}
} else {
- int c;
-
- char_u *s = (char_u *) encode_tv2echo(&tv, NULL);
- c = *arg;
- *arg = NUL;
- list_one_var_a((char_u *)"",
- arg == arg_subsc ? name : name_start,
- tv.v_type,
- s == NULL ? (char_u *)"" : s,
- first);
- *arg = c;
+ char *const s = encode_tv2echo(&tv, NULL);
+ const char *const used_name = (arg == arg_subsc
+ ? name
+ : name_start);
+ const ptrdiff_t name_size = (used_name == tofree
+ ? (ptrdiff_t)strlen(used_name)
+ : (arg - used_name));
+ list_one_var_a("", used_name, name_size,
+ tv.v_type, s == NULL ? "" : s, first);
xfree(s);
}
clear_tv(&tv);
@@ -1779,7 +1778,7 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first)
xfree(tofree);
}
- arg = skipwhite(arg);
+ arg = (const char *)skipwhite((const char_u *)arg);
}
return arg;
@@ -1799,9 +1798,7 @@ ex_let_one (
char_u *op /* "+", "-", "." or NULL*/
)
{
- int c1;
char_u *name;
- char_u *p;
char_u *arg_end = NULL;
int len;
int opt_flags;
@@ -1815,18 +1812,18 @@ ex_let_one (
++arg;
name = arg;
len = get_env_len(&arg);
- if (len == 0)
+ if (len == 0) {
EMSG2(_(e_invarg2), name - 1);
- else {
- if (op != NULL && (*op == '+' || *op == '-'))
+ } else {
+ if (op != NULL && (*op == '+' || *op == '-')) {
EMSG2(_(e_letwrong), op);
- else if (endchars != NULL
- && vim_strchr(endchars, *skipwhite(arg)) == NULL)
+ } else if (endchars != NULL
+ && vim_strchr(endchars, *skipwhite(arg)) == NULL) {
EMSG(_(e_letunexp));
- else if (!check_secure()) {
- c1 = name[len];
+ } else if (!check_secure()) {
+ const char_u c1 = name[len];
name[len] = NUL;
- p = get_tv_string_chk(tv);
+ char_u *p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
char *s = vim_getenv((char *)name);
@@ -1850,43 +1847,41 @@ ex_let_one (
xfree(tofree);
}
}
- }
- /*
- * ":let &option = expr": Set option value.
- * ":let &l:option = expr": Set local option value.
- * ":let &g:option = expr": Set global option value.
- */
- else if (*arg == '&') {
- /* Find the end of the name. */
- p = find_option_end(&arg, &opt_flags);
- if (p == NULL || (endchars != NULL
- && vim_strchr(endchars, *skipwhite(p)) == NULL))
+ // ":let &option = expr": Set option value.
+ // ":let &l:option = expr": Set local option value.
+ // ":let &g:option = expr": Set global option value.
+ } else if (*arg == '&') {
+ // Find the end of the name.
+ char *const p = (char *)find_option_end((const char **)&arg, &opt_flags);
+ if (p == NULL
+ || (endchars != NULL
+ && vim_strchr(endchars, *skipwhite((const char_u *)p)) == NULL)) {
EMSG(_(e_letunexp));
- else {
+ } else {
long n;
int opt_type;
long numval;
- char_u *stringval = NULL;
- char_u *s;
+ char_u *stringval = NULL;
+ char_u *s;
- c1 = *p;
+ const char c1 = *p;
*p = NUL;
n = get_tv_number(tv);
s = get_tv_string_chk(tv); /* != NULL if number or string */
if (s != NULL && op != NULL && *op != '=') {
- opt_type = get_option_value(arg, &numval,
- &stringval, opt_flags);
+ opt_type = get_option_value(arg, &numval, &stringval, opt_flags);
if ((opt_type == 1 && *op == '.')
- || (opt_type == 0 && *op != '.'))
+ || (opt_type == 0 && *op != '.')) {
EMSG2(_(e_letwrong), op);
- else {
- if (opt_type == 1) { /* number */
- if (*op == '+')
+ } else {
+ if (opt_type == 1) { // number
+ if (*op == '+') {
n = numval + n;
- else
+ } else {
n = numval - n;
- } else if (opt_type == 0 && stringval != NULL) { /* string */
+ }
+ } else if (opt_type == 0 && stringval != NULL) { // string
s = concat_str(stringval, s);
xfree(stringval);
stringval = s;
@@ -1895,7 +1890,7 @@ ex_let_one (
}
if (s != NULL) {
set_option_value(arg, n, s, opt_flags);
- arg_end = p;
+ arg_end = (char_u *)p;
}
*p = c1;
xfree(stringval);
@@ -1915,7 +1910,7 @@ ex_let_one (
char_u *ptofree = NULL;
char_u *s;
- p = get_tv_string_chk(tv);
+ char_u *p = get_tv_string_chk(tv);
if (p != NULL && op != NULL && *op == '.') {
s = get_reg_contents(*arg == '@' ? '"' : *arg, kGRegExprSrc);
if (s != NULL) {
@@ -1937,7 +1932,7 @@ ex_let_one (
else if (eval_isnamec1(*arg) || *arg == '{') {
lval_T lv;
- p = get_lval(arg, tv, &lv, FALSE, FALSE, 0, FNE_CHECK_START);
+ char_u *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)
EMSG(_(e_letunexp));
@@ -2047,9 +2042,11 @@ get_lval (
cc = *p;
*p = NUL;
- v = find_var(lp->ll_name, &ht, flags & GLV_NO_AUTOLOAD);
- if (v == NULL && !quiet)
+ v = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), &ht,
+ flags & GLV_NO_AUTOLOAD);
+ if (v == NULL && !quiet) {
EMSG2(_(e_undefvar), lp->ll_name);
+ }
*p = cc;
if (v == NULL)
return NULL;
@@ -2309,7 +2306,7 @@ static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, ch
// handle +=, -= and .=
di = NULL;
- if (get_var_tv(lp->ll_name, (int)STRLEN(lp->ll_name),
+ if (get_var_tv((const char *)lp->ll_name, (int)STRLEN(lp->ll_name),
&tv, &di, true, false) == OK) {
if ((di == NULL
|| (!var_check_ro(di->di_flags, lp->ll_name, false)
@@ -2785,7 +2782,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 = deref_func_name(tofree, &len,
+ name = deref_func_name((const char *)tofree, &len,
partial != NULL ? NULL : &partial, false);
/* Skip white space to allow ":call func ()". Not good, but required for
@@ -2823,9 +2820,10 @@ void ex_call(exarg_T *eap)
break;
}
- /* Handle a function returning a Funcref, Dictionary or List. */
- if (handle_subscript(&arg, &rettv, !eap->skip, TRUE) == FAIL) {
- failed = TRUE;
+ // Handle a function returning a Funcref, Dictionary or List.
+ if (handle_subscript((const char **)&arg, &rettv, !eap->skip, true)
+ == FAIL) {
+ failed = true;
break;
}
@@ -3014,7 +3012,8 @@ int do_unlet(char_u *name, int forceit)
dict_T *d;
dictitem_T *di;
dict_T *dict;
- ht = find_var_ht_dict(name, &varname, &dict);
+ ht = find_var_ht_dict((const char *)name, STRLEN(name),
+ (const char **)&varname, &dict);
if (ht != NULL && *varname != NUL) {
if (ht == &globvarht) {
@@ -3025,7 +3024,7 @@ int do_unlet(char_u *name, int forceit)
} else if (ht == &compat_hashtab) {
d = &vimvardict;
} else {
- di = find_var_in_ht(ht, *name, (char_u *)"", false);
+ di = find_var_in_ht(ht, *name, "", 0, false);
d = di->di_tv.vval.v_dict;
}
if (d == NULL) {
@@ -3034,7 +3033,7 @@ int do_unlet(char_u *name, int forceit)
}
hi = hash_find(ht, varname);
if (HASHITEM_EMPTY(hi)) {
- hi = find_hi_in_scoped_ht(name, &ht);
+ hi = find_hi_in_scoped_ht((const char *)name, &ht);
}
if (hi != NULL && !HASHITEM_EMPTY(hi)) {
di = HI2DI(hi);
@@ -3088,18 +3087,19 @@ static int do_lock_var(lval_T *lp, char_u *name_end, int deep, int lock)
cc = *name_end;
*name_end = NUL;
- /* Normal name or expanded name. */
- if (check_changedtick(lp->ll_name))
+ // Normal name or expanded name.
+ if (check_changedtick(lp->ll_name)) {
ret = FAIL;
- else {
- di = find_var(lp->ll_name, NULL, TRUE);
- if (di == NULL)
+ } else {
+ di = find_var((const char *)lp->ll_name, STRLEN(lp->ll_name), NULL, true);
+ if (di == NULL) {
ret = FAIL;
- else {
- if (lock)
+ } else {
+ if (lock) {
di->di_flags |= DI_FLAGS_LOCK;
- else
+ } else {
di->di_flags &= ~DI_FLAGS_LOCK;
+ }
item_lock(&di->di_tv, deep, lock);
}
}
@@ -4280,9 +4280,10 @@ static int eval7(
break;
// Option value: &name
- case '&': ret = get_option_tv(arg, rettv, evaluate);
+ case '&': {
+ ret = get_option_tv((const char **)arg, rettv, evaluate);
break;
-
+ }
// Environment variable: $VAR.
case '$': ret = get_env_tv(arg, rettv, evaluate);
break;
@@ -4318,7 +4319,7 @@ static int eval7(
// Must be a variable or function name.
// Can also be a curly-braces kind of name: {expr}.
s = *arg;
- len = get_name_len(arg, &alias, evaluate, true);
+ len = get_name_len((const char **)arg, (char **)&alias, evaluate, true);
if (alias != NULL) {
s = alias;
}
@@ -4330,12 +4331,12 @@ static int eval7(
partial_T *partial;
if (!evaluate) {
- check_vars(s, len);
+ check_vars((const char *)s, len);
}
// If "s" is the name of a variable of type VAR_FUNC
// use its contents.
- s = deref_func_name(s, &len, &partial, !evaluate);
+ s = deref_func_name((const char *)s, &len, &partial, !evaluate);
// Invoke the function.
ret = get_func_tv(s, len, rettv, arg,
@@ -4360,9 +4361,9 @@ static int eval7(
ret = FAIL;
}
} else if (evaluate) {
- ret = get_var_tv(s, len, rettv, NULL, true, false);
+ ret = get_var_tv((const char *)s, len, rettv, NULL, true, false);
} else {
- check_vars(s, len);
+ check_vars((const char *)s, len);
ret = OK;
}
}
@@ -4374,7 +4375,7 @@ static int eval7(
// Handle following '[', '(' and '.' for expr[expr], expr.name,
// expr(expr).
if (ret == OK) {
- ret = handle_subscript(arg, rettv, evaluate, true);
+ ret = handle_subscript((const char **)arg, rettv, evaluate, true);
}
// Apply logical NOT and unary '-', from right to left, ignore '+'.
@@ -4675,35 +4676,32 @@ eval_index (
return OK;
}
-/*
- * Get an option value.
- * "arg" points to the '&' or '+' before the option name.
- * "arg" is advanced to character after the option name.
- * Return OK or FAIL.
- */
-static int
-get_option_tv (
- char_u **arg,
- typval_T *rettv, /* when NULL, only check if option exists */
- int evaluate
-)
+/// Get an option value
+///
+/// @param[in,out] arg Points to the '&' or '+' before the option name. Is
+/// advanced to the character after the option name.
+/// @param[out] rettv Location where result is saved.
+/// @param[in] evaluate If not true, rettv is not populated.
+///
+/// @return OK or FAIL.
+static int get_option_tv(const char **const arg, typval_T *const rettv,
+ const bool evaluate)
+ FUNC_ATTR_NONNULL_ARG(1)
{
- char_u *option_end;
long numval;
char_u *stringval;
int opt_type;
int c;
- int working = (**arg == '+'); /* has("+option") */
+ bool working = (**arg == '+'); // has("+option")
int ret = OK;
int opt_flags;
- /*
- * Isolate the option name and find its value.
- */
- option_end = find_option_end(arg, &opt_flags);
+ // Isolate the option name and find its value.
+ char *option_end = (char *)find_option_end(arg, &opt_flags);
if (option_end == NULL) {
- if (rettv != NULL)
+ if (rettv != NULL) {
EMSG2(_("E112: Option name missing: %s"), *arg);
+ }
return FAIL;
}
@@ -4714,8 +4712,8 @@ get_option_tv (
c = *option_end;
*option_end = NUL;
- opt_type = get_option_value(*arg, &numval,
- rettv == NULL ? NULL : &stringval, opt_flags);
+ opt_type = get_option_value((char_u *)(*arg), &numval,
+ rettv == NULL ? NULL : &stringval, opt_flags);
if (opt_type == -3) { /* invalid name */
if (rettv != NULL)
@@ -7266,53 +7264,55 @@ static VimLFuncDef *find_internal_func(const char *const name)
return find_internal_func_gperf(name, len);
}
-/// Check if "name" is a variable of type VAR_FUNC. If so, return the function
-/// name it contains, otherwise return "name".
-/// If "partialp" is not NULL, and "name" is of type VAR_PARTIAL also set
-/// "partialp".
-static char_u *deref_func_name(
- char_u *name, int *lenp,
- partial_T **partialp, bool no_autoload
-)
+/// Return name of the function corresponding to `name`
+///
+/// If `name` points to variable that is either a function or partial then
+/// corresponding function name is returned. Otherwise it returns `name` itself.
+///
+/// @param[in] name Function name to check.
+/// @param[in,out] lenp Location where length of the returned name is stored.
+/// Must be set to the length of the `name` argument.
+/// @param[out] partialp Location where partial will be stored if found
+/// function appears to be a partial. May be NULL if this
+/// is not needed.
+/// @param[in] no_autoload If true, do not source autoload scripts if function
+/// was not found.
+///
+/// @return name of the function.
+static char_u *deref_func_name(const char *name, int *lenp,
+ partial_T **const partialp, bool no_autoload)
+ FUNC_ATTR_NONNULL_ARG(1, 2)
{
- dictitem_T *v;
- int cc;
- char_u *s;
-
if (partialp != NULL) {
*partialp = NULL;
}
- cc = name[*lenp];
- name[*lenp] = NUL;
- v = find_var(name, NULL, no_autoload);
- name[*lenp] = cc;
+ dictitem_T *const v = find_var(name, (size_t)(*lenp), NULL, no_autoload);
if (v != NULL && v->di_tv.v_type == VAR_FUNC) {
- if (v->di_tv.vval.v_string == NULL) {
+ if (v->di_tv.vval.v_string == NULL) { // just in case
*lenp = 0;
- return (char_u *)""; /* just in case */
+ return (char_u *)"";
}
- s = v->di_tv.vval.v_string;
- *lenp = (int)STRLEN(s);
- return s;
+ *lenp = (int)STRLEN(v->di_tv.vval.v_string);
+ return v->di_tv.vval.v_string;
}
if (v != NULL && v->di_tv.v_type == VAR_PARTIAL) {
- partial_T *pt = v->di_tv.vval.v_partial;
+ partial_T *const pt = v->di_tv.vval.v_partial;
- if (pt == NULL) {
+ if (pt == NULL) { // just in case
*lenp = 0;
- return (char_u *)""; // just in case
+ return (char_u *)"";
}
if (partialp != NULL) {
*partialp = pt;
}
- s = partial_name(pt);
+ char_u *s = partial_name(pt);
*lenp = (int)STRLEN(s);
return s;
}
- return name;
+ return (char_u *)name;
}
/*
@@ -7394,34 +7394,49 @@ get_func_tv (
return ret;
}
-#define ERROR_UNKNOWN 0
-#define ERROR_TOOMANY 1
-#define ERROR_TOOFEW 2
-#define ERROR_SCRIPT 3
-#define ERROR_DICT 4
-#define ERROR_NONE 5
-#define ERROR_OTHER 6
-#define ERROR_BOTH 7
-#define ERROR_DELETED 8
+typedef enum {
+ ERROR_UNKNOWN = 0,
+ ERROR_TOOMANY,
+ ERROR_TOOFEW,
+ ERROR_SCRIPT,
+ ERROR_DICT,
+ ERROR_NONE,
+ ERROR_OTHER,
+ ERROR_BOTH,
+ ERROR_DELETED,
+} FnameTransError;
+
#define FLEN_FIXED 40
-/// In a script change <SID>name() and s:name() to K_SNR 123_name().
-/// Change <SNR>123_name() to K_SNR 123_name().
-/// Use "fname_buf[FLEN_FIXED + 1]" when it fits, otherwise allocate memory
-/// (slow).
-static char_u *
-fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) {
- int llen;
+/// In a script transform script-local names into actually used names
+///
+/// Transforms "<SID>" and "s:" prefixes to `K_SNR {N}` (e.g. K_SNR "123") and
+/// "<SNR>" prefix to `K_SNR`. Uses `fname_buf` buffer that is supposed to have
+/// #FLEN_FIXED + 1 length when it fits, otherwise it allocates memory.
+///
+/// @param[in] name Name to transform.
+/// @param fname_buf Buffer to save resulting function name to, if it fits.
+/// Must have at least #FLEN_FIXED + 1 length.
+/// @param[out] tofree Location where pointer to an allocated memory is saved
+/// in case result does not fit into fname_buf.
+/// @param[out] error Location where error type is saved, @see
+/// FnameTransError.
+///
+/// @return transformed name: either `fname_buf` or a pointer to an allocated
+/// memory.
+static char_u *fname_trans_sid(const char_u *const name,
+ char_u *const fname_buf,
+ char_u **const tofree, int *const error)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
char_u *fname;
- int i;
-
- llen = eval_fname_script(name);
+ const int llen = eval_fname_script((const char *)name);
if (llen > 0) {
fname_buf[0] = K_SPECIAL;
fname_buf[1] = KS_EXTRA;
fname_buf[2] = (int)KE_SNR;
- i = 3;
- if (eval_fname_sid(name)) { // "<SID>" or "s:"
+ int i = 3;
+ if (eval_fname_sid((const char *)name)) { // "<SID>" or "s:"
if (current_SID <= 0) {
*error = ERROR_SCRIPT;
} else {
@@ -7444,7 +7459,7 @@ fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error) {
}
}
} else {
- fname = name;
+ fname = (char_u *)name;
}
return fname;
@@ -7564,7 +7579,7 @@ call_func(
rettv->vval.v_number = 0;
error = ERROR_UNKNOWN;
- if (!builtin_function(rfname, -1)) {
+ if (!builtin_function((const char *)rfname, -1)) {
// User defined function.
if (partial != NULL && partial->pt_func != NULL) {
fp = partial->pt_func;
@@ -7579,9 +7594,10 @@ call_func(
/* executed an autocommand, search for the function again */
fp = find_func(rfname);
}
- /* Try loading a package. */
- if (fp == NULL && script_autoload(rfname, TRUE) && !aborting()) {
- /* loaded a package, search for the function again */
+ // 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(rfname);
}
@@ -7609,7 +7625,7 @@ call_func(
}
} else {
// Find the function name in the table, call its implementation.
- VimLFuncDef *const fdef = find_internal_func((char *)fname);
+ VimLFuncDef *const fdef = find_internal_func((const char *)fname);
if (fdef != NULL) {
if (argcount < fdef->min_argc) {
error = ERROR_TOOFEW;
@@ -8292,17 +8308,17 @@ static buf_T *get_buf_tv(typval_T *tv, int curtab_only)
*/
static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
-
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
rettv->v_type = VAR_STRING;
- if (buf != NULL && buf->b_fname != NULL)
- rettv->vval.v_string = vim_strsave(buf->b_fname);
- else
- rettv->vval.v_string = NULL;
- --emsg_off;
+ rettv->vval.v_string = NULL;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ return;
+ }
+ emsg_off++;
+ const buf_T *const buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
+ if (buf != NULL && buf->b_fname != NULL) {
+ rettv->vval.v_string = (char_u *)xstrdup((char *)buf->b_fname);
+ }
}
/*
@@ -8310,36 +8326,36 @@ static void f_bufname(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_bufnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- int error = FALSE;
- char_u *name;
+ int error = false;
+ char_u *name;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
- --emsg_off;
+ rettv->vval.v_number = -1;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ return;
+ }
+ emsg_off++;
+ const buf_T *buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
- /* If the buffer isn't found and the second argument is not zero create a
- * new buffer. */
+ // If the buffer isn't found and the second argument is not zero create a
+ // new buffer.
if (buf == NULL
&& argvars[1].v_type != VAR_UNKNOWN
&& get_tv_number_chk(&argvars[1], &error) != 0
&& !error
&& (name = get_tv_string_chk(&argvars[0])) != NULL
- && !error)
+ && !error) {
buf = buflist_new(name, NULL, (linenr_T)1, 0);
+ }
- if (buf != NULL)
+ if (buf != NULL) {
rettv->vval.v_number = buf->b_fnum;
- else
- rettv->vval.v_number = -1;
+ }
}
static void buf_win_common(typval_T *argvars, typval_T *rettv, bool get_nr)
{
- int error = false;
- (void)get_tv_number_chk(&argvars[0], &error); // issue errmsg if type error
- if (error) { // the argument has an invalid type
+ if (!tv_check_str_or_nr(&argvars[0])) {
rettv->vval.v_number = -1;
return;
}
@@ -8383,14 +8399,13 @@ static void f_bufwinnr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_byte2line(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- long boff = 0;
-
- boff = get_tv_number(&argvars[0]) - 1; /* boff gets -1 on type error */
- if (boff < 0)
+ long boff = get_tv_number(&argvars[0]) - 1;
+ if (boff < 0) {
rettv->vval.v_number = -1;
- else
- rettv->vval.v_number = ml_find_line_or_offset(curbuf,
- (linenr_T)0, &boff);
+ } else {
+ rettv->vval.v_number = (varnumber_T)ml_find_line_or_offset(curbuf, 0,
+ &boff);
+ }
}
static void byteidx(typval_T *argvars, typval_T *rettv, int comp)
@@ -9250,54 +9265,55 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_exists(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- char_u *p;
- char_u *name;
- int n = FALSE;
+ int n = false;
int len = 0;
- p = get_tv_string(&argvars[0]);
- if (*p == '$') { /* environment variable */
- /* first try "normal" environment variables (fast) */
- if (os_getenv((char *)(p + 1)) != NULL)
- n = TRUE;
- else {
- /* try expanding things like $VIM and ${HOME} */
- p = expand_env_save(p);
- if (p != NULL && *p != '$')
- n = TRUE;
+ char *p = (char *)get_tv_string(&argvars[0]);
+ if (*p == '$') { // Environment variable.
+ // First try "normal" environment variables (fast).
+ if (os_getenv(p + 1) != NULL) {
+ n = true;
+ } else {
+ // Try expanding things like $VIM and ${HOME}.
+ p = (char *)expand_env_save((char_u *)p);
+ if (p != NULL && *p != '$') {
+ n = true;
+ }
xfree(p);
}
- } else if (*p == '&' || *p == '+') { // option
- n = (get_option_tv(&p, NULL, true) == OK);
- if (*skipwhite(p) != NUL) {
- n = false; // trailing garbage
+ } else if (*p == '&' || *p == '+') { // Option.
+ n = (get_option_tv((const char **)&p, NULL, true) == OK);
+ if (*skipwhite((const char_u *)p) != NUL) {
+ n = false; // Trailing garbage.
}
- } else if (*p == '*') { // internal or user defined function
+ } else if (*p == '*') { // Internal or user defined function.
n = function_exists(p + 1, false);
} else if (*p == ':') {
n = cmd_exists(p + 1);
} else if (*p == '#') {
- if (p[1] == '#')
+ if (p[1] == '#') {
n = autocmd_supported(p + 2);
- else
+ } else {
n = au_exists(p + 1);
- } else { /* internal variable */
- char_u *tofree;
+ }
+ } else { // Internal variable.
typval_T tv;
- /* get_name_len() takes care of expanding curly braces */
- name = p;
- len = get_name_len(&p, &tofree, TRUE, FALSE);
+ // get_name_len() takes care of expanding curly braces
+ const char *name = p;
+ char *tofree;
+ len = get_name_len((const char **)&p, &tofree, true, false);
if (len > 0) {
if (tofree != NULL) {
name = tofree;
}
n = (get_var_tv(name, len, &tv, NULL, false, true) == OK);
if (n) {
- /* handle d.key, l[idx], f(expr) */
- n = (handle_subscript(&p, &tv, TRUE, FALSE) == OK);
- if (n)
+ // Handle d.key, l[idx], f(expr).
+ n = (handle_subscript((const char **)&p, &tv, true, false) == OK);
+ if (n) {
clear_tv(&tv);
+ }
}
}
if (*p != NUL)
@@ -10055,7 +10071,7 @@ static void common_function(typval_T *argvars, typval_T *rettv,
// Don't check an autoload name for existence here.
} else if (trans_name != NULL
&& (is_funcref ? find_func(trans_name) == NULL
- : !translated_function_exists(trans_name))) {
+ : !translated_function_exists((const char *)trans_name))) {
EMSG2(_("E700: Unknown function: %s"), s);
} else {
int dict_idx = 0;
@@ -10451,20 +10467,22 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
linenr_T lnum;
linenr_T end;
- buf_T *buf;
+ buf_T *buf = NULL;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
- --emsg_off;
+ if (tv_check_str_or_nr(&argvars[0])) {
+ emsg_off++;
+ buf = get_buf_tv(&argvars[0], false);
+ emsg_off--;
+ }
lnum = get_tv_lnum_buf(&argvars[1], buf);
- if (argvars[2].v_type == VAR_UNKNOWN)
+ if (argvars[2].v_type == VAR_UNKNOWN) {
end = lnum;
- else
+ } else {
end = get_tv_lnum_buf(&argvars[2], buf);
+ }
- get_buffer_lines(buf, lnum, end, TRUE, rettv);
+ get_buffer_lines(buf, lnum, end, true, rettv);
}
/*
@@ -10472,26 +10490,25 @@ static void f_getbufline(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- buf_T *save_curbuf;
- char_u *varname;
- dictitem_T *v;
- int done = FALSE;
-
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- varname = get_tv_string_chk(&argvars[1]);
- ++emsg_off;
- buf = get_buf_tv(&argvars[0], FALSE);
+ bool done = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ if (!tv_check_str_or_nr(&argvars[0])) {
+ goto f_getbufvar_end;
+ }
+
+ const char *varname = (const char *)get_tv_string_chk(&argvars[1]);
+ emsg_off++;
+ buf_T *const buf = get_buf_tv(&argvars[0], false);
+
if (buf != NULL && varname != NULL) {
- /* set curbuf to be our buf, temporarily */
- save_curbuf = curbuf;
+ // set curbuf to be our buf, temporarily
+ buf_T *const save_curbuf = curbuf;
curbuf = buf;
- if (*varname == '&') { // buffer-local-option
+ if (*varname == '&') { // buffer-local-option
if (varname[1] == NUL) {
// get all buffer-local options in a dict
dict_T *opts = get_winbuf_options(true);
@@ -10511,25 +10528,26 @@ static void f_getbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
rettv->vval.v_number = curbuf->b_changedtick;
done = true;
} else {
- /* Look up the variable. */
- /* Let getbufvar({nr}, "") return the "b:" dictionary. */
- v = find_var_in_ht(&curbuf->b_vars->dv_hashtab,
- 'b', varname, FALSE);
+ // Look up the variable.
+ // Let getbufvar({nr}, "") return the "b:" dictionary.
+ dictitem_T *const v = find_var_in_ht(&curbuf->b_vars->dv_hashtab, 'b',
+ varname, strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
- done = TRUE;
+ done = true;
}
}
- /* restore previous notion of curbuf */
+ // restore previous notion of curbuf
curbuf = save_curbuf;
}
+ emsg_off--;
- if (!done && argvars[2].v_type != VAR_UNKNOWN)
- /* use the default value */
+f_getbufvar_end:
+ if (!done && argvars[2].v_type != VAR_UNKNOWN) {
+ // use the default value
copy_tv(&argvars[2], rettv);
-
- --emsg_off;
+ }
}
/*
@@ -11297,13 +11315,12 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
win_T *oldcurwin;
tabpage_T *tp, *oldtabpage;
dictitem_T *v;
- char_u *varname;
bool done = false;
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
- varname = get_tv_string_chk(&argvars[1]);
+ const char *const varname = (const char *)get_tv_string_chk(&argvars[1]);
tp = find_tabpage((int)get_tv_number_chk(&argvars[0], NULL));
if (tp != NULL && varname != NULL) {
// Set tp to be our tabpage, temporarily. Also set the window to the
@@ -11312,7 +11329,8 @@ static void f_gettabvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (switch_win(&oldcurwin, &oldtabpage, window, tp, true) == OK) {
// look up the variable
// Let gettabvar({nr}, "") return the "t:" dictionary.
- v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't', varname, FALSE);
+ v = find_var_in_ht(&tp->tp_vars->dv_hashtab, 't',
+ varname, strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
done = true;
@@ -11491,7 +11509,6 @@ getwinvar (
)
{
win_T *win, *oldcurwin;
- char_u *varname;
dictitem_T *v;
tabpage_T *tp = NULL;
tabpage_T *oldtabpage = NULL;
@@ -11502,12 +11519,13 @@ getwinvar (
else
tp = curtab;
win = find_win_by_nr(&argvars[off], tp);
- varname = get_tv_string_chk(&argvars[off + 1]);
- ++emsg_off;
+ const char *varname = (const char *)get_tv_string_chk(
+ &argvars[off + 1]);
rettv->v_type = VAR_STRING;
rettv->vval.v_string = NULL;
+ emsg_off++;
if (win != NULL && varname != NULL) {
// Set curwin to be our win, temporarily. Also set the tabpage,
// otherwise the window is not valid. Only do this when needed,
@@ -11533,7 +11551,8 @@ getwinvar (
} else {
// Look up the variable.
// Let getwinvar({nr}, "") return the "w:" dictionary.
- v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname, FALSE);
+ v = find_var_in_ht(&win->w_vars->dv_hashtab, 'w', varname,
+ strlen(varname), false);
if (v != NULL) {
copy_tv(&v->di_tv, rettv);
done = true;
@@ -11546,12 +11565,12 @@ getwinvar (
restore_win(oldcurwin, oldtabpage, true);
}
}
+ emsg_off--;
- if (!done && argvars[off + 2].v_type != VAR_UNKNOWN)
- /* use the default return value */
+ if (!done && argvars[off + 2].v_type != VAR_UNKNOWN) {
+ // use the default return value
copy_tv(&argvars[off + 2], rettv);
-
- --emsg_off;
+ }
}
/*
@@ -11821,6 +11840,10 @@ static void f_has(typval_T *argvars, typval_T *rettv, FunPtr fptr)
#endif
} else if (STRICMP(name, "syntax_items") == 0) {
n = syntax_present(curwin);
+#ifdef UNIX
+ } else if (STRICMP(name, "unnamedplus") == 0) {
+ n = eval_has_provider("clipboard");
+#endif
}
}
@@ -12217,8 +12240,8 @@ static void get_user_input(typval_T *argvars, typval_T *rettv, int inputdialog)
*p = NUL;
msg_start();
msg_clr_eos();
- msg_puts_attr(prompt, echo_attr);
- msg_didout = FALSE;
+ msg_puts_attr((const char *)prompt, echo_attr);
+ msg_didout = false;
msg_starthere();
*p = c;
}
@@ -12310,7 +12333,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, FunPtr fptr)
msg_clr_eos();
for (li = argvars[0].vval.v_list->lv_first; li != NULL; li = li->li_next) {
- msg_puts(get_tv_string(&li->li_tv));
+ msg_puts((const char *)get_tv_string(&li->li_tv));
msg_putchar('\n');
}
@@ -12435,10 +12458,11 @@ static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
EMSG(_(e_trailing));
else {
if (lv.ll_tv == NULL) {
- if (check_changedtick(lv.ll_name))
- rettv->vval.v_number = 1; /* always locked */
- else {
- di = find_var(lv.ll_name, NULL, TRUE);
+ if (check_changedtick(lv.ll_name)) {
+ rettv->vval.v_number = 1; // Always locked.
+ } else {
+ di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL,
+ true);
if (di != NULL) {
/* Consider a variable locked when:
* 1. the variable itself is locked
@@ -13279,9 +13303,9 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
rettv_dict_alloc(rettv);
if (rhs != NULL) {
// Return a dictionary.
- char_u *lhs = str2special_save(mp->m_keys, TRUE);
- char_u *mapmode = map_mode_to_chars(mp->m_mode);
- dict_T *dict = rettv->vval.v_dict;
+ char_u *lhs = str2special_save(mp->m_keys, true);
+ char *const mapmode = map_mode_to_chars(mp->m_mode);
+ dict_T *dict = rettv->vval.v_dict;
dict_add_nr_str(dict, "lhs", 0L, lhs);
dict_add_nr_str(dict, "rhs", 0L, mp->m_orig_str);
@@ -13291,7 +13315,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
dict_add_nr_str(dict, "sid", (long)mp->m_script_ID, NULL);
dict_add_nr_str(dict, "buffer", (long)buffer_local, NULL);
dict_add_nr_str(dict, "nowait", mp->m_nowait ? 1L : 0L, NULL);
- dict_add_nr_str(dict, "mode", 0L, mapmode);
+ dict_add_nr_str(dict, "mode", 0L, (char_u *)mapmode);
xfree(lhs);
xfree(mapmode);
@@ -15508,44 +15532,45 @@ static void f_serverstop(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_setbufvar(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
- buf_T *buf;
- char_u *varname, *bufvarname;
- typval_T *varp;
char_u nbuf[NUMBUFLEN];
- if (check_restricted() || check_secure())
+ if (check_restricted()
+ || check_secure()
+ || !tv_check_str_or_nr(&argvars[0])) {
return;
- (void)get_tv_number(&argvars[0]); /* issue errmsg if type error */
- varname = get_tv_string_chk(&argvars[1]);
- buf = get_buf_tv(&argvars[0], FALSE);
- varp = &argvars[2];
+ }
+ const char *varname = (const char *)get_tv_string_chk(&argvars[1]);
+ buf_T *const buf = get_buf_tv(&argvars[0], false);
+ typval_T *varp = &argvars[2];
if (buf != NULL && varname != NULL && varp != NULL) {
if (*varname == '&') {
long numval;
- char_u *strval;
+ char_u *strval;
int error = false;
- aco_save_T aco;
+ aco_save_T aco;
// set curbuf to be our buf, temporarily
aucmd_prepbuf(&aco, buf);
- ++varname;
+ varname++;
numval = get_tv_number_chk(varp, &error);
strval = get_tv_string_buf_chk(varp, nbuf);
- if (!error && strval != NULL)
- set_option_value(varname, numval, strval, OPT_LOCAL);
+ if (!error && strval != NULL) {
+ set_option_value((char_u *)varname, numval, strval, OPT_LOCAL);
+ }
// reset notion of buffer
aucmd_restbuf(&aco);
} else {
buf_T *save_curbuf = curbuf;
- bufvarname = xmalloc(STRLEN(varname) + 3);
+ const size_t varname_len = STRLEN(varname);
+ char_u *const bufvarname = xmalloc(STRLEN(varname) + 3);
curbuf = buf;
- STRCPY(bufvarname, "b:");
- STRCPY(bufvarname + 2, varname);
- set_var(bufvarname, varp, TRUE);
+ memcpy(bufvarname, "b:", 2);
+ memcpy(bufvarname + 2, varname, varname_len + 1);
+ set_var(bufvarname, varp, true);
xfree(bufvarname);
curbuf = save_curbuf;
}
@@ -17232,8 +17257,8 @@ static void f_synIDattr(typval_T *argvars, typval_T *rettv, FunPtr fptr)
p = highlight_has_attr(id, HL_ITALIC, modec);
break;
- case 'n': /* name */
- p = get_highlight_name(NULL, id - 1);
+ case 'n': // name
+ p = (char_u *)get_highlight_name(NULL, id - 1);
break;
case 'r': /* reverse */
@@ -18802,11 +18827,12 @@ static int get_env_len(char_u **arg)
// Get the length of the name of a function or internal variable.
// "arg" is advanced to the first non-white character after the name.
// Return 0 if something is wrong.
-static int get_id_len(char_u **arg) {
- char_u *p;
+static int get_id_len(const char **const arg)
+{
int len;
// Find the end of the name.
+ const char *p;
for (p = *arg; eval_isnamec(*p); p++) {
if (*p == ':') {
// "s:" is start of "s:var", but "n:" is not and can be used in
@@ -18823,7 +18849,7 @@ static int get_id_len(char_u **arg) {
}
len = (int)(p - *arg);
- *arg = skipwhite(p);
+ *arg = (const char *)skipwhite((const char_u *)p);
return len;
}
@@ -18837,18 +18863,20 @@ static int get_id_len(char_u **arg) {
* If the name contains 'magic' {}'s, expand them and return the
* expanded name in an allocated string via 'alias' - caller must free.
*/
-static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
+static int get_name_len(const char **const arg,
+ char **alias,
+ int evaluate,
+ int verbose)
{
int len;
- char_u *p;
char_u *expr_start;
char_u *expr_end;
*alias = NULL; /* default to no alias */
- if ((*arg)[0] == K_SPECIAL && (*arg)[1] == KS_EXTRA
- && (*arg)[2] == (int)KE_SNR) {
- /* hard coded <SNR>, already translated */
+ if ((*arg)[0] == (char)K_SPECIAL && (*arg)[1] == (char)KS_EXTRA
+ && (*arg)[2] == (char)KE_SNR) {
+ // Hard coded <SNR>, already translated.
*arg += 3;
return get_id_len(arg) + 3;
}
@@ -18861,14 +18889,14 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
/*
* Find the end of the name; check for {} construction.
*/
- p = find_name_end(*arg, &expr_start, &expr_end,
- len > 0 ? 0 : FNE_CHECK_START);
+ const char *p = (const char *)find_name_end((char_u *)(*arg),
+ &expr_start,
+ &expr_end,
+ len > 0 ? 0 : FNE_CHECK_START);
if (expr_start != NULL) {
- char_u *temp_string;
-
if (!evaluate) {
len += (int)(p - *arg);
- *arg = skipwhite(p);
+ *arg = (const char *)skipwhite((const char_u *)p);
return len;
}
@@ -18876,11 +18904,13 @@ static int get_name_len(char_u **arg, char_u **alias, int evaluate, int verbose)
* Include any <SID> etc in the expanded string:
* Thus the -len here.
*/
- temp_string = make_expanded_name(*arg - len, expr_start, expr_end, p);
- if (temp_string == NULL)
+ char_u *temp_string = make_expanded_name((char_u *)(*arg) - len, expr_start,
+ expr_end, (char_u *)p);
+ if (temp_string == NULL) {
return -1;
- *alias = temp_string;
- *arg = skipwhite(p);
+ }
+ *alias = (char *)temp_string;
+ *arg = (const char *)skipwhite((const char_u *)p);
return (int)STRLEN(temp_string);
}
@@ -19294,9 +19324,8 @@ char_u *set_cmdarg(exarg_T *eap, char_u *oldarg)
* Get the value of internal variable "name".
* Return OK or FAIL.
*/
-static int
-get_var_tv (
- char_u *name,
+static int get_var_tv(
+ const char *name,
int len, // length of "name"
typval_T *rettv, // NULL when only checking existence
dictitem_T **dip, // non-NULL when typval's dict item is needed
@@ -19308,25 +19337,16 @@ get_var_tv (
typval_T *tv = NULL;
typval_T atv;
dictitem_T *v;
- int cc;
- /* truncate the name, so that we can use strcmp() */
- cc = name[len];
- name[len] = NUL;
-
- /*
- * Check for "b:changedtick".
- */
- if (STRCMP(name, "b:changedtick") == 0) {
+ // Check for "b:changedtick".
+ if (sizeof("b:changedtick") - 1 == len
+ && STRNCMP(name, "b:changedtick", len) == 0) {
atv.v_type = VAR_NUMBER;
atv.vval.v_number = curbuf->b_changedtick;
tv = &atv;
- }
- /*
- * Check for user-defined variables.
- */
- else {
- v = find_var(name, NULL, no_autoload);
+ } else {
+ // Check for user-defined variables.
+ v = find_var(name, (size_t)len, NULL, no_autoload);
if (v != NULL) {
tv = &v->di_tv;
if (dip != NULL) {
@@ -19336,41 +19356,33 @@ get_var_tv (
}
if (tv == NULL) {
- if (rettv != NULL && verbose)
- EMSG2(_(e_undefvar), name);
+ if (rettv != NULL && verbose) {
+ emsgf(_("E121: Undefined variable: %.*s"), len, name);
+ }
ret = FAIL;
- } else if (rettv != NULL)
+ } else if (rettv != NULL) {
copy_tv(tv, rettv);
-
- name[len] = cc;
+ }
return ret;
}
/// Check if variable "name[len]" is a local variable or an argument.
/// If so, "*eval_lavars_used" is set to TRUE.
-static void check_vars(char_u *name, int len)
+static void check_vars(const char *name, size_t len)
{
- int cc;
- char_u *varname;
- hashtab_T *ht;
-
if (eval_lavars_used == NULL) {
return;
}
- // truncate the name, so that we can use strcmp()
- cc = name[len];
- name[len] = NUL;
+ const char *varname;
+ hashtab_T *ht = find_var_ht(name, len, &varname);
- ht = find_var_ht(name, &varname);
if (ht == get_funccal_local_ht() || ht == get_funccal_args_ht()) {
- if (find_var(name, NULL, true) != NULL) {
+ if (find_var(name, len, NULL, true) != NULL) {
*eval_lavars_used = true;
}
}
-
- name[len] = cc;
}
/// Handle expr[expr], expr[expr:expr] subscript and .name lookup.
@@ -19378,7 +19390,7 @@ static void check_vars(char_u *name, int len)
/// Can all be combined: dict.func(expr)[idx]['func'](expr)
static int
handle_subscript(
- char_u **arg,
+ const char **const arg,
typval_T *rettv,
int evaluate, /* do more than finding the end */
int verbose /* give error messages */
@@ -19413,7 +19425,7 @@ handle_subscript(
} else {
s = (char_u *)"";
}
- ret = get_func_tv(s, (int)STRLEN(s), rettv, arg,
+ ret = get_func_tv(s, (int)STRLEN(s), rettv, (char_u **)arg,
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
&len, evaluate, pt, selfdict);
@@ -19440,7 +19452,7 @@ handle_subscript(
++selfdict->dv_refcount;
} else
selfdict = NULL;
- if (eval_index(arg, rettv, evaluate, verbose) == FAIL) {
+ if (eval_index((char_u **)arg, rettv, evaluate, verbose) == FAIL) {
clear_tv(rettv);
ret = FAIL;
}
@@ -19813,6 +19825,53 @@ static void init_tv(typval_T *varp)
memset(varp, 0, sizeof(typval_T));
}
+/// Check that given value is a number or string
+///
+/// Error messages are compatible with get_tv_number() previously used for the
+/// same purpose in buf*() functions. Special values are not accepted (previous
+/// behaviour: silently fail to find buffer).
+///
+/// @param[in] tv Value to check.
+///
+/// @return true if everything is OK, false otherwise.
+bool tv_check_str_or_nr(const typval_T *const tv)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
+{
+ switch (tv->v_type) {
+ case VAR_NUMBER:
+ case VAR_STRING: {
+ return true;
+ }
+ case VAR_FLOAT: {
+ EMSG(_("E805: Expected a Number or a String, Float found"));
+ return false;
+ }
+ case VAR_PARTIAL:
+ case VAR_FUNC: {
+ EMSG(_("E703: Expected a Number or a String, Funcref found"));
+ return false;
+ }
+ case VAR_LIST: {
+ EMSG(_("E745: Expected a Number or a String, List found"));
+ return false;
+ }
+ case VAR_DICT: {
+ EMSG(_("E728: Expected a Number or a String, Dictionary found"));
+ return false;
+ }
+ case VAR_SPECIAL: {
+ EMSG(_("E5300: Expected a Number or a String"));
+ return false;
+ }
+ case VAR_UNKNOWN: {
+ EMSG2(_(e_intern2), "tv_check_str_or_nr(UNKNOWN)");
+ return false;
+ }
+ }
+ assert(false);
+ return false;
+}
+
/*
* Get the number value of a variable.
* If it is a String variable, uses vim_str2nr().
@@ -20017,67 +20076,82 @@ char_u *get_tv_string_buf_chk(const typval_T *varp, char_u *buf)
* When "htp" is not NULL we are writing to the variable, set "htp" to the
* hashtab_T used.
*/
-static dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload)
+static dictitem_T *find_var(const char *const name, const size_t name_len,
+ hashtab_T **htp, int no_autoload)
{
- char_u *varname;
- hashtab_T *ht;
- dictitem_T *ret = NULL;
-
- ht = find_var_ht(name, &varname);
+ const char *varname;
+ hashtab_T *ht = find_var_ht(name, name_len, &varname);
if (htp != NULL) {
*htp = ht;
}
if (ht == NULL) {
return NULL;
}
- ret = find_var_in_ht(ht, *name, varname, no_autoload || htp != NULL);
+ dictitem_T *ret = find_var_in_ht(ht, *name,
+ varname, name_len - (size_t)(varname - name),
+ no_autoload || htp != NULL);
if (ret != NULL) {
return ret;
}
// Search in parent scope for lambda
- return find_var_in_scoped_ht(name, no_autoload || htp != NULL);
+ return find_var_in_scoped_ht(name, name_len, no_autoload || htp != NULL);
}
-/// Find variable "varname" in hashtab "ht" with name "htname".
-/// Returns NULL if not found.
-dictitem_T *find_var_in_ht(hashtab_T *ht, int htname,
- char_u *varname, bool no_autoload)
+/// Find variable in hashtab
+///
+/// @param[in] ht Hashtab to find variable in.
+/// @param[in] htname Hashtab name (first character).
+/// @param[in] varname Variable name.
+/// @param[in] varname_len Variable name length.
+/// @param[in] no_autoload If true then autoload scripts will not be sourced
+/// if autoload variable was not found.
+///
+/// @return pointer to the dictionary item with the found variable or NULL if it
+/// was not found.
+static dictitem_T *find_var_in_ht(hashtab_T *const ht,
+ int htname,
+ const char *const varname,
+ const size_t varname_len,
+ int no_autoload)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
hashitem_T *hi;
- if (*varname == NUL) {
- /* Must be something like "s:", otherwise "ht" would be NULL. */
+ if (varname_len == 0) {
+ // Must be something like "s:", otherwise "ht" would be NULL.
switch (htname) {
- case 's': return &SCRIPT_SV(current_SID)->sv_var;
- case 'g': return &globvars_var;
- case 'v': return &vimvars_var;
- case 'b': return &curbuf->b_bufvar;
- case 'w': return &curwin->w_winvar;
- case 't': return &curtab->tp_winvar;
- case 'l': return current_funccal == NULL
- ? NULL : &current_funccal->l_vars_var;
- case 'a': return current_funccal == NULL
- ? NULL : &current_funccal->l_avars_var;
+ case 's': return (dictitem_T *)&SCRIPT_SV(current_SID)->sv_var;
+ case 'g': return (dictitem_T *)&globvars_var;
+ case 'v': return (dictitem_T *)&vimvars_var;
+ case 'b': return (dictitem_T *)&curbuf->b_bufvar;
+ case 'w': return (dictitem_T *)&curwin->w_winvar;
+ case 't': return (dictitem_T *)&curtab->tp_winvar;
+ case 'l': return (current_funccal == NULL
+ ? NULL : (dictitem_T *)&current_funccal->l_vars_var);
+ case 'a': return (current_funccal == NULL
+ ? NULL : (dictitem_T *)&current_funccal->l_avars_var);
}
return NULL;
}
- hi = hash_find(ht, varname);
+ 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
- * loaded already, otherwise it would be loaded every time when
- * checking if a function name is a Funcref variable. */
+ // 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
+ // loaded already, otherwise it would be loaded every time when
+ // checking if a function name is a Funcref variable.
if (ht == &globvarht && !no_autoload) {
- /* Note: script_autoload() may make "hi" invalid. It must either
- * be obtained again or not used. */
- if (!script_autoload(varname, FALSE) || aborting())
+ // Note: script_autoload() may make "hi" invalid. It must either
+ // be obtained again or not used.
+ if (!script_autoload(varname, varname_len, false) || aborting()) {
return NULL;
- hi = hash_find(ht, varname);
+ }
+ hi = hash_find_len(ht, varname, varname_len);
}
- if (HASHITEM_EMPTY(hi))
+ if (HASHITEM_EMPTY(hi)) {
return NULL;
+ }
}
return HI2DI(hi);
}
@@ -20103,7 +20177,7 @@ static funccall_T *get_funccal(void)
/// Return the hashtable used for argument in the current funccal.
/// Return NULL if there is no current funccal.
-hashtab_T *get_funccal_args_ht(void)
+static hashtab_T *get_funccal_args_ht(void)
{
if (current_funccal == NULL) {
return NULL;
@@ -20113,7 +20187,7 @@ hashtab_T *get_funccal_args_ht(void)
/// Return the hashtable used for local variables in the current funccal.
/// Return NULL if there is no current funccal.
-hashtab_T *get_funccal_local_ht(void)
+static hashtab_T *get_funccal_local_ht(void)
{
if (current_funccal == NULL) {
return NULL;
@@ -20121,17 +20195,25 @@ hashtab_T *get_funccal_local_ht(void)
return &get_funccal()->l_vars.dv_hashtab;
}
-// Find the dict and hashtable used for a variable name. Set "varname" to the
-// start of name without ':'.
-static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
+/// Find the dict and hashtable used for a variable
+///
+/// @param[in] name Variable name, possibly with scope prefix.
+/// @param[in] name_len Variable name length.
+/// @param[out] varname Will be set to the start of the name without scope
+/// prefix.
+/// @param[out] d Scope dictionary.
+///
+/// @return Scope hashtab, NULL if name is not valid.
+static hashtab_T *find_var_ht_dict(const char *name, const size_t name_len,
+ const char **varname, dict_T **d)
{
- hashitem_T *hi;
+ hashitem_T *hi;
*d = NULL;
- if (name[0] == NUL) {
+ if (name_len == 0) {
return NULL;
}
- if (name[1] != ':') {
+ if (name_len == 1 || (name_len >= 2 && name[1] != ':')) {
// name has implicit scope
if (name[0] == ':' || name[0] == AUTOLOAD_CHAR) {
// The name must not start with a colon or #.
@@ -20140,7 +20222,7 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
*varname = name;
// "version" is "v:version" in all scopes
- hi = hash_find(&compat_hashtab, name);
+ hi = hash_find_len(&compat_hashtab, name, name_len);
if (!HASHITEM_EMPTY(hi)) {
return &compat_hashtab;
}
@@ -20156,26 +20238,27 @@ static hashtab_T *find_var_ht_dict(char_u *name, uint8_t **varname, dict_T **d)
*varname = name + 2;
if (*name == 'g') { // global variable
*d = &globvardict;
- } else if (vim_strchr(name + 2, ':') != NULL
- || vim_strchr(name + 2, AUTOLOAD_CHAR) != NULL) {
+ } else if (name_len > 2
+ && (memchr(name + 2, ':', name_len - 2) != NULL
+ || memchr(name + 2, AUTOLOAD_CHAR, name_len - 2) != NULL)) {
// There must be no ':' or '#' in the rest of the name if g: was not used
return NULL;
}
- if (*name == 'b') { // buffer variable
+ if (*name == 'b') { // buffer variable
*d = curbuf->b_vars;
- } else if (*name == 'w') { // window variable
+ } else if (*name == 'w') { // window variable
*d = curwin->w_vars;
- } else if (*name == 't') { // tab page variable
+ } else if (*name == 't') { // tab page variable
*d = curtab->tp_vars;
- } else if (*name == 'v') { // v: variable
+ } else if (*name == 'v') { // v: variable
*d = &vimvardict;
} else if (*name == 'a' && current_funccal != NULL) { // function argument
*d = &get_funccal()->l_avars;
} else if (*name == 'l' && current_funccal != NULL) { // local variable
*d = &get_funccal()->l_vars;
- } else if (*name == 's' // script variable
- && current_SID > 0 && current_SID <= ga_scripts.ga_len) {
+ } else if (*name == 's' // script variable
+ && current_SID > 0 && current_SID <= ga_scripts.ga_len) {
*d = &SCRIPT_SV(current_SID)->sv_dict;
}
@@ -20183,13 +20266,19 @@ end:
return *d ? &(*d)->dv_hashtab : NULL;
}
-// Find the hashtab used for a variable name.
-// Return NULL if the name is not valid.
-// Set "varname" to the start of name without ':'.
-static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
+/// Find the hashtable used for a variable
+///
+/// @param[in] name Variable name, possibly with scope prefix.
+/// @param[in] name_len Variable name length.
+/// @param[out] varname Will be set to the start of the name without scope
+/// prefix.
+///
+/// @return Scope hashtab, NULL if name is not valid.
+static hashtab_T *find_var_ht(const char *name, const size_t name_len,
+ const char **varname)
{
dict_T *d;
- return find_var_ht_dict(name, varname, &d);
+ return find_var_ht_dict(name, name_len, varname, &d);
}
/*
@@ -20197,13 +20286,14 @@ static hashtab_T *find_var_ht(uint8_t *name, uint8_t **varname)
* Note: see get_tv_string() for how long the pointer remains valid.
* Returns NULL when it doesn't exist.
*/
-char_u *get_var_value(char_u *name)
+char_u *get_var_value(const char *const name)
{
dictitem_T *v;
- v = find_var(name, NULL, FALSE);
- if (v == NULL)
+ v = find_var(name, strlen(name), NULL, false);
+ if (v == NULL) {
return NULL;
+ }
return get_tv_string(&v->di_tv);
}
@@ -20324,28 +20414,27 @@ static void delete_var(hashtab_T *ht, hashitem_T *hi)
/*
* List the value of one internal variable.
*/
-static void list_one_var(dictitem_T *v, char_u *prefix, int *first)
+static void list_one_var(dictitem_T *v, const char *prefix, int *first)
{
- char_u *s = (char_u *) encode_tv2echo(&v->di_tv, NULL);
- list_one_var_a(prefix, v->di_key, v->di_tv.v_type,
- s == NULL ? (char_u *)"" : s, first);
+ char *const s = encode_tv2echo(&v->di_tv, NULL);
+ list_one_var_a(prefix, (const char *)v->di_key, STRLEN(v->di_key),
+ v->di_tv.v_type, (s == NULL ? "" : s), first);
xfree(s);
}
-static void
-list_one_var_a (
- char_u *prefix,
- char_u *name,
- int type,
- char_u *string,
- int *first /* when TRUE clear rest of screen and set to FALSE */
-)
+/// @param[in] name_len Length of the name. May be -1, in this case strlen()
+/// will be used.
+/// @param[in,out] first When true clear rest of screen and set to false.
+static void list_one_var_a(const char *prefix, const char *name,
+ const ptrdiff_t name_len, const int type,
+ const char *string, int *first)
{
- /* don't use msg() or msg_attr() to avoid overwriting "v:statusmsg" */
+ // don't use msg() or msg_attr() to avoid overwriting "v:statusmsg"
msg_start();
msg_puts(prefix);
- if (name != NULL) /* "a:" vars don't have a name stored */
- msg_puts(name);
+ if (name != NULL) { // "a:" vars don't have a name stored
+ msg_puts_attr_len(name, name_len, 0);
+ }
msg_putchar(' ');
msg_advance(22);
if (type == VAR_NUMBER) {
@@ -20363,10 +20452,10 @@ list_one_var_a (
} else
msg_putchar(' ');
- msg_outtrans(string);
+ msg_outtrans((char_u *)string);
if (type == VAR_FUNC || type == VAR_PARTIAL) {
- msg_puts((char_u *)"()");
+ msg_puts("()");
}
if (*first) {
msg_clr_eos();
@@ -20387,12 +20476,14 @@ set_var (
)
{
dictitem_T *v;
- char_u *varname;
hashtab_T *ht;
typval_T oldtv;
dict_T *dict;
- ht = find_var_ht_dict(name, &varname, &dict);
+ const size_t name_len = STRLEN(name);
+ char_u *varname;
+ ht = find_var_ht_dict((const char *)name, name_len, (const char **)&varname,
+ &dict);
bool watched = is_watched(dict);
if (watched) {
@@ -20403,11 +20494,13 @@ set_var (
EMSG2(_(e_illvar), name);
return;
}
- v = find_var_in_ht(ht, 0, varname, true);
+ v = find_var_in_ht(ht, 0,
+ (const char *)varname, name_len - (size_t)(varname - name),
+ true);
// Search in parent scope which is possible to reference from lambda
if (v == NULL) {
- v = find_var_in_scoped_ht(name, true);
+ v = find_var_in_scoped_ht((const char *)name, name_len, true);
}
if ((tv->v_type == VAR_FUNC || tv->v_type == VAR_PARTIAL)
@@ -20538,12 +20631,12 @@ var_check_func_name (
// 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)) {
+ if (new_var && function_exists((const char *)name, false)) {
EMSG2(_("E705: Variable name conflicts with existing function: %s"),
- name);
- return TRUE;
+ name);
+ return true;
}
- return FALSE;
+ return false;
}
/*
@@ -20738,7 +20831,6 @@ void ex_echo(exarg_T *eap)
{
char_u *arg = eap->arg;
typval_T rettv;
- char_u *p;
bool needclr = true;
bool atstart = true;
@@ -20749,19 +20841,20 @@ void ex_echo(exarg_T *eap)
* still need to be cleared. E.g., "echo 22,44". */
need_clr_eos = needclr;
- p = arg;
- if (eval1(&arg, &rettv, !eap->skip) == FAIL) {
- /*
- * Report the invalid expression unless the expression evaluation
- * has been cancelled due to an aborting error, an interrupt, or an
- * exception.
- */
- if (!aborting())
- EMSG2(_(e_invexpr2), p);
- need_clr_eos = FALSE;
- break;
+ {
+ char_u *p = arg;
+ if (eval1(&arg, &rettv, !eap->skip) == FAIL) {
+ // Report the invalid expression unless the expression evaluation
+ // has been cancelled due to an aborting error, an interrupt, or an
+ // exception.
+ if (!aborting()) {
+ EMSG2(_(e_invexpr2), p);
+ }
+ need_clr_eos = false;
+ break;
+ }
+ need_clr_eos = false;
}
- need_clr_eos = FALSE;
if (!eap->skip) {
if (atstart) {
@@ -20775,9 +20868,11 @@ void ex_echo(exarg_T *eap)
msg_sb_eol();
msg_start();
}
- } else if (eap->cmdidx == CMD_echo)
- msg_puts_attr((char_u *)" ", echo_attr);
- char_u *tofree = p = (char_u *) encode_tv2echo(&rettv, NULL);
+ } else if (eap->cmdidx == CMD_echo) {
+ msg_puts_attr(" ", echo_attr);
+ }
+ char *tofree = encode_tv2echo(&rettv, NULL);
+ const char *p = tofree;
if (p != NULL) {
for (; *p != NUL && !got_int; ++p) {
if (*p == '\n' || *p == '\r' || *p == TAB) {
@@ -20786,15 +20881,16 @@ void ex_echo(exarg_T *eap)
msg_clr_eos();
needclr = false;
}
- msg_putchar_attr(*p, echo_attr);
+ msg_putchar_attr((uint8_t)(*p), echo_attr);
} else {
if (has_mbyte) {
- int i = (*mb_ptr2len)(p);
+ int i = (*mb_ptr2len)((const char_u *)p);
- (void)msg_outtrans_len_attr(p, i, echo_attr);
+ (void)msg_outtrans_len_attr((char_u *)p, i, echo_attr);
p += i - 1;
- } else
- (void)msg_outtrans_len_attr(p, 1, echo_attr);
+ } else {
+ (void)msg_outtrans_len_attr((char_u *)p, 1, echo_attr);
+ }
}
}
}
@@ -20908,9 +21004,9 @@ void ex_execute(exarg_T *eap)
* Returns NULL when no option name found. Otherwise pointer to the char
* after the option name.
*/
-static char_u *find_option_end(char_u **arg, int *opt_flags)
+static const char *find_option_end(const char **const arg, int *const opt_flags)
{
- char_u *p = *arg;
+ const char *p = *arg;
++p;
if (*p == 'g' && p[1] == ':') {
@@ -21086,7 +21182,7 @@ void ex_function(exarg_T *eap)
}
if (!got_int) {
msg_putchar('\n');
- msg_puts((char_u *)" endfunction");
+ msg_puts(" endfunction");
}
} else
emsg_funcname(N_("E123: Undefined function: %s"), name);
@@ -21263,7 +21359,7 @@ void ex_function(exarg_T *eap)
if (*p == '!') {
p = skipwhite(p + 1);
}
- p += eval_fname_script(p);
+ p += eval_fname_script((const char *)p);
xfree(trans_function_name(&p, true, 0, NULL, NULL));
if (*skipwhite(p) == '(') {
nesting++;
@@ -21338,7 +21434,7 @@ void ex_function(exarg_T *eap)
* If there are no errors, add the function
*/
if (fudi.fd_dict == NULL) {
- v = find_var(name, &ht, FALSE);
+ 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"),
name);
@@ -21404,7 +21500,7 @@ void ex_function(exarg_T *eap)
/* Check that the autoload name matches the script name. */
int j = FAIL;
if (sourcing_name != NULL) {
- scriptname = autoload_name(name);
+ scriptname = (char_u *)autoload_name((const char *)name, STRLEN(name));
p = vim_strchr(scriptname, '/');
plen = (int)STRLEN(p);
slen = (int)STRLEN(sourcing_name);
@@ -21521,15 +21617,16 @@ trans_function_name(
if ((*pp)[0] == K_SPECIAL && (*pp)[1] == KS_EXTRA
&& (*pp)[2] == (int)KE_SNR) {
*pp += 3;
- len = get_id_len(pp) + 3;
- return vim_strnsave(start, len);
+ len = get_id_len((const char **)pp) + 3;
+ return (char_u *)xmemdupz(start, len);
}
/* A name starting with "<SID>" or "<SNR>" is local to a script. But
* don't skip over "s:", get_lval() needs it for "s:dict.func". */
- lead = eval_fname_script(start);
- if (lead > 2)
+ lead = eval_fname_script((const char *)start);
+ if (lead > 2) {
start += lead;
+ }
/* Note that TFN_ flags use the same values as GLV_ flags. */
end = get_lval(start, NULL, &lv, FALSE, skip, flags,
@@ -21592,14 +21689,15 @@ trans_function_name(
/* 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 = deref_func_name(lv.ll_exp_name, &len, partial,
+ name = deref_func_name((const char *)lv.ll_exp_name, &len, partial,
flags & TFN_NO_AUTOLOAD);
if (name == lv.ll_exp_name) {
name = NULL;
}
} else if (!(flags & TFN_NO_DEREF)) {
len = (int)(end - *pp);
- name = deref_func_name(*pp, &len, partial, flags & TFN_NO_AUTOLOAD);
+ name = deref_func_name((const char *)(*pp), &len, partial,
+ flags & TFN_NO_AUTOLOAD);
if (name == *pp) {
name = NULL;
}
@@ -21644,9 +21742,9 @@ trans_function_name(
lead = 0; /* do nothing */
else if (lead > 0) {
lead = 3;
- if ((lv.ll_exp_name != NULL && eval_fname_sid(lv.ll_exp_name))
- || eval_fname_sid(*pp)) {
- /* It's "s:" or "<SID>" */
+ if ((lv.ll_exp_name != NULL && eval_fname_sid((const char *)lv.ll_exp_name))
+ || eval_fname_sid((const char *)(*pp))) {
+ // It's "s:" or "<SID>".
if (current_SID <= 0) {
EMSG(_(e_usingsid));
goto theend;
@@ -21654,7 +21752,8 @@ trans_function_name(
sprintf((char *)sid_buf, "%" PRId64 "_", (int64_t)current_SID);
lead += (int)STRLEN(sid_buf);
}
- } else if (!(flags & TFN_INT) && builtin_function(lv.ll_name, len)) {
+ } else if (!(flags & TFN_INT)
+ && builtin_function((const char *)lv.ll_name, len)) {
EMSG2(_("E128: Function name must start with a capital or \"s:\": %s"),
start);
goto theend;
@@ -21691,12 +21790,13 @@ theend:
* Return 2 if "p" starts with "s:".
* Return 0 otherwise.
*/
-static int eval_fname_script(char_u *p)
+static int eval_fname_script(const char *const p)
{
// Use mb_stricmp() because in Turkish comparing the "I" may not work with
// the standard library function.
- if (p[0] == '<' && (mb_strnicmp(p + 1, (char_u *)"SID>", 4) == 0
- || mb_strnicmp(p + 1, (char_u *)"SNR>", 4) == 0)) {
+ if (p[0] == '<'
+ && (mb_strnicmp((char_u *)p + 1, (char_u *)"SID>", 4) == 0
+ || mb_strnicmp((char_u *)p + 1, (char_u *)"SNR>", 4) == 0)) {
return 5;
}
if (p[0] == 's' && p[1] == ':') {
@@ -21705,13 +21805,19 @@ static int eval_fname_script(char_u *p)
return 0;
}
-/*
- * Return TRUE if "p" starts with "<SID>" or "s:".
- * Only works if eval_fname_script() returned non-zero for "p"!
- */
-static int eval_fname_sid(char_u *p)
+/// Check whether function name starts with <SID> or s:
+///
+/// Only works for names previously checked by eval_fname_script(), if it
+/// returned non-zero.
+///
+/// @param[in] name Name to check.
+///
+/// @return true if it starts with <SID> or s:, false otherwise.
+static inline bool eval_fname_sid(const char *const name)
+ FUNC_ATTR_PURE FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_ALL
{
- return *p == 's' || TOUPPER_ASC(p[2]) == 'I';
+ return *name == 's' || TOUPPER_ASC(name[2]) == 'I';
}
/*
@@ -21725,33 +21831,36 @@ static void list_func_head(ufunc_T *fp, int indent)
MSG_PUTS("function ");
if (fp->uf_name[0] == K_SPECIAL) {
MSG_PUTS_ATTR("<SNR>", hl_attr(HLF_8));
- msg_puts(fp->uf_name + 3);
- } else
- msg_puts(fp->uf_name);
+ msg_puts((const char *)fp->uf_name + 3);
+ } else {
+ msg_puts((const char *)fp->uf_name);
+ }
msg_putchar('(');
int j;
- for (j = 0; j < fp->uf_args.ga_len; ++j) {
- if (j)
- MSG_PUTS(", ");
- msg_puts(FUNCARG(fp, j));
+ for (j = 0; j < fp->uf_args.ga_len; j++) {
+ if (j) {
+ msg_puts(", ");
+ }
+ msg_puts((const char *)FUNCARG(fp, j));
}
if (fp->uf_varargs) {
- if (j)
- MSG_PUTS(", ");
- MSG_PUTS("...");
+ if (j) {
+ msg_puts(", ");
+ }
+ msg_puts("...");
}
msg_putchar(')');
if (fp->uf_flags & FC_ABORT) {
- MSG_PUTS(" abort");
+ msg_puts(" abort");
}
if (fp->uf_flags & FC_RANGE) {
- MSG_PUTS(" range");
+ msg_puts(" range");
}
if (fp->uf_flags & FC_DICT) {
- MSG_PUTS(" dict");
+ msg_puts(" dict");
}
if (fp->uf_flags & FC_CLOSURE) {
- MSG_PUTS(" closure");
+ msg_puts(" closure");
}
msg_clr_eos();
if (p_verbose > 0)
@@ -21760,7 +21869,7 @@ static void list_func_head(ufunc_T *fp, int indent)
/// Find a function by name, return pointer to it in ufuncs.
/// @return NULL for unknown function.
-ufunc_T *find_func(char_u *name)
+static ufunc_T *find_func(const char_u *name)
{
hashitem_T *hi;
@@ -21832,58 +21941,59 @@ void free_all_functions(void)
#endif
-int translated_function_exists(char_u *name)
+bool translated_function_exists(const char *name)
{
if (builtin_function(name, -1)) {
return find_internal_func((char *)name) != NULL;
}
- return find_func(name) != NULL;
+ return find_func((const char_u *)name) != NULL;
}
-/// Check if a function exists by name
+/// Check whether function with the given name exists
///
-/// @param[in] name The name of the function to check.
-/// @param[in] no_deref If true, do not dereference a Funcref.
+/// @param[in] name Function name.
+/// @param[in] no_deref Whether to dereference a Funcref.
///
-/// @return true if a function "name" exists.
-static int function_exists(char_u *name, bool no_deref)
+/// @return True if it exists, false otherwise.
+static bool function_exists(const char *const name, bool no_deref)
{
- char_u *nm = name;
- char_u *p;
- int n = false;
+ char_u *nm = (char_u *)name;
+ bool n = false;
int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
if (no_deref) {
flag |= TFN_NO_DEREF;
}
- p = trans_function_name(&nm, false, flag, NULL, NULL);
+ char *const p = (char *)trans_function_name(&nm, false, flag, NULL, NULL);
nm = skipwhite(nm);
/* Only accept "funcname", "funcname ", "funcname (..." and
* "funcname(...", not "funcname!...". */
- if (p != NULL && (*nm == NUL || *nm == '('))
+ if (p != NULL && (*nm == NUL || *nm == '(')) {
n = translated_function_exists(p);
+ }
xfree(p);
return n;
}
/// Checks if a builtin function with the given name exists.
///
-/// @param[in] name The name of the builtin function to check.
-/// @param[in] len The length of "name", or -1 for NUL terminated.
+/// @param[in] name name of the builtin function to check.
+/// @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.
-static bool builtin_function(char_u *name, int len)
+static bool builtin_function(const char *name, int len)
{
if (!ASCII_ISLOWER(name[0])) {
- return FALSE;
+ return false;
}
- char_u *p = vim_strchr(name, AUTOLOAD_CHAR);
+ const char *p = (len == -1
+ ? strchr(name, AUTOLOAD_CHAR)
+ : memchr(name, AUTOLOAD_CHAR, (size_t)len));
- return p == NULL
- || (len > 0 && p > name + len);
+ return p == NULL;
}
/*
@@ -22049,44 +22159,45 @@ static int prof_self_cmp(const void *s1, const void *s2)
}
-/*
- * If "name" has a package name try autoloading the script for it.
- * Return TRUE if a package was loaded.
- */
-static int
-script_autoload (
- char_u *name,
- int reload /* load script again when already loaded */
-)
+/// If name has a package name try autoloading the script for it
+///
+/// @param[in] name Variable/function name.
+/// @param[in] name_len Name length.
+/// @param[in] reload If true, load script again when already loaded.
+///
+/// @return true if a package was loaded.
+static bool script_autoload(const char *const name, const size_t name_len,
+ const bool reload)
{
- char_u *p;
- char_u *scriptname, *tofree;
- int ret = FALSE;
- int i;
-
- /* If there is no '#' after name[0] there is no package name. */
- p = vim_strchr(name, AUTOLOAD_CHAR);
- if (p == NULL || p == name)
- return FALSE;
+ // If there is no '#' after name[0] there is no package name.
+ const char *p = memchr(name, AUTOLOAD_CHAR, name_len);
+ if (p == NULL || p == name) {
+ return false;
+ }
- tofree = scriptname = autoload_name(name);
+ bool ret = false;
+ char *tofree = autoload_name(name, name_len);
+ char *scriptname = tofree;
- /* Find the name in the list of previously loaded package names. Skip
- * "autoload/", it's always the same. */
- for (i = 0; i < ga_loaded.ga_len; ++i)
- if (STRCMP(((char_u **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0)
+ // Find the name in the list of previously loaded package names. Skip
+ // "autoload/", it's always the same.
+ int i = 0;
+ for (; i < ga_loaded.ga_len; i++) {
+ if (STRCMP(((char **)ga_loaded.ga_data)[i] + 9, scriptname + 9) == 0) {
break;
- if (!reload && i < ga_loaded.ga_len)
- ret = FALSE; /* was loaded already */
- else {
- /* Remember the name if it wasn't loaded already. */
+ }
+ }
+ if (!reload && i < ga_loaded.ga_len) {
+ ret = false; // Was loaded already.
+ } else {
+ // Remember the name if it wasn't loaded already.
if (i == ga_loaded.ga_len) {
- GA_APPEND(char_u *, &ga_loaded, scriptname);
+ GA_APPEND(char *, &ga_loaded, scriptname);
tofree = NULL;
}
// Try loading the package from $VIMRUNTIME/autoload/<name>.vim
- if (source_runtime(scriptname, 0) == OK) {
+ if (source_runtime((char_u *)scriptname, 0) == OK) {
ret = true;
}
}
@@ -22095,21 +22206,29 @@ script_autoload (
return ret;
}
-/*
- * Return the autoload script name for a function or variable name.
- */
-static char_u *autoload_name(char_u *name)
+/// Return the autoload script name for a function or variable name
+///
+/// @param[in] name Variable/function name.
+/// @param[in] name_len Name length.
+///
+/// @return [allocated] autoload script name.
+static char *autoload_name(const char *const name, const size_t name_len)
+ FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
{
- /* Get the script file name: replace '#' with '/', append ".vim". */
- char_u *scriptname = xmalloc(STRLEN(name) + 14);
- STRCPY(scriptname, "autoload/");
- STRCAT(scriptname, name);
- *vim_strrchr(scriptname, AUTOLOAD_CHAR) = NUL;
- STRCAT(scriptname, ".vim");
-
- char_u *p;
- while ((p = vim_strchr(scriptname, AUTOLOAD_CHAR)) != NULL)
- *p = '/';
+ // Get the script file name: replace '#' with '/', append ".vim".
+ char *const scriptname = xmalloc(name_len + sizeof("autoload/.vim"));
+ memcpy(scriptname, "autoload/", sizeof("autoload/") - 1);
+ memcpy(scriptname + sizeof("autoload/") - 1, name, name_len);
+ size_t auchar_idx = 0;
+ for (size_t i = sizeof("autoload/") - 1;
+ i - sizeof("autoload/") + 1 < name_len;
+ i++) {
+ if (scriptname[i] == AUTOLOAD_CHAR) {
+ scriptname[i] = '/';
+ auchar_idx = i;
+ }
+ }
+ memcpy(scriptname + auchar_idx, ".vim", sizeof(".vim"));
return scriptname;
}
@@ -22582,24 +22701,24 @@ call_user_func(
smsg(_("calling %s"), sourcing_name);
if (p_verbose >= 14) {
- char_u buf[MSG_BUF_LEN];
-
- msg_puts((char_u *)"(");
- for (int i = 0; i < argcount; ++i) {
+ msg_puts("(");
+ for (int i = 0; i < argcount; i++) {
if (i > 0) {
- msg_puts((char_u *)", ");
+ msg_puts(", ");
}
if (argvars[i].v_type == VAR_NUMBER) {
msg_outnum((long)argvars[i].vval.v_number);
} else {
// Do not want errors such as E724 here.
emsg_off++;
- char_u *s = (char_u *) encode_tv2string(&argvars[i], NULL);
- char_u *tofree = s;
+ char *tofree = encode_tv2string(&argvars[i], NULL);
+ char *s = tofree;
emsg_off--;
if (s != NULL) {
- if (vim_strsize(s) > MSG_BUF_CLEN) {
- trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN);
+ if (vim_strsize((char_u *)s) > MSG_BUF_CLEN) {
+ char buf[MSG_BUF_LEN];
+ trunc_string((char_u *)s, (char_u *)buf, MSG_BUF_CLEN,
+ sizeof(buf));
s = buf;
}
msg_puts(s);
@@ -22607,9 +22726,9 @@ call_user_func(
}
}
}
- msg_puts((char_u *)")");
+ msg_puts(")");
}
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -22700,7 +22819,7 @@ call_user_func(
xfree(tofree);
}
}
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -22718,7 +22837,7 @@ call_user_func(
verbose_enter_scroll();
smsg(_("continuing in %s"), sourcing_name);
- msg_puts((char_u *)"\n"); /* don't overwrite this either */
+ msg_puts("\n"); // don't overwrite this either
verbose_leave_scroll();
--no_wait_return;
@@ -23172,23 +23291,23 @@ static var_flavour_T var_flavour(char_u *varname)
}
/// Search hashitem in parent scope.
-hashitem_T *find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
+hashitem_T *find_hi_in_scoped_ht(const char *name, hashtab_T **pht)
{
- funccall_T *old_current_funccal = current_funccal;
- hashtab_T *ht;
- hashitem_T *hi = NULL;
- char_u *varname;
-
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) {
return NULL;
}
+ funccall_T *old_current_funccal = current_funccal;
+ hashitem_T *hi = NULL;
+ const size_t namelen = strlen(name);
+ const char *varname;
+
// Search in parent scope which is possible to reference from lambda
current_funccal = current_funccal->func->uf_scoped;
while (current_funccal != NULL) {
- ht = find_var_ht(name, &varname);
+ hashtab_T *ht = find_var_ht(name, namelen, &varname);
if (ht != NULL && *varname != NUL) {
- hi = hash_find(ht, varname);
+ hi = hash_find_len(ht, varname, namelen - (varname - name));
if (!HASHITEM_EMPTY(hi)) {
*pht = ht;
break;
@@ -23205,23 +23324,24 @@ hashitem_T *find_hi_in_scoped_ht(char_u *name, hashtab_T **pht)
}
/// Search variable in parent scope.
-dictitem_T *find_var_in_scoped_ht(char_u *name, int no_autoload)
+dictitem_T *find_var_in_scoped_ht(const char *name, const size_t namelen,
+ int no_autoload)
{
- dictitem_T *v = NULL;
- funccall_T *old_current_funccal = current_funccal;
- hashtab_T *ht;
- char_u *varname;
-
if (current_funccal == NULL || current_funccal->func->uf_scoped == NULL) {
return NULL;
}
+ dictitem_T *v = NULL;
+ funccall_T *old_current_funccal = current_funccal;
+ const char *varname;
+
// Search in parent scope which is possible to reference from lambda
current_funccal = current_funccal->func->uf_scoped;
while (current_funccal) {
- ht = find_var_ht(name, &varname);
+ hashtab_T *ht = find_var_ht(name, namelen, &varname);
if (ht != NULL && *varname != NUL) {
- v = find_var_in_ht(ht, *name, varname, no_autoload);
+ v = find_var_in_ht(ht, *name, varname,
+ namelen - (size_t)(varname - name), no_autoload);
if (v != NULL) {
break;
}
@@ -23230,7 +23350,7 @@ dictitem_T *find_var_in_scoped_ht(char_u *name, int no_autoload)
break;
}
current_funccal = current_funccal->func->uf_scoped;
- }
+ }
current_funccal = old_current_funccal;
return v;
@@ -24137,10 +24257,12 @@ bool eval_has_provider(char *name)
{
#define check_provider(name) \
if (has_##name == -1) { \
- has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
if (!has_##name) { \
- script_autoload((uint8_t *)"provider#" #name "#Call", false); \
- has_##name = !!find_func((uint8_t *)"provider#" #name "#Call"); \
+ script_autoload("provider#" #name "#Call", \
+ sizeof("provider#" #name "#Call") - 1, \
+ false); \
+ has_##name = !!find_func((char_u *)"provider#" #name "#Call"); \
} \
}