mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
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;
|
listener_T *lnr;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[6];
|
typval_T argv[6];
|
||||||
listitem_T *li;
|
listitem_T *li;
|
||||||
linenr_T start = MAXLNUM;
|
linenr_T start = MAXLNUM;
|
||||||
@ -389,8 +388,7 @@ invoke_listeners(buf_T *buf)
|
|||||||
|
|
||||||
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
for (lnr = buf->b_listener; lnr != NULL; lnr = lnr->lr_next)
|
||||||
{
|
{
|
||||||
call_callback(&lnr->lr_callback, -1, &rettv,
|
call_callback(&lnr->lr_callback, -1, &rettv, 5, argv);
|
||||||
5, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
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)
|
invoke_callback(channel_T *channel, callback_T *callback, typval_T *argv)
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
|
|
||||||
if (safe_to_invoke_callback == 0)
|
if (safe_to_invoke_callback == 0)
|
||||||
iemsg("INTERNAL: Invoking callback when it is not safe");
|
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].v_type = VAR_CHANNEL;
|
||||||
argv[0].vval.v_channel = channel;
|
argv[0].vval.v_channel = channel;
|
||||||
|
|
||||||
call_callback(callback, -1, &rettv, 2, argv, NULL,
|
call_callback(callback, -1, &rettv, 2, argv);
|
||||||
0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
channel_need_redraw = TRUE;
|
channel_need_redraw = TRUE;
|
||||||
}
|
}
|
||||||
@ -3029,7 +3027,6 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
|||||||
{
|
{
|
||||||
typval_T argv[1];
|
typval_T argv[1];
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
|
|
||||||
/* Increment the refcount to avoid the channel being freed
|
/* Increment the refcount to avoid the channel being freed
|
||||||
* halfway. */
|
* halfway. */
|
||||||
@ -3038,8 +3035,7 @@ channel_close(channel_T *channel, int invoke_close_cb)
|
|||||||
(char *)channel->ch_close_cb.cb_name);
|
(char *)channel->ch_close_cb.cb_name);
|
||||||
argv[0].v_type = VAR_CHANNEL;
|
argv[0].v_type = VAR_CHANNEL;
|
||||||
argv[0].vval.v_channel = channel;
|
argv[0].vval.v_channel = channel;
|
||||||
call_callback(&channel->ch_close_cb, -1,
|
call_callback(&channel->ch_close_cb, -1, &rettv, 1, argv);
|
||||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
channel_need_redraw = TRUE;
|
channel_need_redraw = TRUE;
|
||||||
|
|
||||||
@ -5541,7 +5537,6 @@ job_cleanup(job_T *job)
|
|||||||
{
|
{
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
|
|
||||||
/* Invoke the exit callback. Make sure the refcount is > 0. */
|
/* Invoke the exit callback. Make sure the refcount is > 0. */
|
||||||
ch_log(job->jv_channel, "Invoking exit callback %s",
|
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[0].vval.v_job = job;
|
||||||
argv[1].v_type = VAR_NUMBER;
|
argv[1].v_type = VAR_NUMBER;
|
||||||
argv[1].vval.v_number = job->jv_exitval;
|
argv[1].vval.v_number = job->jv_exitval;
|
||||||
call_callback(&job->jv_exit_cb, -1,
|
call_callback(&job->jv_exit_cb, -1, &rettv, 2, argv);
|
||||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
--job->jv_refcount;
|
--job->jv_refcount;
|
||||||
channel_need_redraw = TRUE;
|
channel_need_redraw = TRUE;
|
||||||
@ -6036,7 +6030,6 @@ job_stop(job_T *job, typval_T *argvars, char *type)
|
|||||||
invoke_prompt_callback(void)
|
invoke_prompt_callback(void)
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[2];
|
typval_T argv[2];
|
||||||
char_u *text;
|
char_u *text;
|
||||||
char_u *prompt;
|
char_u *prompt;
|
||||||
@ -6059,8 +6052,7 @@ invoke_prompt_callback(void)
|
|||||||
argv[0].vval.v_string = vim_strsave(text);
|
argv[0].vval.v_string = vim_strsave(text);
|
||||||
argv[1].v_type = VAR_UNKNOWN;
|
argv[1].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
call_callback(&curbuf->b_prompt_callback, -1,
|
call_callback(&curbuf->b_prompt_callback, -1, &rettv, 1, argv);
|
||||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&argv[0]);
|
clear_tv(&argv[0]);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
@ -6072,7 +6064,6 @@ invoke_prompt_callback(void)
|
|||||||
invoke_prompt_interrupt(void)
|
invoke_prompt_interrupt(void)
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[1];
|
typval_T argv[1];
|
||||||
|
|
||||||
if (curbuf->b_prompt_interrupt.cb_name == NULL
|
if (curbuf->b_prompt_interrupt.cb_name == NULL
|
||||||
@ -6081,8 +6072,7 @@ invoke_prompt_interrupt(void)
|
|||||||
argv[0].v_type = VAR_UNKNOWN;
|
argv[0].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
got_int = FALSE; // don't skip executing commands
|
got_int = FALSE; // don't skip executing commands
|
||||||
call_callback(&curbuf->b_prompt_interrupt, -1,
|
call_callback(&curbuf->b_prompt_interrupt, -1, &rettv, 0, argv);
|
||||||
&rettv, 0, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
return TRUE;
|
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)
|
eval_expr_typval(typval_T *expr, typval_T *argv, int argc, typval_T *rettv)
|
||||||
{
|
{
|
||||||
char_u *s;
|
char_u *s;
|
||||||
int dummy;
|
|
||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
if (expr->v_type == VAR_FUNC)
|
if (expr->v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
s = expr->vval.v_string;
|
s = expr->vval.v_string;
|
||||||
if (s == NULL || *s == NUL)
|
if (s == NULL || *s == NUL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (call_func(s, -1, rettv, argc, argv, NULL,
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
0L, 0L, &dummy, TRUE, NULL, NULL) == FAIL)
|
funcexe.evaluate = TRUE;
|
||||||
|
if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
else if (expr->v_type == VAR_PARTIAL)
|
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);
|
s = partial_name(partial);
|
||||||
if (s == NULL || *s == NUL)
|
if (s == NULL || *s == NUL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
if (call_func(s, -1, rettv, argc, argv, NULL,
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
0L, 0L, &dummy, TRUE, partial, NULL) == FAIL)
|
funcexe.evaluate = TRUE;
|
||||||
|
funcexe.partial = partial;
|
||||||
|
if (call_func(s, -1, rettv, argc, argv, &funcexe) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1092,13 +1095,15 @@ call_vim_function(
|
|||||||
typval_T *argv,
|
typval_T *argv,
|
||||||
typval_T *rettv)
|
typval_T *rettv)
|
||||||
{
|
{
|
||||||
int doesrange;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||||
ret = call_func(func, -1, rettv, argc, argv, NULL,
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe.firstline = curwin->w_cursor.lnum;
|
||||||
&doesrange, TRUE, NULL, NULL);
|
funcexe.lastline = curwin->w_cursor.lnum;
|
||||||
|
funcexe.evaluate = TRUE;
|
||||||
|
ret = call_func(func, -1, rettv, argc, argv, &funcexe);
|
||||||
if (ret == FAIL)
|
if (ret == FAIL)
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
|
|
||||||
@ -4681,10 +4686,19 @@ eval7(
|
|||||||
if (s == NULL)
|
if (s == NULL)
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
else
|
else
|
||||||
/* Invoke the function. */
|
{
|
||||||
ret = get_func_tv(s, len, rettv, arg,
|
funcexe_T funcexe;
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
|
||||||
&len, evaluate, partial, NULL);
|
// 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);
|
vim_free(s);
|
||||||
|
|
||||||
/* If evaluate is FALSE rettv->v_type was not set in
|
/* If evaluate is FALSE rettv->v_type was not set in
|
||||||
@ -7359,7 +7373,6 @@ handle_subscript(
|
|||||||
int ret = OK;
|
int ret = OK;
|
||||||
dict_T *selfdict = NULL;
|
dict_T *selfdict = NULL;
|
||||||
char_u *s;
|
char_u *s;
|
||||||
int len;
|
|
||||||
typval_T functv;
|
typval_T functv;
|
||||||
|
|
||||||
// "." is ".name" lookup when we found a dict or when evaluating and
|
// "." is ".name" lookup when we found a dict or when evaluating and
|
||||||
@ -7377,6 +7390,7 @@ handle_subscript(
|
|||||||
if (**arg == '(')
|
if (**arg == '(')
|
||||||
{
|
{
|
||||||
partial_T *pt = NULL;
|
partial_T *pt = NULL;
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
/* need to copy the funcref so that we can clear rettv */
|
/* need to copy the funcref so that we can clear rettv */
|
||||||
if (evaluate)
|
if (evaluate)
|
||||||
@ -7395,9 +7409,15 @@ handle_subscript(
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
s = (char_u *)"";
|
s = (char_u *)"";
|
||||||
ret = get_func_tv(s, -1, rettv, arg,
|
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe.argv_func = NULL;
|
||||||
&len, evaluate, pt, selfdict);
|
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
|
/* Clear the funcref afterwards, so that deleting it while
|
||||||
* evaluating the arguments is possible (see test55). */
|
* evaluating the arguments is possible (see test55). */
|
||||||
|
@ -110,15 +110,13 @@ create_timer(long msec, int repeat)
|
|||||||
timer_callback(timer_T *timer)
|
timer_callback(timer_T *timer)
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[2];
|
typval_T argv[2];
|
||||||
|
|
||||||
argv[0].v_type = VAR_NUMBER;
|
argv[0].v_type = VAR_NUMBER;
|
||||||
argv[0].vval.v_number = (varnumber_T)timer->tr_id;
|
argv[0].vval.v_number = (varnumber_T)timer->tr_id;
|
||||||
argv[1].v_type = VAR_UNKNOWN;
|
argv[1].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
call_callback(&timer->tr_callback, -1,
|
call_callback(&timer->tr_callback, -1, &rettv, 1, argv);
|
||||||
&rettv, 1, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1284,9 +1284,9 @@ item_compare2(const void *s1, const void *s2)
|
|||||||
int res;
|
int res;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
int dummy;
|
|
||||||
char_u *func_name;
|
char_u *func_name;
|
||||||
partial_T *partial = sortinfo->item_compare_partial;
|
partial_T *partial = sortinfo->item_compare_partial;
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
/* shortcut after failure in previous call; compare all items equal */
|
/* shortcut after failure in previous call; compare all items equal */
|
||||||
if (sortinfo->item_compare_func_err)
|
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]);
|
copy_tv(&si2->item->li_tv, &argv[1]);
|
||||||
|
|
||||||
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
rettv.v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||||
res = call_func(func_name, -1, &rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE,
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
partial, sortinfo->item_compare_selfdict);
|
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[0]);
|
||||||
clear_tv(&argv[1]);
|
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)
|
invoke_popup_callback(win_T *wp, typval_T *result)
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
|
|
||||||
argv[0].v_type = VAR_NUMBER;
|
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;
|
argv[2].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
call_callback(&wp->w_close_cb, -1,
|
call_callback(&wp->w_close_cb, -1, &rettv, 2, argv);
|
||||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
clear_tv(&argv[1]);
|
clear_tv(&argv[1]);
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
@ -2455,7 +2453,6 @@ invoke_popup_filter(win_T *wp, int c)
|
|||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int dummy;
|
|
||||||
typval_T argv[3];
|
typval_T argv[3];
|
||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
linenr_T old_lnum = wp->w_cursor.lnum;
|
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;
|
argv[2].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
// NOTE: The callback might close the popup, thus make "wp" invalid.
|
// NOTE: The callback might close the popup, thus make "wp" invalid.
|
||||||
call_callback(&wp->w_filter_cb, -1,
|
call_callback(&wp->w_filter_cb, -1, &rettv, 2, argv);
|
||||||
&rettv, 2, argv, NULL, 0L, 0L, &dummy, TRUE, NULL);
|
|
||||||
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
if (win_valid_popup(wp) && old_lnum != wp->w_cursor.lnum)
|
||||||
popup_highlight_curline(wp);
|
popup_highlight_curline(wp);
|
||||||
|
|
||||||
|
@ -3,15 +3,15 @@ void func_init(void);
|
|||||||
hashtab_T *func_tbl_get(void);
|
hashtab_T *func_tbl_get(void);
|
||||||
int get_lambda_tv(char_u **arg, typval_T *rettv, int evaluate);
|
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);
|
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);
|
ufunc_T *find_func(char_u *name);
|
||||||
void save_funccal(funccal_entry_T *entry);
|
void save_funccal(funccal_entry_T *entry);
|
||||||
void restore_funccal(void);
|
void restore_funccal(void);
|
||||||
funccall_T *get_current_funccal(void);
|
funccall_T *get_current_funccal(void);
|
||||||
void free_all_functions(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 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_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, 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_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);
|
char_u *trans_function_name(char_u **pp, int skip, int flags, funcdict_T *fdp, partial_T **partial);
|
||||||
void ex_function(exarg_T *eap);
|
void ex_function(exarg_T *eap);
|
||||||
int eval_fname_script(char_u *p);
|
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)
|
if (expr != NULL)
|
||||||
{
|
{
|
||||||
typval_T argv[2];
|
typval_T argv[2];
|
||||||
int dummy;
|
|
||||||
char_u buf[NUMBUFLEN];
|
char_u buf[NUMBUFLEN];
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
staticList10_T matchList;
|
staticList10_T matchList;
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
rettv.v_type = VAR_STRING;
|
rettv.v_type = VAR_STRING;
|
||||||
rettv.vval.v_string = NULL;
|
rettv.vval.v_string = NULL;
|
||||||
argv[0].v_type = VAR_LIST;
|
argv[0].v_type = VAR_LIST;
|
||||||
argv[0].vval.v_list = &matchList.sl_list;
|
argv[0].vval.v_list = &matchList.sl_list;
|
||||||
matchList.sl_list.lv_len = 0;
|
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)
|
if (expr->v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
s = expr->vval.v_string;
|
s = expr->vval.v_string;
|
||||||
call_func(s, -1, &rettv,
|
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
||||||
1, argv, fill_submatch_list,
|
|
||||||
0L, 0L, &dummy, TRUE, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
else if (expr->v_type == VAR_PARTIAL)
|
else if (expr->v_type == VAR_PARTIAL)
|
||||||
{
|
{
|
||||||
partial_T *partial = expr->vval.v_partial;
|
partial_T *partial = expr->vval.v_partial;
|
||||||
|
|
||||||
s = partial_name(partial);
|
s = partial_name(partial);
|
||||||
call_func(s, -1, &rettv,
|
funcexe.partial = partial;
|
||||||
1, argv, fill_submatch_list,
|
call_func(s, -1, &rettv, 1, argv, &funcexe);
|
||||||
0L, 0L, &dummy, TRUE, partial, NULL);
|
|
||||||
}
|
}
|
||||||
if (matchList.sl_list.lv_len > 0)
|
if (matchList.sl_list.lv_len > 0)
|
||||||
/* fill_submatch_list() was called */
|
/* fill_submatch_list() was called */
|
||||||
|
@ -1517,6 +1517,22 @@ struct funccall_S
|
|||||||
// "func"
|
// "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()
|
* 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;
|
char_u *func;
|
||||||
typval_T argvars[2];
|
typval_T argvars[2];
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
int doesrange;
|
funcexe_T funcexe;
|
||||||
|
|
||||||
if (item->li_next == NULL)
|
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].v_type = VAR_NUMBER;
|
||||||
argvars[0].vval.v_number = term->tl_buffer->b_fnum;
|
argvars[0].vval.v_number = term->tl_buffer->b_fnum;
|
||||||
argvars[1] = item->li_next->li_tv;
|
argvars[1] = item->li_next->li_tv;
|
||||||
if (call_func(func, -1, &rettv,
|
vim_memset(&funcexe, 0, sizeof(funcexe));
|
||||||
2, argvars, /* argv_func */ NULL,
|
funcexe.firstline = 1L;
|
||||||
/* firstline */ 1, /* lastline */ 1,
|
funcexe.lastline = 1L;
|
||||||
&doesrange, /* evaluate */ TRUE,
|
funcexe.evaluate = TRUE;
|
||||||
/* partial */ NULL, /* selfdict */ NULL) == OK)
|
if (call_func(func, -1, &rettv, 2, argvars, &funcexe) == OK)
|
||||||
{
|
{
|
||||||
clear_tv(&rettv);
|
clear_tv(&rettv);
|
||||||
ch_log(channel, "Function %s called", func);
|
ch_log(channel, "Function %s called", func);
|
||||||
|
@ -432,12 +432,7 @@ get_func_tv(
|
|||||||
int len, // length of "name" or -1 to use strlen()
|
int len, // length of "name" or -1 to use strlen()
|
||||||
typval_T *rettv,
|
typval_T *rettv,
|
||||||
char_u **arg, // argument, pointing to the '('
|
char_u **arg, // argument, pointing to the '('
|
||||||
linenr_T firstline, // first line of range
|
funcexe_T *funcexe) // various values
|
||||||
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"
|
|
||||||
{
|
{
|
||||||
char_u *argp;
|
char_u *argp;
|
||||||
int ret = OK;
|
int ret = OK;
|
||||||
@ -448,12 +443,13 @@ get_func_tv(
|
|||||||
* Get the arguments.
|
* Get the arguments.
|
||||||
*/
|
*/
|
||||||
argp = *arg;
|
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 ',' */
|
argp = skipwhite(argp + 1); /* skip the '(' or ',' */
|
||||||
if (*argp == ')' || *argp == ',' || *argp == NUL)
|
if (*argp == ')' || *argp == ',' || *argp == NUL)
|
||||||
break;
|
break;
|
||||||
if (eval1(&argp, &argvars[argcount], evaluate) == FAIL)
|
if (eval1(&argp, &argvars[argcount], funcexe->evaluate) == FAIL)
|
||||||
{
|
{
|
||||||
ret = FAIL;
|
ret = FAIL;
|
||||||
break;
|
break;
|
||||||
@ -483,8 +479,7 @@ get_func_tv(
|
|||||||
&argvars[i];
|
&argvars[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = call_func(name, len, rettv, argcount, argvars, NULL,
|
ret = call_func(name, len, rettv, argcount, argvars, funcexe);
|
||||||
firstline, lastline, doesrange, evaluate, partial, selfdict);
|
|
||||||
|
|
||||||
funcargs.ga_len -= i;
|
funcargs.ga_len -= i;
|
||||||
}
|
}
|
||||||
@ -1416,7 +1411,6 @@ func_call(
|
|||||||
listitem_T *item;
|
listitem_T *item;
|
||||||
typval_T argv[MAX_FUNC_ARGS + 1];
|
typval_T argv[MAX_FUNC_ARGS + 1];
|
||||||
int argc = 0;
|
int argc = 0;
|
||||||
int dummy;
|
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
for (item = args->vval.v_list->lv_first; item != NULL;
|
for (item = args->vval.v_list->lv_first; item != NULL;
|
||||||
@ -1434,9 +1428,18 @@ func_call(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (item == NULL)
|
if (item == NULL)
|
||||||
r = call_func(name, -1, rettv, argc, argv, NULL,
|
{
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
funcexe_T funcexe;
|
||||||
&dummy, TRUE, partial, selfdict);
|
|
||||||
|
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. */
|
/* Free the arguments. */
|
||||||
while (argc > 0)
|
while (argc > 0)
|
||||||
@ -1454,28 +1457,21 @@ call_callback(
|
|||||||
int len, // length of "name" or -1 to use strlen()
|
int len, // length of "name" or -1 to use strlen()
|
||||||
typval_T *rettv, // return value goes here
|
typval_T *rettv, // return value goes here
|
||||||
int argcount, // number of "argvars"
|
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!
|
// 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,
|
return call_func(callback->cb_name, len, rettv, argcount, argvars,
|
||||||
argv_func, firstline, lastline, doesrange, evaluate,
|
&funcexe);
|
||||||
callback->cb_partial, selfdict);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call a function with its resolved parameters
|
* 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.
|
* Return FAIL when the function can't be called, OK otherwise.
|
||||||
* Also returns OK when an error was encountered while executing the function.
|
* Also returns OK when an error was encountered while executing the function.
|
||||||
*/
|
*/
|
||||||
@ -1487,14 +1483,7 @@ call_func(
|
|||||||
int argcount_in, // number of "argvars"
|
int argcount_in, // number of "argvars"
|
||||||
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
typval_T *argvars_in, // vars for arguments, must have "argcount"
|
||||||
// PLUS ONE elements!
|
// PLUS ONE elements!
|
||||||
int (* argv_func)(int, typval_T *, int),
|
funcexe_T *funcexe) // more arguments
|
||||||
// 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"
|
|
||||||
{
|
{
|
||||||
int ret = FAIL;
|
int ret = FAIL;
|
||||||
int error = ERROR_NONE;
|
int error = ERROR_NONE;
|
||||||
@ -1506,9 +1495,10 @@ call_func(
|
|||||||
char_u *name;
|
char_u *name;
|
||||||
int argcount = argcount_in;
|
int argcount = argcount_in;
|
||||||
typval_T *argvars = argvars_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 */
|
typval_T argv[MAX_FUNC_ARGS + 1]; /* used when "partial" is not NULL */
|
||||||
int argv_clear = 0;
|
int argv_clear = 0;
|
||||||
|
partial_T *partial = funcexe->partial;
|
||||||
|
|
||||||
// Make a copy of the name, if it comes from a funcref variable it could
|
// Make a copy of the name, if it comes from a funcref variable it could
|
||||||
// be changed or deleted in the called function.
|
// be changed or deleted in the called function.
|
||||||
@ -1518,15 +1508,15 @@ call_func(
|
|||||||
|
|
||||||
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
||||||
|
|
||||||
*doesrange = FALSE;
|
if (funcexe->doesrange != NULL)
|
||||||
|
*funcexe->doesrange = FALSE;
|
||||||
|
|
||||||
if (partial != NULL)
|
if (partial != NULL)
|
||||||
{
|
{
|
||||||
/* When the function has a partial with a dict and there is a dict
|
/* When the function has a partial with a dict and there is a dict
|
||||||
* argument, use the dict argument. That is backwards compatible.
|
* argument, use the dict argument. That is backwards compatible.
|
||||||
* When the dict was bound explicitly use the one from the partial. */
|
* When the dict was bound explicitly use the one from the partial. */
|
||||||
if (partial->pt_dict != NULL
|
if (partial->pt_dict != NULL && (selfdict == NULL || !partial->pt_auto))
|
||||||
&& (selfdict_in == NULL || !partial->pt_auto))
|
|
||||||
selfdict = partial->pt_dict;
|
selfdict = partial->pt_dict;
|
||||||
if (error == ERROR_NONE && partial->pt_argc > 0)
|
if (error == ERROR_NONE && partial->pt_argc > 0)
|
||||||
{
|
{
|
||||||
@ -1542,7 +1532,7 @@ call_func(
|
|||||||
/*
|
/*
|
||||||
* Execute the function if executing and no errors were detected.
|
* 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
|
// Not evaluating, which means the return value is unknown. This
|
||||||
// matters for giving error messages.
|
// matters for giving error messages.
|
||||||
@ -1590,11 +1580,12 @@ call_func(
|
|||||||
error = ERROR_DELETED;
|
error = ERROR_DELETED;
|
||||||
else if (fp != NULL)
|
else if (fp != NULL)
|
||||||
{
|
{
|
||||||
if (argv_func != NULL)
|
if (funcexe->argv_func != NULL)
|
||||||
argcount = argv_func(argcount, argvars, fp->uf_args.ga_len);
|
argcount = funcexe->argv_func(argcount, argvars,
|
||||||
|
fp->uf_args.ga_len);
|
||||||
|
|
||||||
if (fp->uf_flags & FC_RANGE)
|
if (fp->uf_flags & FC_RANGE && funcexe->doesrange != NULL)
|
||||||
*doesrange = TRUE;
|
*funcexe->doesrange = TRUE;
|
||||||
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
|
if (argcount < fp->uf_args.ga_len - fp->uf_def_args.ga_len)
|
||||||
error = ERROR_TOOFEW;
|
error = ERROR_TOOFEW;
|
||||||
else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
|
else if (!fp->uf_varargs && argcount > fp->uf_args.ga_len)
|
||||||
@ -1621,7 +1612,7 @@ call_func(
|
|||||||
}
|
}
|
||||||
++fp->uf_calls;
|
++fp->uf_calls;
|
||||||
call_user_func(fp, argcount, argvars, rettv,
|
call_user_func(fp, argcount, argvars, rettv,
|
||||||
firstline, lastline,
|
funcexe->firstline, funcexe->lastline,
|
||||||
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
(fp->uf_flags & FC_DICT) ? selfdict : NULL);
|
||||||
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
if (--fp->uf_calls <= 0 && fp->uf_refcount <= 0)
|
||||||
/* Function was unreferenced while being used, free it
|
/* Function was unreferenced while being used, free it
|
||||||
@ -3112,6 +3103,8 @@ ex_call(exarg_T *eap)
|
|||||||
lnum = eap->line1;
|
lnum = eap->line1;
|
||||||
for ( ; lnum <= eap->line2; ++lnum)
|
for ( ; lnum <= eap->line2; ++lnum)
|
||||||
{
|
{
|
||||||
|
funcexe_T funcexe;
|
||||||
|
|
||||||
if (!eap->skip && eap->addr_count > 0)
|
if (!eap->skip && eap->addr_count > 0)
|
||||||
{
|
{
|
||||||
if (lnum > curbuf->b_ml.ml_line_count)
|
if (lnum > curbuf->b_ml.ml_line_count)
|
||||||
@ -3126,9 +3119,15 @@ ex_call(exarg_T *eap)
|
|||||||
curwin->w_cursor.coladd = 0;
|
curwin->w_cursor.coladd = 0;
|
||||||
}
|
}
|
||||||
arg = startarg;
|
arg = startarg;
|
||||||
if (get_func_tv(name, -1, &rettv, &arg,
|
|
||||||
eap->line1, eap->line2, &doesrange,
|
funcexe.argv_func = NULL;
|
||||||
!eap->skip, partial, fudi.fd_dict) == FAIL)
|
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;
|
failed = TRUE;
|
||||||
break;
|
break;
|
||||||
|
@ -773,6 +773,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
1800,
|
||||||
/**/
|
/**/
|
||||||
1799,
|
1799,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user