mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
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.
This commit is contained in:
@@ -432,12 +432,7 @@ get_func_tv(
|
||||
int len, // length of "name" or -1 to use strlen()
|
||||
typval_T *rettv,
|
||||
char_u **arg, // argument, pointing to the '('
|
||||
linenr_T firstline, // first line of range
|
||||
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"
|
||||
funcexe_T *funcexe) // various values
|
||||
{
|
||||
char_u *argp;
|
||||
int ret = OK;
|
||||
@@ -448,12 +443,13 @@ get_func_tv(
|
||||
* Get the arguments.
|
||||
*/
|
||||
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 ',' */
|
||||
if (*argp == ')' || *argp == ',' || *argp == NUL)
|
||||
break;
|
||||
if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
|
||||
if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL)
|
||||
{
|
||||
ret = FAIL;
|
||||
break;
|
||||
@@ -483,8 +479,7 @@ get_func_tv(
|
||||
&argvars[i];
|
||||
}
|
||||
|
||||
ret = call_func(name, len, rettv, argcount, argvars, NULL,
|
||||
firstline, lastline, doesrange, evaluate, partial, selfdict);
|
||||
ret = call_func(name, len, rettv, argcount, argvars, funcexe);
|
||||
|
||||
funcargs.ga_len -= i;
|
||||
}
|
||||
@@ -1416,7 +1411,6 @@ func_call(
|
||||
listitem_T *item;
|
||||
typval_T argv[MAX_FUNC_ARGS + 1];
|
||||
int argc = 0;
|
||||
int dummy;
|
||||
int r = 0;
|
||||
|
||||
for (item = args->vval.v_list->lv_first; item != NULL;
|
||||
@@ -1434,9 +1428,18 @@ func_call(
|
||||
}
|
||||
|
||||
if (item == NULL)
|
||||
r = call_func(name, -1, rettv, argc, argv, NULL,
|
||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||
&dummy, TRUE, partial, selfdict);
|
||||
{
|
||||
funcexe_T funcexe;
|
||||
|
||||
funcexe.argv_func = NULL;
|
||||
funcexe.firstline = curwin->w_cursor.lnum;
|
||||
funcexe.lastline = curwin->w_cursor.lnum;
|
||||
funcexe.doesrange = NULL;
|
||||
funcexe.evaluate = TRUE;
|
||||
funcexe.partial = partial;
|
||||
funcexe.selfdict = selfdict;
|
||||
r = call_func(name, -1, rettv, argc, argv, &funcexe);
|
||||
}
|
||||
|
||||
/* Free the arguments. */
|
||||
while (argc > 0)
|
||||
@@ -1454,28 +1457,21 @@ call_callback(
|
||||
int len, // length of "name" or -1 to use strlen()
|
||||
typval_T *rettv, // return value goes here
|
||||
int argcount, // number of "argvars"
|
||||
typval_T *argvars, // vars for arguments, must have "argcount"
|
||||
typval_T *argvars) // vars for arguments, must have "argcount"
|
||||
// PLUS ONE elements!
|
||||
int (* argv_func)(int, typval_T *, int),
|
||||
// function to fill in argvars
|
||||
linenr_T firstline, // first line of range
|
||||
linenr_T lastline, // last line of range
|
||||
int *doesrange, // return: function handled range
|
||||
int evaluate,
|
||||
dict_T *selfdict) // Dictionary for "self"
|
||||
{
|
||||
funcexe_T funcexe;
|
||||
|
||||
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||
funcexe.evaluate = TRUE;
|
||||
funcexe.partial = callback->cb_partial;
|
||||
return call_func(callback->cb_name, len, rettv, argcount, argvars,
|
||||
argv_func, firstline, lastline, doesrange, evaluate,
|
||||
callback->cb_partial, selfdict);
|
||||
&funcexe);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 when the function can't be called, OK otherwise.
|
||||
* Also returns OK when an error was encountered while executing the function.
|
||||
*/
|
||||
@@ -1487,14 +1483,7 @@ call_func(
|
||||
int argcount_in, // number of "argvars"
|
||||
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
||||
// PLUS ONE elements!
|
||||
int (* argv_func)(int, typval_T *, int),
|
||||
// function to fill in argvars
|
||||
linenr_T firstline, // first line of range
|
||||
linenr_T lastline, // last line of range
|
||||
int *doesrange, // return: function handled range
|
||||
int evaluate,
|
||||
partial_T *partial, // optional, can be NULL
|
||||
dict_T *selfdict_in) // Dictionary for "self"
|
||||
funcexe_T *funcexe) // more arguments
|
||||
{
|
||||
int ret = FAIL;
|
||||
int error = ERROR_NONE;
|
||||
@@ -1506,9 +1495,10 @@ call_func(
|
||||
char_u *name;
|
||||
int argcount = argcount_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 */
|
||||
int argv_clear = 0;
|
||||
partial_T *partial = funcexe->partial;
|
||||
|
||||
// Make a copy of the name, if it comes from a funcref variable it could
|
||||
// be changed or deleted in the called function.
|
||||
@@ -1518,15 +1508,15 @@ call_func(
|
||||
|
||||
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
||||
|
||||
*doesrange = FALSE;
|
||||
if (funcexe->doesrange != NULL)
|
||||
*funcexe->doesrange = FALSE;
|
||||
|
||||
if (partial != NULL)
|
||||
{
|
||||
/* When the function has a partial with a dict and there is a dict
|
||||
* argument, use the dict argument. That is backwards compatible.
|
||||
* When the dict was bound explicitly use the one from the partial. */
|
||||
if (partial->pt_dict != NULL
|
||||
&& (selfdict_in == NULL || !partial->pt_auto))
|
||||
if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto))
|
||||
selfdict = partial->pt_dict;
|
||||
if (error == ERROR_NONE && partial->pt_argc > 0)
|
||||
{
|
||||
@@ -1542,7 +1532,7 @@ call_func(
|
||||
/*
|
||||
* Execute the function if executing and no errors were detected.
|
||||
*/
|
||||
if (!evaluate)
|
||||
if (!funcexe->evaluate)
|
||||
{
|
||||
// Not evaluating, which means the return value is unknown. This
|
||||
// matters for giving error messages.
|
||||
@@ -1590,11 +1580,12 @@ call_func(
|
||||
error = ERROR_DELETED;
|
||||
else if (fp != NULL)
|
||||
{
|
||||
if (argv_func != NULL)
|
||||
argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
|
||||
if (funcexe->argv_func != NULL)
|
||||
argcount = funcexe->argv_func(argcount, argvars,
|
||||
fp->uf_args.ga_len);
|
||||
|
||||
if (fp->uf_flags & FC_RANGE)
|
||||
*doesrange = TRUE;
|
||||
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
|
||||
*funcexe->doesrange = TRUE;
|
||||
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
|
||||
error = ERROR_TOOFEW;
|
||||
else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
|
||||
@@ -1621,7 +1612,7 @@ call_func(
|
||||
}
|
||||
++fp->uf_calls;
|
||||
call_user_func(fp, argcount, argvars, rettv,
|
||||
firstline, lastline,
|
||||
funcexe->firstline, funcexe->lastline,
|
||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
||||
/* Function was unreferenced while being used, free it
|
||||
@@ -3112,6 +3103,8 @@ ex_call(exarg_T *eap)
|
||||
lnum = eap->line1;
|
||||
for ( ; lnum <= eap->line2; ++lnum)
|
||||
{
|
||||
funcexe_T funcexe;
|
||||
|
||||
if (!eap->skip && eap->addr_count > 0)
|
||||
{
|
||||
if (lnum > curbuf->b_ml.ml_line_count)
|
||||
@@ -3126,9 +3119,15 @@ ex_call(exarg_T *eap)
|
||||
curwin->w_cursor.coladd = 0;
|
||||
}
|
||||
arg = startarg;
|
||||
if (get_func_tv(name, -1, &rettv, &arg,
|
||||
eap->line1, eap->line2, &doesrange,
|
||||
!eap->skip, partial, fudi.fd_dict) == FAIL)
|
||||
|
||||
funcexe.argv_func = NULL;
|
||||
funcexe.firstline = eap->line1;
|
||||
funcexe.lastline = eap->line2;
|
||||
funcexe.doesrange = &doesrange;
|
||||
funcexe.evaluate = !eap->skip;
|
||||
funcexe.partial = partial;
|
||||
funcexe.selfdict = fudi.fd_dict;
|
||||
if (get_func_tv(name, -1, &rettv, &arg, &funcexe) == FAIL)
|
||||
{
|
||||
failed = TRUE;
|
||||
break;
|
||||
|
Reference in New Issue
Block a user