summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-08-03 18:17:11 +0200
committerBram Moolenaar <Bram@vim.org>2019-08-03 18:17:11 +0200
commitc6538bcc1cdd1fb83732f22fdc69bd9bb66f968a (patch)
tree80b89c210388f6e038ccbdc346f72a31bffd8430
parent749fa0af85232be1d44b77a09161f71cdbace62c (diff)
downloadvim-git-c6538bcc1cdd1fb83732f22fdc69bd9bb66f968a.tar.gz
patch 8.1.1800: function call functions have too many argumentsv8.1.1800
Problem: Function call functions have too many arguments. Solution: Pass values in a funcexe_T struct.
-rw-r--r--src/change.c4
-rw-r--r--src/channel.c20
-rw-r--r--src/eval.c54
-rw-r--r--src/ex_cmds2.c4
-rw-r--r--src/list.c9
-rw-r--r--src/popupwin.c8
-rw-r--r--src/proto/userfunc.pro6
-rw-r--r--src/regexp.c14
-rw-r--r--src/structs.h16
-rw-r--r--src/terminal.c12
-rw-r--r--src/userfunc.c97
-rw-r--r--src/version.c2
12 files changed, 134 insertions, 112 deletions
diff --git a/src/change.c b/src/change.c
index 0f6164b04..f83587d83 100644
--- a/src/change.c
+++ b/src/change.c
@@ -341,7 +341,6 @@ invoke_listeners(buf_T *buf)
{
listener_T *lnr;
typval_T rettv;
- int dummy;
typval_T argv[6];
listitem_T *li;
linenr_T start = MAXLNUM;
@@ -389,8 +388,7 @@ invoke_listeners(buf_T *buf)
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
{
- call_callback(&lnr->lr_callback, -1, &rettv,
- 5, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&lnr->lr_callback, -1, &rettv, 5, argv);
clear_tv(&rettv);
}
diff --git a/src/channel.c b/src/channel.c
index 6351c892c..8b0abdc30 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1633,7 +1633,6 @@ channel_write_new_lines(buf_T *buf)
invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
{
typval_T rettv;
- int dummy;
if (safe_to_invoke_callback == 0)
iemsg("INTERNAL: Invoking callback when it is not safe");
@@ -1641,8 +1640,7 @@ invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
argv[0].v_type = VAR_CHANNEL;
argv[0].vval.v_channel = channel;
- call_callback(callback, -1, &rettv, 2, argv, NULL,
- 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(callback, -1, &rettv, 2, argv);
clear_tv(&rettv);
channel_need_redraw = TRUE;
}
@@ -3029,7 +3027,6 @@ channel_close(channel_T *channel, int invoke_close_cb)
{
typval_T argv[1];
typval_T rettv;
- int dummy;
/* Increment the refcount to avoid the channel being freed
* halfway. */
@@ -3038,8 +3035,7 @@ channel_close(channel_T *channel, int invoke_close_cb)
(char *)channel->ch_close_cb.cb_name);
argv[0].v_type = VAR_CHANNEL;
argv[0].vval.v_channel = channel;
- call_callback(&channel->ch_close_cb, -1,
- &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&channel->ch_close_cb, -1, &rettv, 1, argv);
clear_tv(&rettv);
channel_need_redraw = TRUE;
@@ -5541,7 +5537,6 @@ job_cleanup(job_T *job)
{
typval_T argv[3];
typval_T rettv;
- int dummy;
/* Invoke the exit callback. Make sure the refcount is > 0. */
ch_log(job->jv_channel, "Invoking exit callback %s",
@@ -5551,8 +5546,7 @@ job_cleanup(job_T *job)
argv[0].vval.v_job = job;
argv[1].v_type = VAR_NUMBER;
argv[1].vval.v_number = job->jv_exitval;
- call_callback(&job->jv_exit_cb, -1,
- &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&job->jv_exit_cb, -1, &rettv, 2, argv);
clear_tv(&rettv);
--job->jv_refcount;
channel_need_redraw = TRUE;
@@ -6036,7 +6030,6 @@ job_stop(job_T *job, typval_T *argvars, char *type)
invoke_prompt_callback(void)
{
typval_T rettv;
- int dummy;
typval_T argv[2];
char_u *text;
char_u *prompt;
@@ -6059,8 +6052,7 @@ invoke_prompt_callback(void)
argv[0].vval.v_string = vim_strsave(text);
argv[1].v_type = VAR_UNKNOWN;
- call_callback(&curbuf->b_prompt_callback, -1,
- &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&curbuf->b_prompt_callback, -1, &rettv, 1, argv);
clear_tv(&argv[0]);
clear_tv(&rettv);
}
@@ -6072,7 +6064,6 @@ invoke_prompt_callback(void)
invoke_prompt_interrupt(void)
{
typval_T rettv;
- int dummy;
typval_T argv[1];
if (curbuf->b_prompt_interrupt.cb_name == NULL
@@ -6081,8 +6072,7 @@ invoke_prompt_interrupt(void)
argv[0].v_type = VAR_UNKNOWN;
got_int = FALSE; // don't skip executing commands
- call_callback(&curbuf->b_prompt_interrupt, -1,
- &rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&curbuf->b_prompt_interrupt, -1, &rettv, 0, argv);
clear_tv(&rettv);
return TRUE;
}
diff --git a/src/eval.c b/src/eval.c
index 278f30700..6d7bd6677 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -765,16 +765,17 @@ eval1_emsg(char_u **arg, typval_T *rettv, int evaluate)
eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
{
char_u *s;
- int dummy;
char_u buf[NUMBUFLEN];
+ funcexe_T funcexe;
if (expr->v_type == VAR_FUNC)
{
s = expr->vval.v_string;
if (s == NULL || *s == NUL)
return FAIL;
- if (call_func(s, -1, rettv, argc, argv, NULL,
- 0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.evaluate = TRUE;
+ if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
return FAIL;
}
else if (expr->v_type == VAR_PARTIAL)
@@ -784,8 +785,10 @@ eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
s = partial_name(partial);
if (s == NULL || *s == NUL)
return FAIL;
- if (call_func(s, -1, rettv, argc, argv, NULL,
- 0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.evaluate = TRUE;
+ funcexe.partial = partial;
+ if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
return FAIL;
}
else
@@ -1092,13 +1095,15 @@ call_vim_function(
typval_T *argv,
typval_T *rettv)
{
- int doesrange;
int ret;
+ funcexe_T funcexe;
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
- ret = call_func(func, -1, rettv, argc, argv, NULL,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &doesrange, TRUE, NULL, NULL);
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.evaluate = TRUE;
+ ret = call_func(func, -1, rettv, argc, argv, &funcexe);
if (ret == FAIL)
clear_tv(rettv);
@@ -4681,10 +4686,19 @@ eval7(
if (s == NULL)
ret = FAIL;
else
- /* Invoke the function. */
- ret = get_func_tv(s, len, rettv, arg,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &len, evaluate, partial, NULL);
+ {
+ funcexe_T funcexe;
+
+ // Invoke the function.
+ funcexe.argv_func = NULL;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.doesrange = &len;
+ funcexe.evaluate = evaluate;
+ funcexe.partial = partial;
+ funcexe.selfdict = NULL;
+ ret = get_func_tv(s, len, rettv, arg, &funcexe);
+ }
vim_free(s);
/* If evaluate is FALSE rettv->v_type was not set in
@@ -7359,7 +7373,6 @@ handle_subscript(
int ret = OK;
dict_T *selfdict = NULL;
char_u *s;
- int len;
typval_T functv;
// "." is ".name" lookup when we found a dict or when evaluating and
@@ -7377,6 +7390,7 @@ handle_subscript(
if (**arg == '(')
{
partial_T *pt = NULL;
+ funcexe_T funcexe;
/* need to copy the funcref so that we can clear rettv */
if (evaluate)
@@ -7395,9 +7409,15 @@ handle_subscript(
}
else
s = (char_u *)"";
- ret = get_func_tv(s, -1, rettv, arg,
- curwin->w_cursor.lnum, curwin->w_cursor.lnum,
- &len, evaluate, pt, selfdict);
+
+ funcexe.argv_func = NULL;
+ funcexe.firstline = curwin->w_cursor.lnum;
+ funcexe.lastline = curwin->w_cursor.lnum;
+ funcexe.doesrange = NULL;
+ funcexe.evaluate = evaluate;
+ funcexe.partial = pt;
+ funcexe.selfdict = selfdict;
+ ret = get_func_tv(s, -1, rettv, arg, &funcexe);
/* Clear the funcref afterwards, so that deleting it while
* evaluating the arguments is possible (see test55). */
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index a8be96dc3..c44ac8da1 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -110,15 +110,13 @@ create_timer(long msec, int repeat)
timer_callback(timer_T *timer)
{
typval_T rettv;
- int dummy;
typval_T argv[2];
argv[0].v_type = VAR_NUMBER;
argv[0].vval.v_number = (varnumber_T)timer->tr_id;
argv[1].v_type = VAR_UNKNOWN;
- call_callback(&timer->tr_callback, -1,
- &rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&timer->tr_callback, -1, &rettv, 1, argv);
clear_tv(&rettv);
}
diff --git a/src/list.c b/src/list.c
index c2bf4909c..fc348672b 100644
--- a/src/list.c
+++ b/src/list.c
@@ -1284,9 +1284,9 @@ item_compare2(const void *s1, const void *s2)
int res;
typval_T rettv;
typval_T argv[3];
- int dummy;
char_u *func_name;
partial_T *partial = sortinfo->item_compare_partial;
+ funcexe_T funcexe;
/* shortcut after failure in previous call; compare all items equal */
if (sortinfo->item_compare_func_err)
@@ -1306,8 +1306,11 @@ item_compare2(const void *s1, const void *s2)
copy_tv(&si2->item->li_tv, &argv[1]);
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
- res = call_func(func_name, -1, &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
- partial, sortinfo->item_compare_selfdict);
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.evaluate = TRUE;
+ funcexe.partial = partial;
+ funcexe.selfdict = sortinfo->item_compare_selfdict;
+ res = call_func(func_name, -1, &rettv, 2, argv, &funcexe);
clear_tv(&argv[0]);
clear_tv(&argv[1]);
diff --git a/src/popupwin.c b/src/popupwin.c
index 28ad48cfc..f2297f52e 100644
--- a/src/popupwin.c
+++ b/src/popupwin.c
@@ -1673,7 +1673,6 @@ f_popup_beval(typval_T *argvars, typval_T *rettv)
invoke_popup_callback(win_T *wp, typval_T *result)
{
typval_T rettv;
- int dummy;
typval_T argv[3];
argv[0].v_type = VAR_NUMBER;
@@ -1689,8 +1688,7 @@ invoke_popup_callback(win_T *wp, typval_T *result)
argv[2].v_type = VAR_UNKNOWN;
- call_callback(&wp->w_close_cb, -1,
- &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&wp->w_close_cb, -1, &rettv, 2, argv);
if (result != NULL)
clear_tv(&argv[1]);
clear_tv(&rettv);
@@ -2455,7 +2453,6 @@ invoke_popup_filter(win_T *wp, int c)
{
int res;
typval_T rettv;
- int dummy;
typval_T argv[3];
char_u buf[NUMBUFLEN];
linenr_T old_lnum = wp->w_cursor.lnum;
@@ -2481,8 +2478,7 @@ invoke_popup_filter(win_T *wp, int c)
argv[2].v_type = VAR_UNKNOWN;
// NOTE: The callback might close the popup, thus make "wp" invalid.
- call_callback(&wp->w_filter_cb, -1,
- &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
+ call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
popup_highlight_curline(wp);
diff --git a/src/proto/userfunc.pro b/src/proto/userfunc.pro
index 2b59473ea..3b11bb9af 100644
--- a/src/proto/userfunc.pro
+++ b/src/proto/userfunc.pro
@@ -3,15 +3,15 @@ void func_init(void);
hashtab_T *func_tbl_get(void);
int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
-int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict);
+int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
ufunc_T *find_func(char_u *name);
void save_funccal(funccal_entry_T *entry);
void restore_funccal(void);
funccall_T *get_current_funccal(void);
void free_all_functions(void);
int func_call(char_u *name, typval_T *args, partial_T *partial, dict_T *selfdict, typval_T *rettv);
-int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, dict_T *selfdict);
-int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, int (*argv_func)(int, typval_T *, int), linenr_T firstline, linenr_T lastline, int *doesrange, int evaluate, partial_T *partial, dict_T *selfdict_in);
+int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
+int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fdp, partial_T **partial);
void ex_function(exarg_T *eap);
int eval_fname_script(char_u *p);
diff --git a/src/regexp.c b/src/regexp.c
index 7d0ac6068..c95795d0c 100644
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -7416,31 +7416,31 @@ vim_regsub_both(
if (expr != NULL)
{
typval_T argv[2];
- int dummy;
char_u buf[NUMBUFLEN];
typval_T rettv;
staticList10_T matchList;
+ funcexe_T funcexe;
rettv.v_type = VAR_STRING;
rettv.vval.v_string = NULL;
argv[0].v_type = VAR_LIST;
argv[0].vval.v_list = &matchList.sl_list;
matchList.sl_list.lv_len = 0;
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.argv_func = fill_submatch_list;
+ funcexe.evaluate = TRUE;
if (expr->v_type == VAR_FUNC)
{
s = expr->vval.v_string;
- call_func(s, -1, &rettv,
- 1, argv, fill_submatch_list,
- 0L, 0L, &dummy, TRUE, NULL, NULL);
+ call_func(s, -1, &rettv, 1, argv, &funcexe);
}
else if (expr->v_type == VAR_PARTIAL)
{
partial_T *partial = expr->vval.v_partial;
s = partial_name(partial);
- call_func(s, -1, &rettv,
- 1, argv, fill_submatch_list,
- 0L, 0L, &dummy, TRUE, partial, NULL);
+ funcexe.partial = partial;
+ call_func(s, -1, &rettv, 1, argv, &funcexe);
}
if (matchList.sl_list.lv_len > 0)
/* fill_submatch_list() was called */
diff --git a/src/structs.h b/src/structs.h
index 7a21d270a..e3f6a73fe 100644
--- a/src/structs.h
+++ b/src/structs.h
@@ -1517,6 +1517,22 @@ struct funccall_S
// "func"
};
+// Struct passed between functions dealing with function call execution.
+//
+// "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)
+//
+typedef struct {
+ int (* argv_func)(int, typval_T *, int);
+ linenr_T firstline; // first line of range
+ linenr_T lastline; // last line of range
+ int *doesrange; // if not NULL: return: function handled range
+ int evaluate; // actually evaluate expressions
+ partial_T *partial; // for extra arguments
+ dict_T *selfdict; // Dictionary for "self"
+} funcexe_T;
+
/*
* Struct used by trans_function_name()
*/
diff --git a/src/terminal.c b/src/terminal.c
index 93b081707..51e242f19 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -3772,7 +3772,7 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
char_u *func;
typval_T argvars[2];
typval_T rettv;
- int doesrange;
+ funcexe_T funcexe;
if (item->li_next == NULL)
{
@@ -3790,11 +3790,11 @@ handle_call_command(term_T *term, channel_T *channel, listitem_T *item)
argvars[0].v_type = VAR_NUMBER;
argvars[0].vval.v_number = term->tl_buffer->b_fnum;
argvars[1] = item->li_next->li_tv;
- if (call_func(func, -1, &rettv,
- 2, argvars, /* argv_func */ NULL,
- /* firstline */ 1, /* lastline */ 1,
- &doesrange, /* evaluate */ TRUE,
- /* partial */ NULL, /* selfdict */ NULL) == OK)
+ vim_memset(&funcexe, 0, sizeof(funcexe));
+ funcexe.firstline = 1L;
+ funcexe.lastline = 1L;
+ funcexe.evaluate = TRUE;
+ if (call_func(func, -1, &rettv, 2, argvars, &funcexe) == OK)
{
clear_tv(&rettv);
ch_log(channel, "Function %s called", func);
diff --git a/src/userfunc.c b/src/userfunc.c
index a07b1b397..9d2063b34 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -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;
diff --git a/src/version.c b/src/version.c
index b2c4416ae..92d8482e8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -774,6 +774,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1800,
+/**/
1799,
/**/
1798,