]> granicus.if.org Git - vim/commitdiff
patch 8.1.1800: function call functions have too many arguments v8.1.1800
authorBram Moolenaar <Bram@vim.org>
Sat, 3 Aug 2019 16:17:11 +0000 (18:17 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 3 Aug 2019 16:17:11 +0000 (18:17 +0200)
Problem:    Function call functions have too many arguments.
Solution:   Pass values in a funcexe_T struct.

12 files changed:
src/change.c
src/channel.c
src/eval.c
src/ex_cmds2.c
src/list.c
src/popupwin.c
src/proto/userfunc.pro
src/regexp.c
src/structs.h
src/terminal.c
src/userfunc.c
src/version.c

index 0f6164b04b69168dd8185211ea9db529e9d5d419..f83587d8337bdfdc5230afac9f24d9c735cf29fe 100644 (file)
@@ -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);
     }
 
index 6351c892c3c16784e7691738606ed30a78b511c5..8b0abdc3020f7c1d5ab0cd91b0bb862778df3e26 100644 (file)
@@ -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;
 }
index 278f3070020a288f10f5b7fce4efc085bc54b937..6d7bd66775b742375b4bfa035a3a1bda0851170d 100644 (file)
@@ -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). */
index a8be96dc32b0a57f90efa709c3e81f97ced06084..c44ac8da171af8a246325fd9216f859cee448a9c 100644 (file)
@@ -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);
 }
 
index c2bf4909cc72ef1f9f3157dbc3f9f505d00e2194..fc348672b4458848a7b87ed9f58ebd9446a93cda 100644 (file)
@@ -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]);
 
index 28ad48cfc850526f7ac6394d83a7a1b85ad2b887..f2297f52e26c4292f6c8b1445c71a0b3dadea851 100644 (file)
@@ -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);
 
index 2b59473eacf9d1176db5fe9da4118026570b1ca9..3b11bb9af884d74e3c940f822583cd5370704dcf 100644 (file)
@@ -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);
index 7d0ac60681ab00eda1ac51ed3ec74b4e5a0776ca..c95795d0c9a7cc5e27047ceec453fc0a15e68250 100644 (file)
@@ -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 */
index 7a21d270a48776e7f1fd3cc0363bca7e5143fc8d..e3f6a73fe40da038b9b8d72c8a176b4029b957e4 100644 (file)
@@ -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()
  */
index 93b08170760a31c74167026a444388a8ddbad59a..51e242f1966d593aef7ea6ef7b45fce350065bab 100644 (file)
@@ -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);
index a07b1b3971bae7e05fab29705c5c07918d7cced1..9d2063b34bf948a83409abfee34ab27778911eb2 100644 (file)
@@ -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;
index b2c4416ae3de4fd9bc5139e630097d054dd1a24d..92d8482e8c79908d94898d6ff469c028b40c44d4 100644 (file)
@@ -773,6 +773,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1800,
 /**/
     1799,
 /**/