mirror of
https://github.com/neovim/neovim.git
synced 2025-09-15 07:48:18 +00:00
eval: Move get_dict_callback to typval.c
This commit is contained in:
253
src/nvim/eval.c
253
src/nvim/eval.c
@@ -729,7 +729,7 @@ void set_internal_string_var(char_u *name, char_u *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static lval_T *redir_lval = NULL;
|
static lval_T *redir_lval = NULL;
|
||||||
static garray_T redir_ga; /* only valid when redir_lval is not NULL */
|
static garray_T redir_ga; // Only valid when redir_lval is not NULL.
|
||||||
static char_u *redir_endp = NULL;
|
static char_u *redir_endp = NULL;
|
||||||
static char_u *redir_varname = NULL;
|
static char_u *redir_varname = NULL;
|
||||||
|
|
||||||
@@ -761,9 +761,9 @@ var_redir_start (
|
|||||||
/* The output is stored in growarray "redir_ga" until redirection ends. */
|
/* The output is stored in growarray "redir_ga" until redirection ends. */
|
||||||
ga_init(&redir_ga, (int)sizeof(char), 500);
|
ga_init(&redir_ga, (int)sizeof(char), 500);
|
||||||
|
|
||||||
/* Parse the variable name (can be a dict or list entry). */
|
// Parse the variable name (can be a dict or list entry).
|
||||||
redir_endp = get_lval(redir_varname, NULL, redir_lval, FALSE, FALSE, 0,
|
redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval, false, false,
|
||||||
FNE_CHECK_START);
|
0, FNE_CHECK_START);
|
||||||
if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp !=
|
if (redir_endp == NULL || redir_lval->ll_name == NULL || *redir_endp !=
|
||||||
NUL) {
|
NUL) {
|
||||||
clear_lval(redir_lval);
|
clear_lval(redir_lval);
|
||||||
@@ -839,12 +839,13 @@ void var_redir_stop(void)
|
|||||||
ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
|
ga_append(&redir_ga, NUL); /* Append the trailing NUL. */
|
||||||
tv.v_type = VAR_STRING;
|
tv.v_type = VAR_STRING;
|
||||||
tv.vval.v_string = redir_ga.ga_data;
|
tv.vval.v_string = redir_ga.ga_data;
|
||||||
/* Call get_lval() again, if it's inside a Dict or List it may
|
// Call get_lval() again, if it's inside a Dict or List it may
|
||||||
* have changed. */
|
// have changed.
|
||||||
redir_endp = get_lval(redir_varname, NULL, redir_lval,
|
redir_endp = (char_u *)get_lval(redir_varname, NULL, redir_lval,
|
||||||
FALSE, FALSE, 0, FNE_CHECK_START);
|
false, false, 0, FNE_CHECK_START);
|
||||||
if (redir_endp != NULL && redir_lval->ll_name != NULL)
|
if (redir_endp != NULL && redir_lval->ll_name != NULL) {
|
||||||
set_var_lval(redir_lval, redir_endp, &tv, FALSE, (char_u *)".");
|
set_var_lval(redir_lval, redir_endp, &tv, false, (char_u *)".");
|
||||||
|
}
|
||||||
clear_lval(redir_lval);
|
clear_lval(redir_lval);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1457,11 +1458,13 @@ void ex_let(exarg_T *eap)
|
|||||||
char_u *argend;
|
char_u *argend;
|
||||||
int first = TRUE;
|
int first = TRUE;
|
||||||
|
|
||||||
argend = skip_var_list(arg, &var_count, &semicolon);
|
argend = (char_u *)skip_var_list(arg, &var_count, &semicolon);
|
||||||
if (argend == NULL)
|
if (argend == NULL) {
|
||||||
return;
|
return;
|
||||||
if (argend > arg && argend[-1] == '.') /* for var.='str' */
|
}
|
||||||
--argend;
|
if (argend > arg && argend[-1] == '.') { // For var.='str'.
|
||||||
|
argend--;
|
||||||
|
}
|
||||||
expr = skipwhite(argend);
|
expr = skipwhite(argend);
|
||||||
if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
|
if (*expr != '=' && !(vim_strchr((char_u *)"+-.", *expr) != NULL
|
||||||
&& expr[1] == '=')) {
|
&& expr[1] == '=')) {
|
||||||
@@ -1606,9 +1609,11 @@ ex_let_vars (
|
|||||||
* for "[var, var; var]" set "semicolon".
|
* for "[var, var; var]" set "semicolon".
|
||||||
* Return NULL for an error.
|
* Return NULL for an error.
|
||||||
*/
|
*/
|
||||||
static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon)
|
static const char_u *skip_var_list(const char_u *arg, int *var_count,
|
||||||
|
int *semicolon)
|
||||||
{
|
{
|
||||||
char_u *p, *s;
|
const char_u *p;
|
||||||
|
const char_u *s;
|
||||||
|
|
||||||
if (*arg == '[') {
|
if (*arg == '[') {
|
||||||
/* "[var, var]": find the matching ']'. */
|
/* "[var, var]": find the matching ']'. */
|
||||||
@@ -1645,7 +1650,7 @@ static char_u *skip_var_list(char_u *arg, int *var_count, int *semicolon)
|
|||||||
* Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
|
* Skip one (assignable) variable name, including @r, $VAR, &option, d.key,
|
||||||
* l[idx].
|
* l[idx].
|
||||||
*/
|
*/
|
||||||
static char_u *skip_var_one(char_u *arg)
|
static const char_u *skip_var_one(const char_u *arg)
|
||||||
{
|
{
|
||||||
if (*arg == '@' && arg[1] != NUL)
|
if (*arg == '@' && arg[1] != NUL)
|
||||||
return arg + 2;
|
return arg + 2;
|
||||||
@@ -1825,19 +1830,21 @@ static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
|
|||||||
|
|
||||||
// TODO(ZyX-I): move to eval/ex_cmds
|
// TODO(ZyX-I): move to eval/ex_cmds
|
||||||
|
|
||||||
/*
|
/// Set one item of `:let var = expr` or `:let [v1, v2] = list` to its value
|
||||||
* Set one item of ":let var = expr" or ":let [v1, v2] = list" to its value.
|
///
|
||||||
* Returns a pointer to the char just after the var name.
|
/// @param[in] arg Start of the variable name.
|
||||||
* Returns NULL if there is an error.
|
/// @param[in] tv Value to assign to the variable.
|
||||||
*/
|
/// @param[in] copy If true, copy value from `tv`.
|
||||||
static char_u *
|
/// @param[in] endchars Valid characters after variable name or NULL.
|
||||||
ex_let_one (
|
/// @param[in] op Operation performed: *op is `+`, `-`, `.` for `+=`, etc.
|
||||||
char_u *arg, /* points to variable name */
|
/// NULL for `=`.
|
||||||
typval_T *tv, /* value to assign to variable */
|
///
|
||||||
int copy, /* copy value from "tv" */
|
/// @return a pointer to the char just after the var name or NULL in case of
|
||||||
char_u *endchars, /* valid chars after variable name or NULL */
|
/// error.
|
||||||
char_u *op /* "+", "-", "." or NULL*/
|
static char_u *ex_let_one(char_u *arg, typval_T *const tv,
|
||||||
)
|
const bool copy, const char_u *const endchars,
|
||||||
|
const char_u *const op)
|
||||||
|
FUNC_ATTR_NONNULL_ARG(1, 2) FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
char_u *name;
|
char_u *name;
|
||||||
char_u *arg_end = NULL;
|
char_u *arg_end = NULL;
|
||||||
@@ -1849,10 +1856,10 @@ ex_let_one (
|
|||||||
* ":let $VAR = expr": Set environment variable.
|
* ":let $VAR = expr": Set environment variable.
|
||||||
*/
|
*/
|
||||||
if (*arg == '$') {
|
if (*arg == '$') {
|
||||||
/* Find the end of the name. */
|
// Find the end of the name.
|
||||||
++arg;
|
arg++;
|
||||||
name = arg;
|
name = arg;
|
||||||
len = get_env_len(&arg);
|
len = get_env_len((const char_u **)&arg);
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
EMSG2(_(e_invarg2), name - 1);
|
EMSG2(_(e_invarg2), name - 1);
|
||||||
} else {
|
} else {
|
||||||
@@ -1975,9 +1982,9 @@ ex_let_one (
|
|||||||
|
|
||||||
char_u *const 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 (p != NULL && lv.ll_name != NULL) {
|
||||||
if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL)
|
if (endchars != NULL && vim_strchr(endchars, *skipwhite(p)) == NULL) {
|
||||||
EMSG(_(e_letunexp));
|
EMSG(_(e_letunexp));
|
||||||
else {
|
} else {
|
||||||
set_var_lval(&lv, p, tv, copy, op);
|
set_var_lval(&lv, p, tv, copy, op);
|
||||||
arg_end = p;
|
arg_end = p;
|
||||||
}
|
}
|
||||||
@@ -2020,7 +2027,6 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,
|
|||||||
FUNC_ATTR_NONNULL_ARG(1, 3)
|
FUNC_ATTR_NONNULL_ARG(1, 3)
|
||||||
{
|
{
|
||||||
char_u *p;
|
char_u *p;
|
||||||
char_u *expr_start, *expr_end;
|
|
||||||
int cc;
|
int cc;
|
||||||
dictitem_T *v;
|
dictitem_T *v;
|
||||||
typval_T var1;
|
typval_T var1;
|
||||||
@@ -2036,13 +2042,17 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,
|
|||||||
memset(lp, 0, sizeof(lval_T));
|
memset(lp, 0, sizeof(lval_T));
|
||||||
|
|
||||||
if (skip) {
|
if (skip) {
|
||||||
/* When skipping just find the end of the name. */
|
// When skipping just find the end of the name.
|
||||||
lp->ll_name = name;
|
lp->ll_name = (char_u *)name;
|
||||||
return find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
|
return (char_u *)find_name_end(name, NULL, NULL, FNE_INCL_BR | fne_flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the end of the name. */
|
// Find the end of the name.
|
||||||
p = find_name_end(name, &expr_start, &expr_end, fne_flags);
|
char_u *expr_start;
|
||||||
|
char_u *expr_end;
|
||||||
|
p = (char_u *)find_name_end(name,
|
||||||
|
(const char_u **)&expr_start,
|
||||||
|
(const char_u **)&expr_end, fne_flags);
|
||||||
if (expr_start != NULL) {
|
if (expr_start != NULL) {
|
||||||
/* Don't expand the name when we already know there is an error. */
|
/* Don't expand the name when we already know there is an error. */
|
||||||
if (unlet && !ascii_iswhite(*p) && !ends_excmd(*p)
|
if (unlet && !ascii_iswhite(*p) && !ends_excmd(*p)
|
||||||
@@ -2063,8 +2073,9 @@ static char_u *get_lval(char_u *const name, typval_T *const rettv,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
lp->ll_name = lp->ll_exp_name;
|
lp->ll_name = lp->ll_exp_name;
|
||||||
} else
|
} else {
|
||||||
lp->ll_name = name;
|
lp->ll_name = (char_u *)name;
|
||||||
|
}
|
||||||
|
|
||||||
/* Without [idx] or .key we are done. */
|
/* Without [idx] or .key we are done. */
|
||||||
if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
|
if ((*p != '[' && *p != '.') || lp->ll_name == NULL)
|
||||||
@@ -2351,7 +2362,8 @@ static void clear_lval(lval_T *lp)
|
|||||||
* "endp" points to just after the parsed name.
|
* "endp" points to just after the parsed name.
|
||||||
* "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
|
* "op" is NULL, "+" for "+=", "-" for "-=", "." for ".=" or "=" for "=".
|
||||||
*/
|
*/
|
||||||
static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv, int copy, char_u *op)
|
static void set_var_lval(lval_T *lp, char_u *endp, typval_T *rettv,
|
||||||
|
int copy, const char_u *op)
|
||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
listitem_T *ri;
|
listitem_T *ri;
|
||||||
@@ -2493,10 +2505,10 @@ notify:
|
|||||||
* Set "*errp" to TRUE for an error, FALSE otherwise;
|
* Set "*errp" to TRUE for an error, FALSE otherwise;
|
||||||
* Return a pointer that holds the info. Null when there is an error.
|
* Return a pointer that holds the info. Null when there is an error.
|
||||||
*/
|
*/
|
||||||
void *eval_for_line(char_u *arg, bool *errp, char_u **nextcmdp, int skip)
|
void *eval_for_line(const char_u *arg, bool *errp, char_u **nextcmdp, int skip)
|
||||||
{
|
{
|
||||||
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
|
forinfo_T *fi = xcalloc(1, sizeof(forinfo_T));
|
||||||
char_u *expr;
|
const char_u *expr;
|
||||||
typval_T tv;
|
typval_T tv;
|
||||||
list_T *l;
|
list_T *l;
|
||||||
|
|
||||||
@@ -2824,16 +2836,17 @@ void ex_lockvar(exarg_T *eap)
|
|||||||
static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep)
|
static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep)
|
||||||
{
|
{
|
||||||
char_u *arg = argstart;
|
char_u *arg = argstart;
|
||||||
char_u *name_end;
|
bool error = false;
|
||||||
int error = FALSE;
|
|
||||||
lval_T lv;
|
lval_T lv;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
/* Parse the name and find the end. */
|
// Parse the name and find the end.
|
||||||
name_end = get_lval(arg, NULL, &lv, TRUE, eap->skip || error, 0,
|
char_u *const name_end = (char_u *)get_lval(arg, NULL, &lv, true,
|
||||||
FNE_CHECK_START);
|
eap->skip || error,
|
||||||
if (lv.ll_name == NULL)
|
0, FNE_CHECK_START);
|
||||||
error = TRUE; /* error but continue parsing */
|
if (lv.ll_name == NULL) {
|
||||||
|
error = true; // error, but continue parsing.
|
||||||
|
}
|
||||||
if (name_end == NULL || (!ascii_iswhite(*name_end)
|
if (name_end == NULL || (!ascii_iswhite(*name_end)
|
||||||
&& !ends_excmd(*name_end))) {
|
&& !ends_excmd(*name_end))) {
|
||||||
if (name_end != NULL) {
|
if (name_end != NULL) {
|
||||||
@@ -2868,7 +2881,7 @@ static void ex_unletlock(exarg_T *eap, char_u *argstart, int deep)
|
|||||||
|
|
||||||
// TODO(ZyX-I): move to eval/ex_cmds
|
// TODO(ZyX-I): move to eval/ex_cmds
|
||||||
|
|
||||||
static int do_unlet_var(lval_T *lp, char_u *name_end, int forceit)
|
static int do_unlet_var(lval_T *const lp, char_u *const name_end, int forceit)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
int cc;
|
int cc;
|
||||||
@@ -3022,7 +3035,7 @@ int do_unlet(char_u *name, int forceit)
|
|||||||
* "deep" is the levels to go (-1 for unlimited);
|
* "deep" is the levels to go (-1 for unlimited);
|
||||||
* "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
|
* "lock" is TRUE for ":lockvar", FALSE for ":unlockvar".
|
||||||
*/
|
*/
|
||||||
static int do_lock_var(lval_T *lp, char_u *name_end, const int deep,
|
static int do_lock_var(lval_T *lp, char_u *const name_end, const int deep,
|
||||||
const bool lock)
|
const bool lock)
|
||||||
{
|
{
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@@ -5605,34 +5618,6 @@ void dict_set_keys_readonly(dict_T *const dict)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a function from a dictionary
|
|
||||||
/// @param[out] result The address where a pointer to the wanted callback
|
|
||||||
/// will be left.
|
|
||||||
/// @return true/false on success/failure.
|
|
||||||
static bool get_dict_callback(dict_T *d, char *key, Callback *result)
|
|
||||||
{
|
|
||||||
dictitem_T *const di = tv_dict_find(d, key, -1);
|
|
||||||
|
|
||||||
if (di == NULL) {
|
|
||||||
result->type = kCallbackNone;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (di->di_tv.v_type != VAR_FUNC && di->di_tv.v_type != VAR_STRING
|
|
||||||
&& di->di_tv.v_type != VAR_PARTIAL) {
|
|
||||||
EMSG(_("Argument is not a function or function name"));
|
|
||||||
result->type = kCallbackNone;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
typval_T tv;
|
|
||||||
copy_tv(&di->di_tv, &tv);
|
|
||||||
set_selfdict(&tv, d);
|
|
||||||
bool res = callback_from_typval(result, &tv);
|
|
||||||
tv_clear(&tv);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocate a variable for a Dictionary and fill it from "*arg".
|
* Allocate a variable for a Dictionary and fill it from "*arg".
|
||||||
* Return OK or FAIL. Returns NOTDONE for {expr}.
|
* Return OK or FAIL. Returns NOTDONE for {expr}.
|
||||||
@@ -5997,7 +5982,7 @@ static int get_env_tv(char_u **arg, typval_T *rettv, int evaluate)
|
|||||||
|
|
||||||
++*arg;
|
++*arg;
|
||||||
name = *arg;
|
name = *arg;
|
||||||
len = get_env_len(arg);
|
len = get_env_len((const char_u **)arg);
|
||||||
|
|
||||||
if (evaluate) {
|
if (evaluate) {
|
||||||
if (len == 0) {
|
if (len == 0) {
|
||||||
@@ -11291,16 +11276,16 @@ static void f_isdirectory(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_islocked(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
lval_T lv;
|
lval_T lv;
|
||||||
char_u *end;
|
|
||||||
dictitem_T *di;
|
dictitem_T *di;
|
||||||
|
|
||||||
rettv->vval.v_number = -1;
|
rettv->vval.v_number = -1;
|
||||||
end = get_lval(get_tv_string(&argvars[0]), NULL, &lv, false, false,
|
const char_u *const end = get_lval(get_tv_string(&argvars[0]), NULL,
|
||||||
GLV_NO_AUTOLOAD|GLV_READ_ONLY, FNE_CHECK_START);
|
&lv, false, false,
|
||||||
|
GLV_NO_AUTOLOAD, FNE_CHECK_START);
|
||||||
if (end != NULL && lv.ll_name != NULL) {
|
if (end != NULL && lv.ll_name != NULL) {
|
||||||
if (*end != NUL)
|
if (*end != NUL) {
|
||||||
EMSG(_(e_trailing));
|
EMSG(_(e_trailing));
|
||||||
else {
|
} else {
|
||||||
if (lv.ll_tv == NULL) {
|
if (lv.ll_tv == NULL) {
|
||||||
di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL, true);
|
di = find_var((const char *)lv.ll_name, STRLEN(lv.ll_name), NULL, true);
|
||||||
if (di != NULL) {
|
if (di != NULL) {
|
||||||
@@ -16580,7 +16565,8 @@ static void f_test_garbagecollect_now(typval_T *argvars,
|
|||||||
garbage_collect(true);
|
garbage_collect(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool callback_from_typval(Callback *callback, typval_T *arg)
|
bool callback_from_typval(Callback *const callback, typval_T *const arg)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) {
|
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) {
|
||||||
callback->data.partial = arg->vval.v_partial;
|
callback->data.partial = arg->vval.v_partial;
|
||||||
@@ -17698,15 +17684,16 @@ static int list2fpos(typval_T *arg, pos_T *posp, int *fnump, colnr_T *curswantp)
|
|||||||
* Advance "arg" to the first character after the name.
|
* Advance "arg" to the first character after the name.
|
||||||
* Return 0 for error.
|
* Return 0 for error.
|
||||||
*/
|
*/
|
||||||
static int get_env_len(char_u **arg)
|
static int get_env_len(const char_u **arg)
|
||||||
{
|
{
|
||||||
char_u *p;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
for (p = *arg; vim_isIDc(*p); ++p)
|
const char_u *p;
|
||||||
;
|
for (p = *arg; vim_isIDc(*p); p++) {
|
||||||
if (p == *arg) /* no name found */
|
}
|
||||||
|
if (p == *arg) { // No name found.
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
len = (int)(p - *arg);
|
len = (int)(p - *arg);
|
||||||
*arg = p;
|
*arg = p;
|
||||||
@@ -17758,8 +17745,6 @@ static int get_name_len(const char **const arg,
|
|||||||
int verbose)
|
int verbose)
|
||||||
{
|
{
|
||||||
int len;
|
int len;
|
||||||
char_u *expr_start;
|
|
||||||
char_u *expr_end;
|
|
||||||
|
|
||||||
*alias = NULL; /* default to no alias */
|
*alias = NULL; /* default to no alias */
|
||||||
|
|
||||||
@@ -17775,12 +17760,12 @@ static int get_name_len(const char **const arg,
|
|||||||
*arg += len;
|
*arg += len;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Find the end of the name; check for {} construction.
|
||||||
* Find the end of the name; check for {} construction.
|
char_u *expr_start;
|
||||||
*/
|
char_u *expr_end;
|
||||||
const char *p = (const char *)find_name_end((char_u *)(*arg),
|
const char *p = (const char *)find_name_end((char_u *)(*arg),
|
||||||
&expr_start,
|
(const char_u **)&expr_start,
|
||||||
&expr_end,
|
(const char_u **)&expr_end,
|
||||||
len > 0 ? 0 : FNE_CHECK_START);
|
len > 0 ? 0 : FNE_CHECK_START);
|
||||||
if (expr_start != NULL) {
|
if (expr_start != NULL) {
|
||||||
if (!evaluate) {
|
if (!evaluate) {
|
||||||
@@ -17816,12 +17801,11 @@ static int get_name_len(const char **const arg,
|
|||||||
// "flags" can have FNE_INCL_BR and FNE_CHECK_START.
|
// "flags" can have FNE_INCL_BR and FNE_CHECK_START.
|
||||||
// Return a pointer to just after the name. Equal to "arg" if there is no
|
// Return a pointer to just after the name. Equal to "arg" if there is no
|
||||||
// valid name.
|
// valid name.
|
||||||
static char_u *find_name_end(char_u *arg, char_u **expr_start,
|
static const char_u *find_name_end(const char_u *arg, const char_u **expr_start,
|
||||||
char_u **expr_end, int flags)
|
const char_u **expr_end, int flags)
|
||||||
{
|
{
|
||||||
int mb_nest = 0;
|
int mb_nest = 0;
|
||||||
int br_nest = 0;
|
int br_nest = 0;
|
||||||
char_u *p;
|
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
if (expr_start != NULL) {
|
if (expr_start != NULL) {
|
||||||
@@ -17834,6 +17818,7 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start,
|
|||||||
return arg;
|
return arg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const char_u *p;
|
||||||
for (p = arg; *p != NUL
|
for (p = arg; *p != NUL
|
||||||
&& (eval_isnamec(*p)
|
&& (eval_isnamec(*p)
|
||||||
|| *p == '{'
|
|| *p == '{'
|
||||||
@@ -17905,7 +17890,8 @@ static char_u *find_name_end(char_u *arg, char_u **expr_start,
|
|||||||
* Returns a new allocated string, which the caller must free.
|
* Returns a new allocated string, which the caller must free.
|
||||||
* Returns NULL for failure.
|
* Returns NULL for failure.
|
||||||
*/
|
*/
|
||||||
static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *expr_end, char_u *in_end)
|
static char_u *make_expanded_name(const char_u *in_start, char_u *expr_start,
|
||||||
|
char_u *expr_end, char_u *in_end)
|
||||||
{
|
{
|
||||||
char_u c1;
|
char_u c1;
|
||||||
char_u *retval = NULL;
|
char_u *retval = NULL;
|
||||||
@@ -17934,7 +17920,9 @@ static char_u *make_expanded_name(char_u *in_start, char_u *expr_start, char_u *
|
|||||||
*expr_end = '}';
|
*expr_end = '}';
|
||||||
|
|
||||||
if (retval != NULL) {
|
if (retval != NULL) {
|
||||||
temp_result = find_name_end(retval, &expr_start, &expr_end, 0);
|
temp_result = (char_u *)find_name_end(retval,
|
||||||
|
(const char_u **)&expr_start,
|
||||||
|
(const char_u **)&expr_end, 0);
|
||||||
if (expr_start != NULL) {
|
if (expr_start != NULL) {
|
||||||
/* Further expansion! */
|
/* Further expansion! */
|
||||||
temp_result = make_expanded_name(retval, expr_start,
|
temp_result = make_expanded_name(retval, expr_start,
|
||||||
@@ -18351,7 +18339,7 @@ handle_subscript(
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_selfdict(typval_T *rettv, dict_T *selfdict)
|
void set_selfdict(typval_T *rettv, dict_T *selfdict)
|
||||||
{
|
{
|
||||||
// Don't do this when "dict.Func" is already a partial that was bound
|
// Don't do this when "dict.Func" is already a partial that was bound
|
||||||
// explicitly (pt_auto is false).
|
// explicitly (pt_auto is false).
|
||||||
@@ -20195,15 +20183,15 @@ ret_free:
|
|||||||
static char_u *
|
static char_u *
|
||||||
trans_function_name(
|
trans_function_name(
|
||||||
char_u **pp,
|
char_u **pp,
|
||||||
int skip, /* only find the end, don't evaluate */
|
int skip, // only find the end, don't evaluate
|
||||||
int flags,
|
int flags,
|
||||||
funcdict_T *fdp, // return: info about dictionary used
|
funcdict_T *fdp, // return: info about dictionary used
|
||||||
partial_T **partial // return: partial of a FuncRef
|
partial_T **partial // return: partial of a FuncRef
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
char_u *name = NULL;
|
char_u *name = NULL;
|
||||||
char_u *start;
|
const char_u *start;
|
||||||
char_u *end;
|
const char_u *end;
|
||||||
int lead;
|
int lead;
|
||||||
char_u sid_buf[20];
|
char_u sid_buf[20];
|
||||||
int len;
|
int len;
|
||||||
@@ -20229,8 +20217,8 @@ trans_function_name(
|
|||||||
start += lead;
|
start += lead;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Note that TFN_ flags use the same values as GLV_ flags. */
|
// Note that TFN_ flags use the same values as GLV_ flags.
|
||||||
end = get_lval(start, NULL, &lv, FALSE, skip, flags,
|
end = get_lval((char_u *)start, NULL, &lv, false, skip, flags,
|
||||||
lead > 2 ? 0 : FNE_CHECK_START);
|
lead > 2 ? 0 : FNE_CHECK_START);
|
||||||
if (end == start) {
|
if (end == start) {
|
||||||
if (!skip)
|
if (!skip)
|
||||||
@@ -20244,10 +20232,12 @@ trans_function_name(
|
|||||||
* interrupt, or an exception.
|
* interrupt, or an exception.
|
||||||
*/
|
*/
|
||||||
if (!aborting()) {
|
if (!aborting()) {
|
||||||
if (end != NULL)
|
if (end != NULL) {
|
||||||
EMSG2(_(e_invarg2), start);
|
emsgf(_(e_invarg2), start);
|
||||||
} else
|
}
|
||||||
*pp = find_name_end(start, NULL, NULL, FNE_INCL_BR);
|
} else {
|
||||||
|
*pp = (char_u *)find_name_end(start, NULL, NULL, FNE_INCL_BR);
|
||||||
|
}
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20260,11 +20250,11 @@ trans_function_name(
|
|||||||
}
|
}
|
||||||
if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) {
|
if (lv.ll_tv->v_type == VAR_FUNC && lv.ll_tv->vval.v_string != NULL) {
|
||||||
name = vim_strsave(lv.ll_tv->vval.v_string);
|
name = vim_strsave(lv.ll_tv->vval.v_string);
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
} else if (lv.ll_tv->v_type == VAR_PARTIAL
|
} else if (lv.ll_tv->v_type == VAR_PARTIAL
|
||||||
&& lv.ll_tv->vval.v_partial != NULL) {
|
&& lv.ll_tv->vval.v_partial != NULL) {
|
||||||
name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial));
|
name = vim_strsave(partial_name(lv.ll_tv->vval.v_partial));
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
if (partial != NULL) {
|
if (partial != NULL) {
|
||||||
*partial = lv.ll_tv->vval.v_partial;
|
*partial = lv.ll_tv->vval.v_partial;
|
||||||
}
|
}
|
||||||
@@ -20274,7 +20264,7 @@ trans_function_name(
|
|||||||
|| fdp->fd_newkey == NULL)) {
|
|| fdp->fd_newkey == NULL)) {
|
||||||
EMSG(_(e_funcref));
|
EMSG(_(e_funcref));
|
||||||
} else {
|
} else {
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
}
|
}
|
||||||
name = NULL;
|
name = NULL;
|
||||||
}
|
}
|
||||||
@@ -20282,8 +20272,8 @@ trans_function_name(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (lv.ll_name == NULL) {
|
if (lv.ll_name == NULL) {
|
||||||
/* Error found, but continue after the function name. */
|
// Error found, but continue after the function name.
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
goto theend;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -20305,7 +20295,7 @@ trans_function_name(
|
|||||||
}
|
}
|
||||||
if (name != NULL) {
|
if (name != NULL) {
|
||||||
name = vim_strsave(name);
|
name = vim_strsave(name);
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
if (strncmp((char *)name, "<SNR>", 5) == 0) {
|
if (strncmp((char *)name, "<SNR>", 5) == 0) {
|
||||||
// Change "<SNR>" to the byte sequence.
|
// Change "<SNR>" to the byte sequence.
|
||||||
name[0] = K_SPECIAL;
|
name[0] = K_SPECIAL;
|
||||||
@@ -20379,7 +20369,7 @@ trans_function_name(
|
|||||||
}
|
}
|
||||||
memmove(name + lead, lv.ll_name, (size_t)len);
|
memmove(name + lead, lv.ll_name, (size_t)len);
|
||||||
name[lead + len] = NUL;
|
name[lead + len] = NUL;
|
||||||
*pp = end;
|
*pp = (char_u *)end;
|
||||||
|
|
||||||
theend:
|
theend:
|
||||||
clear_lval(&lv);
|
clear_lval(&lv);
|
||||||
@@ -20408,8 +20398,8 @@ static int eval_fname_script(const char *const p)
|
|||||||
|
|
||||||
/// Check whether function name starts with <SID> or s:
|
/// Check whether function name starts with <SID> or s:
|
||||||
///
|
///
|
||||||
/// Only works for names previously checked by eval_fname_script(), if it
|
/// @warning Only works for names previously checked by eval_fname_script(), if
|
||||||
/// returned non-zero.
|
/// it returned non-zero.
|
||||||
///
|
///
|
||||||
/// @param[in] name Name to check.
|
/// @param[in] name Name to check.
|
||||||
///
|
///
|
||||||
@@ -20558,14 +20548,15 @@ bool translated_function_exists(const char *name)
|
|||||||
/// @return True if it exists, false otherwise.
|
/// @return True if it exists, false otherwise.
|
||||||
static bool function_exists(const char *const name, bool no_deref)
|
static bool function_exists(const char *const name, bool no_deref)
|
||||||
{
|
{
|
||||||
char_u *nm = (char_u *)name;
|
const char_u *nm = (const char_u *)name;
|
||||||
bool n = false;
|
bool n = false;
|
||||||
int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
|
int flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
|
||||||
|
|
||||||
if (no_deref) {
|
if (no_deref) {
|
||||||
flag |= TFN_NO_DEREF;
|
flag |= TFN_NO_DEREF;
|
||||||
}
|
}
|
||||||
char *const p = (char *)trans_function_name(&nm, false, flag, NULL, NULL);
|
char *const p = (char *)trans_function_name((char_u **)&nm, false, flag, NULL,
|
||||||
|
NULL);
|
||||||
nm = skipwhite(nm);
|
nm = skipwhite(nm);
|
||||||
|
|
||||||
/* Only accept "funcname", "funcname ", "funcname (..." and
|
/* Only accept "funcname", "funcname ", "funcname (..." and
|
||||||
@@ -22510,9 +22501,9 @@ static inline TerminalJobData *common_job_init(char **argv,
|
|||||||
static inline bool common_job_callbacks(dict_T *vopts, Callback *on_stdout,
|
static inline bool common_job_callbacks(dict_T *vopts, Callback *on_stdout,
|
||||||
Callback *on_stderr, Callback *on_exit)
|
Callback *on_stderr, Callback *on_exit)
|
||||||
{
|
{
|
||||||
if (get_dict_callback(vopts, "on_stdout", on_stdout)
|
if (tv_dict_get_callback(vopts, S_LEN("on_stdout"), on_stdout)
|
||||||
&& get_dict_callback(vopts, "on_stderr", on_stderr)
|
&&tv_dict_get_callback(vopts, S_LEN("on_stderr"), on_stderr)
|
||||||
&& get_dict_callback(vopts, "on_exit", on_exit)) {
|
&& tv_dict_get_callback(vopts, S_LEN("on_exit"), on_exit)) {
|
||||||
vopts->dv_refcount++;
|
vopts->dv_refcount++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -1130,6 +1130,42 @@ const char *tv_dict_get_string_buf(dict_T *const d, const char *const key,
|
|||||||
return (const char *)get_tv_string_buf(&di->di_tv, (char_u *)numbuf);
|
return (const char *)get_tv_string_buf(&di->di_tv, (char_u *)numbuf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a function from a dictionary
|
||||||
|
///
|
||||||
|
/// @param[in] d Dictionary to get callback from.
|
||||||
|
/// @param[in] key Dictionary key.
|
||||||
|
/// @param[in] key_len Key length, may be -1 to use strlen().
|
||||||
|
/// @param[out] result The address where a pointer to the wanted callback
|
||||||
|
/// will be left.
|
||||||
|
///
|
||||||
|
/// @return true/false on success/failure.
|
||||||
|
bool tv_dict_get_callback(dict_T *const d,
|
||||||
|
const char *const key, const ptrdiff_t key_len,
|
||||||
|
Callback *const result)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
|
{
|
||||||
|
result->type = kCallbackNone;
|
||||||
|
|
||||||
|
dictitem_T *const di = tv_dict_find(d, key, key_len);
|
||||||
|
|
||||||
|
if (di == NULL) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (di->di_tv.v_type != VAR_FUNC && di->di_tv.v_type != VAR_STRING
|
||||||
|
&& di->di_tv.v_type != VAR_PARTIAL) {
|
||||||
|
EMSG(_("Argument is not a function or function name"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
typval_T tv;
|
||||||
|
copy_tv(&di->di_tv, &tv);
|
||||||
|
set_selfdict(&tv, d);
|
||||||
|
bool res = callback_from_typval(result, &tv);
|
||||||
|
tv_clear(&tv);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
//{{{2 Operations on the whole dict
|
//{{{2 Operations on the whole dict
|
||||||
|
|
||||||
/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
|
/// Clear all the keys of a Dictionary. "d" remains a valid empty Dictionary.
|
||||||
|
Reference in New Issue
Block a user