Mercurial > vim
diff src/userfunc.c @ 17606:ff097edaae89 v8.1.1800
patch 8.1.1800: function call functions have too many arguments
commit https://github.com/vim/vim/commit/c6538bcc1cdd1fb83732f22fdc69bd9bb66f968a
Author: Bram Moolenaar <Bram@vim.org>
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.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 03 Aug 2019 18:30:07 +0200 |
parents | 9088fafff9b3 |
children | e259d11e2900 |
line wrap: on
line diff
--- 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;