# HG changeset patch # User Bram Moolenaar # Date 1564849807 -7200 # Node ID ff097edaae8914219deb988b615b85fc326eed3d # Parent bb1b495f4e059092ad0d04aaaaaa2e38e72ed54d patch 8.1.1800: function call functions have too many arguments commit https://github.com/vim/vim/commit/c6538bcc1cdd1fb83732f22fdc69bd9bb66f968a Author: Bram Moolenaar Date: Sat Aug 3 18:17:11 2019 +0200 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. diff --git a/src/change.c b/src/change.c --- 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 --- 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, call 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 in { 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 in (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, 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 --- a/src/eval.c +++ b/src/eval.c @@ -765,16 +765,17 @@ eval1_emsg(char_u **arg, typval_T *rettv 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_ 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 --- 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 --- a/src/list.c +++ b/src/list.c @@ -1284,9 +1284,9 @@ item_compare2(const void *s1, const void 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 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 --- a/src/popupwin.c +++ b/src/popupwin.c @@ -1673,7 +1673,6 @@ f_popup_beval(typval_T *argvars, typval_ 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_ 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 --- 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 --- 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 --- 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 --- a/src/terminal.c +++ b/src/terminal.c @@ -3772,7 +3772,7 @@ handle_call_command(term_T *term, channe 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, channe 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 --- 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 (fp->uf_flags & FC_RANGE) - *doesrange = TRUE; + if (funcexe->argv_func != NULL) + argcount = funcexe->argv_func(argcount, argvars, + fp->uf_args.ga_len); + + 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 --- 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,