forked from aniani/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.
This commit is contained in:
parent
749fa0af85
commit
c6538bcc1c
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
54
src/eval.c
54
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). */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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]);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
14
src/regexp.c
14
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 */
|
||||
|
@ -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()
|
||||
*/
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -773,6 +773,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1800,
|
||||
/**/
|
||||
1799,
|
||||
/**/
|
||||
|
Loading…
x
Reference in New Issue
Block a user