mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
vim-patch:8.1.1800: function call functions have too many arguments
Problem: Function call functions have too many arguments.
Solution: Pass values in a funcexe_T struct.
c6538bcc1c
Use FUNCEXE_INIT to initialize funcexe_T instances.
call_callback() and other Vim listener related stuff is N/A.
This commit is contained in:
parent
60dd76c7e2
commit
4042ae5a2b
@ -614,12 +614,15 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
|
|||||||
recursive++;
|
recursive++;
|
||||||
try_start();
|
try_start();
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = true;
|
||||||
|
funcexe.selfdict = self;
|
||||||
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
|
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
|
||||||
// (see above) to capture abort-causing non-exception errors.
|
// (see above) to capture abort-causing non-exception errors.
|
||||||
(void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size,
|
(void)call_func((char_u *)fn.data, (int)fn.size, &rettv, (int)args.size,
|
||||||
vim_args, NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
vim_args, &funcexe);
|
||||||
&dummy, true, NULL, self);
|
|
||||||
if (!try_end(err)) {
|
if (!try_end(err)) {
|
||||||
rv = vim_to_object(&rettv);
|
rv = vim_to_object(&rettv);
|
||||||
}
|
}
|
||||||
|
@ -737,15 +737,15 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv,
|
|||||||
int argc, typval_T *rettv)
|
int argc, typval_T *rettv)
|
||||||
FUNC_ATTR_NONNULL_ARG(1, 2, 4)
|
FUNC_ATTR_NONNULL_ARG(1, 2, 4)
|
||||||
{
|
{
|
||||||
int dummy;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
|
|
||||||
if (expr->v_type == VAR_FUNC) {
|
if (expr->v_type == VAR_FUNC) {
|
||||||
const char_u *const s = expr->vval.v_string;
|
const char_u *const s = expr->vval.v_string;
|
||||||
if (s == NULL || *s == NUL) {
|
if (s == NULL || *s == NUL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (call_func(s, -1, rettv, argc, argv, NULL,
|
funcexe.evaluate = true;
|
||||||
0L, 0L, &dummy, true, NULL, NULL) == FAIL) {
|
if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
} else if (expr->v_type == VAR_PARTIAL) {
|
} else if (expr->v_type == VAR_PARTIAL) {
|
||||||
@ -754,8 +754,9 @@ int eval_expr_typval(const typval_T *expr, typval_T *argv,
|
|||||||
if (s == NULL || *s == NUL) {
|
if (s == NULL || *s == NUL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
if (call_func(s, -1, rettv, argc, argv, NULL,
|
funcexe.evaluate = true;
|
||||||
0L, 0L, &dummy, true, partial, NULL) == FAIL) {
|
funcexe.partial = partial;
|
||||||
|
if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL) {
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1051,7 +1052,6 @@ int call_vim_function(
|
|||||||
)
|
)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
{
|
{
|
||||||
int doesrange;
|
|
||||||
int ret;
|
int ret;
|
||||||
int len = (int)STRLEN(func);
|
int len = (int)STRLEN(func);
|
||||||
partial_T *pt = NULL;
|
partial_T *pt = NULL;
|
||||||
@ -1067,9 +1067,12 @@ int call_vim_function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this.
|
rettv->v_type = VAR_UNKNOWN; // tv_clear() uses this.
|
||||||
ret = call_func(func, len, rettv, argc, argv, NULL,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
&doesrange, true, pt, NULL);
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = true;
|
||||||
|
funcexe.partial = pt;
|
||||||
|
ret = call_func(func, len, rettv, argc, argv, &funcexe);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
if (ret == FAIL) {
|
if (ret == FAIL) {
|
||||||
@ -3988,9 +3991,12 @@ static int eval7(
|
|||||||
s = xmemdupz(s, len);
|
s = xmemdupz(s, len);
|
||||||
|
|
||||||
// Invoke the function.
|
// Invoke the function.
|
||||||
ret = get_func_tv(s, len, rettv, arg,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
&len, evaluate, partial, NULL);
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = evaluate;
|
||||||
|
funcexe.partial = partial;
|
||||||
|
ret = get_func_tv(s, len, rettv, arg, &funcexe);
|
||||||
|
|
||||||
xfree(s);
|
xfree(s);
|
||||||
|
|
||||||
@ -7260,10 +7266,12 @@ bool callback_call(Callback *const callback, const int argcount_in,
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
int dummy;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
return call_func(name, -1, rettv, argcount_in, argvars_in,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
NULL, curwin->w_cursor.lnum, curwin->w_cursor.lnum, &dummy,
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
true, partial, NULL);
|
funcexe.evaluate = true;
|
||||||
|
funcexe.partial = partial;
|
||||||
|
return call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool set_ref_in_callback(Callback *callback, int copyID,
|
static bool set_ref_in_callback(Callback *callback, int copyID,
|
||||||
@ -8426,7 +8434,6 @@ handle_subscript(
|
|||||||
int ret = OK;
|
int ret = OK;
|
||||||
dict_T *selfdict = NULL;
|
dict_T *selfdict = NULL;
|
||||||
const char_u *s;
|
const char_u *s;
|
||||||
int len;
|
|
||||||
typval_T functv;
|
typval_T functv;
|
||||||
int slen = 0;
|
int slen = 0;
|
||||||
bool lua = false;
|
bool lua = false;
|
||||||
@ -8474,9 +8481,14 @@ handle_subscript(
|
|||||||
} else {
|
} else {
|
||||||
s = (char_u *)"";
|
s = (char_u *)"";
|
||||||
}
|
}
|
||||||
ret = get_func_tv(s, lua ? slen : -1, rettv, (char_u **)arg,
|
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
&len, evaluate, pt, selfdict);
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = evaluate;
|
||||||
|
funcexe.partial = pt;
|
||||||
|
funcexe.selfdict = selfdict;
|
||||||
|
ret = get_func_tv(s, lua ? slen : -1, rettv, (char_u **)arg, &funcexe);
|
||||||
|
|
||||||
// Clear the funcref afterwards, so that deleting it while
|
// Clear the funcref afterwards, so that deleting it while
|
||||||
// evaluating the arguments is possible (see test55).
|
// evaluating the arguments is possible (see test55).
|
||||||
@ -10416,19 +10428,11 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments,
|
|||||||
typval_T rettv = { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED };
|
typval_T rettv = { .v_type = VAR_UNKNOWN, .v_lock = VAR_UNLOCKED };
|
||||||
tv_list_ref(arguments);
|
tv_list_ref(arguments);
|
||||||
|
|
||||||
int dummy;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
(void)call_func((const char_u *)func,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
name_len,
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
&rettv,
|
funcexe.evaluate = true;
|
||||||
2,
|
(void)call_func((const char_u *)func, name_len, &rettv, 2, argvars, &funcexe);
|
||||||
argvars,
|
|
||||||
NULL,
|
|
||||||
curwin->w_cursor.lnum,
|
|
||||||
curwin->w_cursor.lnum,
|
|
||||||
&dummy,
|
|
||||||
true,
|
|
||||||
NULL,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
tv_list_unref(arguments);
|
tv_list_unref(arguments);
|
||||||
// Restore caller scope information
|
// Restore caller scope information
|
||||||
|
@ -9420,7 +9420,6 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
|
|||||||
int res;
|
int res;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
int dummy;
|
|
||||||
const char *func_name;
|
const char *func_name;
|
||||||
partial_T *partial = sortinfo->item_compare_partial;
|
partial_T *partial = sortinfo->item_compare_partial;
|
||||||
|
|
||||||
@ -9444,10 +9443,11 @@ static int item_compare2(const void *s1, const void *s2, bool keep_zero)
|
|||||||
tv_copy(TV_LIST_ITEM_TV(si2->item), &argv[1]);
|
tv_copy(TV_LIST_ITEM_TV(si2->item), &argv[1]);
|
||||||
|
|
||||||
rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this
|
rettv.v_type = VAR_UNKNOWN; // tv_clear() uses this
|
||||||
res = call_func((const char_u *)func_name,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
-1,
|
funcexe.evaluate = true;
|
||||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, true,
|
funcexe.partial = partial;
|
||||||
partial, sortinfo->item_compare_selfdict);
|
funcexe.selfdict = sortinfo->item_compare_selfdict;
|
||||||
|
res = call_func((const char_u *)func_name, -1, &rettv, 2, argv, &funcexe);
|
||||||
tv_clear(&argv[0]);
|
tv_clear(&argv[0]);
|
||||||
tv_clear(&argv[1]);
|
tv_clear(&argv[1]);
|
||||||
|
|
||||||
|
@ -414,12 +414,7 @@ get_func_tv(
|
|||||||
int len, // length of "name" or -1 to use strlen()
|
int len, // length of "name" or -1 to use strlen()
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
char_u **arg, // argument, pointing to the '('
|
char_u **arg, // argument, pointing to the '('
|
||||||
linenr_T firstline, // first line of range
|
funcexe_T *funcexe // various values
|
||||||
linenr_T lastline, // last line of range
|
|
||||||
int *doesrange, // return: function handled range
|
|
||||||
int evaluate,
|
|
||||||
partial_T *partial, // for extra arguments
|
|
||||||
dict_T *selfdict // Dictionary for "self"
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
char_u *argp;
|
char_u *argp;
|
||||||
@ -431,12 +426,13 @@ get_func_tv(
|
|||||||
* Get the arguments.
|
* Get the arguments.
|
||||||
*/
|
*/
|
||||||
argp = *arg;
|
argp = *arg;
|
||||||
while (argcount < MAX_FUNC_ARGS - (partial == NULL ? 0 : partial->pt_argc)) {
|
while (argcount < MAX_FUNC_ARGS
|
||||||
|
- (funcexe->partial == NULL ? 0 : funcexe->partial->pt_argc)) {
|
||||||
argp = skipwhite(argp + 1); // skip the '(' or ','
|
argp = skipwhite(argp + 1); // skip the '(' or ','
|
||||||
if (*argp == ')' || *argp == ',' || *argp == NUL) {
|
if (*argp == ')' || *argp == ',' || *argp == NUL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (eval1(&argp, &argvars[argcount], evaluate) == FAIL) {
|
if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL) {
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -463,9 +459,7 @@ get_func_tv(
|
|||||||
((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i];
|
((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = call_func(name, len, rettv, argcount, argvars, NULL,
|
ret = call_func(name, len, rettv, argcount, argvars, funcexe);
|
||||||
firstline, lastline, doesrange, evaluate,
|
|
||||||
partial, selfdict);
|
|
||||||
|
|
||||||
funcargs.ga_len -= i;
|
funcargs.ga_len -= i;
|
||||||
} else if (!aborting()) {
|
} else if (!aborting()) {
|
||||||
@ -1367,7 +1361,6 @@ int func_call(char_u *name, typval_T *args, partial_T *partial,
|
|||||||
{
|
{
|
||||||
typval_T argv[MAX_FUNC_ARGS + 1];
|
typval_T argv[MAX_FUNC_ARGS + 1];
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
int dummy;
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
TV_LIST_ITER(args->vval.v_list, item, {
|
TV_LIST_ITER(args->vval.v_list, item, {
|
||||||
@ -1380,9 +1373,13 @@ int func_call(char_u *name, typval_T *args, partial_T *partial,
|
|||||||
tv_copy(TV_LIST_ITEM_TV(item), &argv[argc++]);
|
tv_copy(TV_LIST_ITEM_TV(item), &argv[argc++]);
|
||||||
});
|
});
|
||||||
|
|
||||||
r = call_func(name, -1, rettv, argc, argv, NULL,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
&dummy, true, partial, selfdict);
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = true;
|
||||||
|
funcexe.partial = partial;
|
||||||
|
funcexe.selfdict = selfdict;
|
||||||
|
r = call_func(name, -1, rettv, argc, argv, &funcexe);
|
||||||
|
|
||||||
func_call_skip_call:
|
func_call_skip_call:
|
||||||
// Free the arguments.
|
// Free the arguments.
|
||||||
@ -1425,10 +1422,6 @@ static void user_func_error(int error, const char_u *name)
|
|||||||
|
|
||||||
/// Call a function with its resolved parameters
|
/// Call a function with its resolved parameters
|
||||||
///
|
///
|
||||||
/// "argv_func", when not NULL, can be used to fill in arguments only when the
|
|
||||||
/// invoked function uses them. It is called like this:
|
|
||||||
/// new_argcount = argv_func(current_argcount, argv, called_func_argcount)
|
|
||||||
///
|
|
||||||
/// @return FAIL if function cannot be called, else OK (even if an error
|
/// @return FAIL if function cannot be called, else OK (even if an error
|
||||||
/// occurred while executing the function! Set `msg_list` to capture
|
/// occurred while executing the function! Set `msg_list` to capture
|
||||||
/// the error, see do_cmdline()).
|
/// the error, see do_cmdline()).
|
||||||
@ -1440,15 +1433,9 @@ call_func(
|
|||||||
int argcount_in, // number of "argvars"
|
int argcount_in, // number of "argvars"
|
||||||
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
||||||
// PLUS ONE elements!
|
// PLUS ONE elements!
|
||||||
ArgvFunc argv_func, // function to fill in argvars
|
funcexe_T *funcexe // more arguments
|
||||||
linenr_T firstline, // first line of range
|
|
||||||
linenr_T lastline, // last line of range
|
|
||||||
int *doesrange, // [out] function handled range
|
|
||||||
bool evaluate,
|
|
||||||
partial_T *partial, // optional, can be NULL
|
|
||||||
dict_T *selfdict_in // Dictionary for "self"
|
|
||||||
)
|
)
|
||||||
FUNC_ATTR_NONNULL_ARG(1, 3, 5, 9)
|
FUNC_ATTR_NONNULL_ARG(1, 3, 5, 6)
|
||||||
{
|
{
|
||||||
int ret = FAIL;
|
int ret = FAIL;
|
||||||
int error = ERROR_NONE;
|
int error = ERROR_NONE;
|
||||||
@ -1459,9 +1446,10 @@ call_func(
|
|||||||
char_u *name = NULL;
|
char_u *name = NULL;
|
||||||
int argcount = argcount_in;
|
int argcount = argcount_in;
|
||||||
typval_T *argvars = argvars_in;
|
typval_T *argvars = argvars_in;
|
||||||
dict_T *selfdict = selfdict_in;
|
dict_T *selfdict = funcexe->selfdict;
|
||||||
typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" is not NULL
|
typval_T argv[MAX_FUNC_ARGS + 1]; // used when "partial" is not NULL
|
||||||
int argv_clear = 0;
|
int argv_clear = 0;
|
||||||
|
partial_T *partial = funcexe->partial;
|
||||||
|
|
||||||
// Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
|
// Initialize rettv so that it is safe for caller to invoke clear_tv(rettv)
|
||||||
// even when call_func() returns FAIL.
|
// even when call_func() returns FAIL.
|
||||||
@ -1480,14 +1468,15 @@ call_func(
|
|||||||
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
||||||
}
|
}
|
||||||
|
|
||||||
*doesrange = false;
|
if (funcexe->doesrange != NULL) {
|
||||||
|
*funcexe->doesrange = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (partial != NULL) {
|
if (partial != NULL) {
|
||||||
// When the function has a partial with a dict and there is a dict
|
// When the function has a partial with a dict and there is a dict
|
||||||
// argument, use the dict argument. That is backwards compatible.
|
// argument, use the dict argument. That is backwards compatible.
|
||||||
// When the dict was bound explicitly use the one from the partial.
|
// When the dict was bound explicitly use the one from the partial.
|
||||||
if (partial->pt_dict != NULL
|
if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto)) {
|
||||||
&& (selfdict_in == NULL || !partial->pt_auto)) {
|
|
||||||
selfdict = partial->pt_dict;
|
selfdict = partial->pt_dict;
|
||||||
}
|
}
|
||||||
if (error == ERROR_NONE && partial->pt_argc > 0) {
|
if (error == ERROR_NONE && partial->pt_argc > 0) {
|
||||||
@ -1506,7 +1495,7 @@ call_func(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (error == ERROR_NONE && evaluate) {
|
if (error == ERROR_NONE && funcexe->evaluate) {
|
||||||
char_u *rfname = fname;
|
char_u *rfname = fname;
|
||||||
|
|
||||||
// Ignore "g:" before a function name.
|
// Ignore "g:" before a function name.
|
||||||
@ -1549,13 +1538,13 @@ call_func(
|
|||||||
cfunc_T cb = fp->uf_cb;
|
cfunc_T cb = fp->uf_cb;
|
||||||
error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
|
error = (*cb)(argcount, argvars, rettv, fp->uf_cb_state);
|
||||||
} else if (fp != NULL) {
|
} else if (fp != NULL) {
|
||||||
if (argv_func != NULL) {
|
if (funcexe->argv_func != NULL) {
|
||||||
// postponed filling in the arguments, do it now
|
// postponed filling in the arguments, do it now
|
||||||
argcount = argv_func(argcount, argvars, argv_clear,
|
argcount = funcexe->argv_func(argcount, argvars, argv_clear,
|
||||||
fp->uf_args.ga_len);
|
fp->uf_args.ga_len);
|
||||||
}
|
}
|
||||||
if (fp->uf_flags & FC_RANGE) {
|
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL) {
|
||||||
*doesrange = true;
|
*funcexe->doesrange = true;
|
||||||
}
|
}
|
||||||
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
|
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len) {
|
||||||
error = ERROR_TOOFEW;
|
error = ERROR_TOOFEW;
|
||||||
@ -1565,7 +1554,8 @@ call_func(
|
|||||||
error = ERROR_DICT;
|
error = ERROR_DICT;
|
||||||
} else {
|
} else {
|
||||||
// Call the user function.
|
// Call the user function.
|
||||||
call_user_func(fp, argcount, argvars, rettv, firstline, lastline,
|
call_user_func(fp, argcount, argvars, rettv, funcexe->firstline,
|
||||||
|
funcexe->lastline,
|
||||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||||
error = ERROR_NONE;
|
error = ERROR_NONE;
|
||||||
}
|
}
|
||||||
@ -2901,7 +2891,7 @@ void ex_call(exarg_T *eap)
|
|||||||
int len;
|
int len;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
linenr_T lnum;
|
linenr_T lnum;
|
||||||
int doesrange;
|
bool doesrange;
|
||||||
bool failed = false;
|
bool failed = false;
|
||||||
funcdict_T fudi;
|
funcdict_T fudi;
|
||||||
partial_T *partial = NULL;
|
partial_T *partial = NULL;
|
||||||
@ -2965,9 +2955,15 @@ void ex_call(exarg_T *eap)
|
|||||||
curwin->w_cursor.coladd = 0;
|
curwin->w_cursor.coladd = 0;
|
||||||
}
|
}
|
||||||
arg = startarg;
|
arg = startarg;
|
||||||
if (get_func_tv(name, -1, &rettv, &arg,
|
|
||||||
eap->line1, eap->line2, &doesrange,
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
true, partial, fudi.fd_dict) == FAIL) {
|
funcexe.firstline = eap->line1;
|
||||||
|
funcexe.lastline = eap->line2;
|
||||||
|
funcexe.doesrange = &doesrange;
|
||||||
|
funcexe.evaluate = true;
|
||||||
|
funcexe.partial = partial;
|
||||||
|
funcexe.selfdict = fudi.fd_dict;
|
||||||
|
if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL) {
|
||||||
failed = true;
|
failed = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -30,9 +30,32 @@ typedef enum {
|
|||||||
ERROR_DELETED,
|
ERROR_DELETED,
|
||||||
} FnameTransError;
|
} FnameTransError;
|
||||||
|
|
||||||
|
/// Used in funcexe_T. Returns the new argcount.
|
||||||
typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip,
|
typedef int (*ArgvFunc)(int current_argcount, typval_T *argv, int argskip,
|
||||||
int called_func_argcount);
|
int called_func_argcount);
|
||||||
|
|
||||||
|
/// Structure passed between functions dealing with function call execution.
|
||||||
|
typedef struct {
|
||||||
|
ArgvFunc argv_func; ///< when not NULL, can be used to fill in arguments only
|
||||||
|
///< when the invoked function uses them
|
||||||
|
linenr_T firstline; ///< first line of range
|
||||||
|
linenr_T lastline; ///< last line of range
|
||||||
|
bool *doesrange; ///< [out] if not NULL: function handled range
|
||||||
|
bool evaluate; ///< actually evaluate expressions
|
||||||
|
partial_T *partial; ///< for extra arguments
|
||||||
|
dict_T *selfdict; ///< Dictionary for "self"
|
||||||
|
} funcexe_T;
|
||||||
|
|
||||||
|
#define FUNCEXE_INIT (funcexe_T) { \
|
||||||
|
.argv_func = NULL, \
|
||||||
|
.firstline = 0, \
|
||||||
|
.lastline = 0, \
|
||||||
|
.doesrange = NULL, \
|
||||||
|
.evaluate = false, \
|
||||||
|
.partial = NULL, \
|
||||||
|
.selfdict = NULL, \
|
||||||
|
}
|
||||||
|
|
||||||
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
|
#define FUNCARG(fp, j) ((char_u **)(fp->uf_args.ga_data))[j]
|
||||||
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
|
#define FUNCLINE(fp, j) ((char_u **)(fp->uf_lines.ga_data))[j]
|
||||||
|
|
||||||
|
@ -780,13 +780,13 @@ int nlua_call(lua_State *lstate)
|
|||||||
|
|
||||||
try_start();
|
try_start();
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = true;
|
||||||
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
|
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
|
||||||
// (TRY_WRAP) to capture abort-causing non-exception errors.
|
// (TRY_WRAP) to capture abort-causing non-exception errors.
|
||||||
(void)call_func(name, (int)name_len, &rettv, nargs,
|
(void)call_func(name, (int)name_len, &rettv, nargs, vim_args, &funcexe);
|
||||||
vim_args, NULL,
|
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
|
||||||
&dummy, true, NULL, NULL);
|
|
||||||
if (!try_end(&err)) {
|
if (!try_end(&err)) {
|
||||||
nlua_push_typval(lstate, &rettv, false);
|
nlua_push_typval(lstate, &rettv, false);
|
||||||
}
|
}
|
||||||
|
@ -2531,12 +2531,12 @@ do_mouse (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int doesrange;
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
(void)call_func((char_u *)tab_page_click_defs[mouse_col].func,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
-1,
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
&rettv, ARRAY_SIZE(argv), argv, NULL,
|
funcexe.evaluate = true;
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
(void)call_func((char_u *)tab_page_click_defs[mouse_col].func, -1,
|
||||||
&doesrange, true, NULL, NULL);
|
&rettv, ARRAY_SIZE(argv), argv, &funcexe);
|
||||||
tv_clear(&rettv);
|
tv_clear(&rettv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6726,26 +6726,24 @@ static int vim_regsub_both(char_u *source, typval_T *expr, char_u *dest,
|
|||||||
|
|
||||||
if (expr != NULL) {
|
if (expr != NULL) {
|
||||||
typval_T argv[2];
|
typval_T argv[2];
|
||||||
int dummy;
|
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
staticList10_T matchList = TV_LIST_STATIC10_INIT;
|
staticList10_T matchList = TV_LIST_STATIC10_INIT;
|
||||||
|
|
||||||
rettv.v_type = VAR_STRING;
|
rettv.v_type = VAR_STRING;
|
||||||
rettv.vval.v_string = NULL;
|
rettv.vval.v_string = NULL;
|
||||||
argv[0].v_type = VAR_LIST;
|
argv[0].v_type = VAR_LIST;
|
||||||
argv[0].vval.v_list = &matchList.sl_list;
|
argv[0].vval.v_list = &matchList.sl_list;
|
||||||
|
funcexe_T funcexe = FUNCEXE_INIT;
|
||||||
|
funcexe.argv_func = fill_submatch_list;
|
||||||
|
funcexe.evaluate = true;
|
||||||
if (expr->v_type == VAR_FUNC) {
|
if (expr->v_type == VAR_FUNC) {
|
||||||
s = expr->vval.v_string;
|
s = expr->vval.v_string;
|
||||||
call_func(s, -1, &rettv, 1, argv,
|
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
||||||
fill_submatch_list, 0L, 0L, &dummy,
|
|
||||||
true, NULL, NULL);
|
|
||||||
} else if (expr->v_type == VAR_PARTIAL) {
|
} else if (expr->v_type == VAR_PARTIAL) {
|
||||||
partial_T *partial = expr->vval.v_partial;
|
partial_T *partial = expr->vval.v_partial;
|
||||||
|
|
||||||
s = partial_name(partial);
|
s = partial_name(partial);
|
||||||
call_func(s, -1, &rettv, 1, argv,
|
funcexe.partial = partial;
|
||||||
fill_submatch_list, 0L, 0L, &dummy,
|
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
||||||
true, partial, NULL);
|
|
||||||
}
|
}
|
||||||
if (tv_list_len(&matchList.sl_list) > 0) {
|
if (tv_list_len(&matchList.sl_list) > 0) {
|
||||||
// fill_submatch_list() was called.
|
// fill_submatch_list() was called.
|
||||||
|
Loading…
Reference in New Issue
Block a user