mirror of
https://github.com/vim/vim.git
synced 2025-07-04 23:07:33 -04:00
patch 8.1.0053: first argument of 'completefunc' has inconsistent type
Problem: The first argument given to 'completefunc' can be Number or String, depending on the value. Solution: Avoid guessing the type of an argument, use typval_T in the callers of call_vim_function(). (Ozaki Kiichi, closes #2993)
This commit is contained in:
parent
83f4cbd973
commit
ffa9684150
20
src/edit.c
20
src/edit.c
@ -4201,7 +4201,7 @@ expand_by_function(
|
|||||||
{
|
{
|
||||||
list_T *matchlist = NULL;
|
list_T *matchlist = NULL;
|
||||||
dict_T *matchdict = NULL;
|
dict_T *matchdict = NULL;
|
||||||
char_u *args[2];
|
typval_T args[3];
|
||||||
char_u *funcname;
|
char_u *funcname;
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
win_T *curwin_save;
|
win_T *curwin_save;
|
||||||
@ -4213,15 +4213,18 @@ expand_by_function(
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
/* Call 'completefunc' to obtain the list of matches. */
|
/* Call 'completefunc' to obtain the list of matches. */
|
||||||
args[0] = (char_u *)"0";
|
args[0].v_type = VAR_NUMBER;
|
||||||
args[1] = base;
|
args[0].vval.v_number = 0;
|
||||||
|
args[1].v_type = VAR_STRING;
|
||||||
|
args[1].vval.v_string = base != NULL ? base : (char_u *)"";
|
||||||
|
args[2].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
pos = curwin->w_cursor;
|
pos = curwin->w_cursor;
|
||||||
curwin_save = curwin;
|
curwin_save = curwin;
|
||||||
curbuf_save = curbuf;
|
curbuf_save = curbuf;
|
||||||
|
|
||||||
/* Call a function, which returns a list or dict. */
|
/* Call a function, which returns a list or dict. */
|
||||||
if (call_vim_function(funcname, 2, args, FALSE, FALSE, &rettv) == OK)
|
if (call_vim_function(funcname, 2, args, &rettv, FALSE) == OK)
|
||||||
{
|
{
|
||||||
switch (rettv.v_type)
|
switch (rettv.v_type)
|
||||||
{
|
{
|
||||||
@ -5528,7 +5531,7 @@ ins_complete(int c, int enable_pum)
|
|||||||
* Call user defined function 'completefunc' with "a:findstart"
|
* Call user defined function 'completefunc' with "a:findstart"
|
||||||
* set to 1 to obtain the length of text to use for completion.
|
* set to 1 to obtain the length of text to use for completion.
|
||||||
*/
|
*/
|
||||||
char_u *args[2];
|
typval_T args[3];
|
||||||
int col;
|
int col;
|
||||||
char_u *funcname;
|
char_u *funcname;
|
||||||
pos_T pos;
|
pos_T pos;
|
||||||
@ -5548,8 +5551,11 @@ ins_complete(int c, int enable_pum)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
args[0] = (char_u *)"1";
|
args[0].v_type = VAR_NUMBER;
|
||||||
args[1] = NULL;
|
args[0].vval.v_number = 1;
|
||||||
|
args[1].v_type = VAR_STRING;
|
||||||
|
args[1].vval.v_string = (char_u *)"";
|
||||||
|
args[2].v_type = VAR_UNKNOWN;
|
||||||
pos = curwin->w_cursor;
|
pos = curwin->w_cursor;
|
||||||
curwin_save = curwin;
|
curwin_save = curwin;
|
||||||
curbuf_save = curbuf;
|
curbuf_save = curbuf;
|
||||||
|
78
src/eval.c
78
src/eval.c
@ -1011,63 +1011,22 @@ eval_expr(char_u *arg, char_u **nextcmd)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Call some Vim script function and return the result in "*rettv".
|
* Call some Vim script function and return the result in "*rettv".
|
||||||
* Uses argv[argc] for the function arguments. Only Number and String
|
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc]
|
||||||
* arguments are currently supported.
|
* should have type VAR_UNKNOWN.
|
||||||
* Returns OK or FAIL.
|
* Returns OK or FAIL.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
call_vim_function(
|
call_vim_function(
|
||||||
char_u *func,
|
char_u *func,
|
||||||
int argc,
|
int argc,
|
||||||
char_u **argv,
|
typval_T *argv,
|
||||||
int safe, /* use the sandbox */
|
typval_T *rettv,
|
||||||
int str_arg_only, /* all arguments are strings */
|
int safe) /* use the sandbox */
|
||||||
typval_T *rettv)
|
|
||||||
{
|
{
|
||||||
typval_T *argvars;
|
|
||||||
varnumber_T n;
|
|
||||||
int len;
|
|
||||||
int i;
|
|
||||||
int doesrange;
|
int doesrange;
|
||||||
void *save_funccalp = NULL;
|
void *save_funccalp = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
argvars = (typval_T *)alloc((unsigned)((argc + 1) * sizeof(typval_T)));
|
|
||||||
if (argvars == NULL)
|
|
||||||
return FAIL;
|
|
||||||
|
|
||||||
for (i = 0; i < argc; i++)
|
|
||||||
{
|
|
||||||
/* Pass a NULL or empty argument as an empty string */
|
|
||||||
if (argv[i] == NULL || *argv[i] == NUL)
|
|
||||||
{
|
|
||||||
argvars[i].v_type = VAR_STRING;
|
|
||||||
argvars[i].vval.v_string = (char_u *)"";
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str_arg_only)
|
|
||||||
len = 0;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Recognize a number argument, the others must be strings. A dash
|
|
||||||
* is a string too. */
|
|
||||||
vim_str2nr(argv[i], NULL, &len, STR2NR_ALL, &n, NULL, 0);
|
|
||||||
if (len == 1 && *argv[i] == '-')
|
|
||||||
len = 0;
|
|
||||||
}
|
|
||||||
if (len != 0 && len == (int)STRLEN(argv[i]))
|
|
||||||
{
|
|
||||||
argvars[i].v_type = VAR_NUMBER;
|
|
||||||
argvars[i].vval.v_number = n;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
argvars[i].v_type = VAR_STRING;
|
|
||||||
argvars[i].vval.v_string = argv[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (safe)
|
if (safe)
|
||||||
{
|
{
|
||||||
save_funccalp = save_funccal();
|
save_funccalp = save_funccal();
|
||||||
@ -1075,7 +1034,7 @@ call_vim_function(
|
|||||||
}
|
}
|
||||||
|
|
||||||
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
rettv->v_type = VAR_UNKNOWN; /* clear_tv() uses this */
|
||||||
ret = call_func(func, (int)STRLEN(func), rettv, argc, argvars, NULL,
|
ret = call_func(func, (int)STRLEN(func), rettv, argc, argv, NULL,
|
||||||
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
curwin->w_cursor.lnum, curwin->w_cursor.lnum,
|
||||||
&doesrange, TRUE, NULL, NULL);
|
&doesrange, TRUE, NULL, NULL);
|
||||||
if (safe)
|
if (safe)
|
||||||
@ -1083,7 +1042,6 @@ call_vim_function(
|
|||||||
--sandbox;
|
--sandbox;
|
||||||
restore_funccal(save_funccalp);
|
restore_funccal(save_funccalp);
|
||||||
}
|
}
|
||||||
vim_free(argvars);
|
|
||||||
|
|
||||||
if (ret == FAIL)
|
if (ret == FAIL)
|
||||||
clear_tv(rettv);
|
clear_tv(rettv);
|
||||||
@ -1094,20 +1052,20 @@ call_vim_function(
|
|||||||
/*
|
/*
|
||||||
* Call Vim script function "func" and return the result as a number.
|
* Call Vim script function "func" and return the result as a number.
|
||||||
* Returns -1 when calling the function fails.
|
* Returns -1 when calling the function fails.
|
||||||
* Uses argv[argc] for the function arguments.
|
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||||
|
* have type VAR_UNKNOWN.
|
||||||
*/
|
*/
|
||||||
varnumber_T
|
varnumber_T
|
||||||
call_func_retnr(
|
call_func_retnr(
|
||||||
char_u *func,
|
char_u *func,
|
||||||
int argc,
|
int argc,
|
||||||
char_u **argv,
|
typval_T *argv,
|
||||||
int safe) /* use the sandbox */
|
int safe) /* use the sandbox */
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
varnumber_T retval;
|
varnumber_T retval;
|
||||||
|
|
||||||
/* All arguments are passed as strings, no conversion to number. */
|
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
retval = get_tv_number_chk(&rettv, NULL);
|
retval = get_tv_number_chk(&rettv, NULL);
|
||||||
@ -1122,20 +1080,20 @@ call_func_retnr(
|
|||||||
/*
|
/*
|
||||||
* Call Vim script function "func" and return the result as a string.
|
* Call Vim script function "func" and return the result as a string.
|
||||||
* Returns NULL when calling the function fails.
|
* Returns NULL when calling the function fails.
|
||||||
* Uses argv[argc] for the function arguments.
|
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||||
|
* have type VAR_UNKNOWN.
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
call_func_retstr(
|
call_func_retstr(
|
||||||
char_u *func,
|
char_u *func,
|
||||||
int argc,
|
int argc,
|
||||||
char_u **argv,
|
typval_T *argv,
|
||||||
int safe) /* use the sandbox */
|
int safe) /* use the sandbox */
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
char_u *retval;
|
char_u *retval;
|
||||||
|
|
||||||
/* All arguments are passed as strings, no conversion to number. */
|
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
retval = vim_strsave(get_tv_string(&rettv));
|
retval = vim_strsave(get_tv_string(&rettv));
|
||||||
@ -1146,20 +1104,20 @@ call_func_retstr(
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Call Vim script function "func" and return the result as a List.
|
* Call Vim script function "func" and return the result as a List.
|
||||||
* Uses argv[argc] for the function arguments.
|
* Uses argv[0] to argv[argc - 1] for the function arguments. argv[argc] should
|
||||||
|
* have type VAR_UNKNOWN.
|
||||||
* Returns NULL when there is something wrong.
|
* Returns NULL when there is something wrong.
|
||||||
*/
|
*/
|
||||||
void *
|
void *
|
||||||
call_func_retlist(
|
call_func_retlist(
|
||||||
char_u *func,
|
char_u *func,
|
||||||
int argc,
|
int argc,
|
||||||
char_u **argv,
|
typval_T *argv,
|
||||||
int safe) /* use the sandbox */
|
int safe) /* use the sandbox */
|
||||||
{
|
{
|
||||||
typval_T rettv;
|
typval_T rettv;
|
||||||
|
|
||||||
/* All arguments are passed as strings, no conversion to number. */
|
if (call_vim_function(func, argc, argv, &rettv, safe) == FAIL)
|
||||||
if (call_vim_function(func, argc, argv, safe, TRUE, &rettv) == FAIL)
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (rettv.v_type != VAR_LIST)
|
if (rettv.v_type != VAR_LIST)
|
||||||
|
@ -5266,7 +5266,7 @@ expand_shellcmd(
|
|||||||
|
|
||||||
|
|
||||||
# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
|
# if defined(FEAT_USR_CMDS) && defined(FEAT_EVAL)
|
||||||
static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, char_u **, int), expand_T *xp, int *num_file, char_u ***file);
|
static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, typval_T *, int), expand_T *xp, int *num_file, char_u ***file);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Call "user_expand_func()" to invoke a user defined Vim script function and
|
* Call "user_expand_func()" to invoke a user defined Vim script function and
|
||||||
@ -5274,15 +5274,15 @@ static void * call_user_expand_func(void *(*user_expand_func)(char_u *, int, cha
|
|||||||
*/
|
*/
|
||||||
static void *
|
static void *
|
||||||
call_user_expand_func(
|
call_user_expand_func(
|
||||||
void *(*user_expand_func)(char_u *, int, char_u **, int),
|
void *(*user_expand_func)(char_u *, int, typval_T *, int),
|
||||||
expand_T *xp,
|
expand_T *xp,
|
||||||
int *num_file,
|
int *num_file,
|
||||||
char_u ***file)
|
char_u ***file)
|
||||||
{
|
{
|
||||||
int keep = 0;
|
int keep = 0;
|
||||||
char_u num[50];
|
typval_T args[4];
|
||||||
char_u *args[3];
|
|
||||||
int save_current_SID = current_SID;
|
int save_current_SID = current_SID;
|
||||||
|
char_u *pat = NULL;
|
||||||
void *ret;
|
void *ret;
|
||||||
struct cmdline_info save_ccline;
|
struct cmdline_info save_ccline;
|
||||||
|
|
||||||
@ -5297,10 +5297,15 @@ call_user_expand_func(
|
|||||||
ccline.cmdbuff[ccline.cmdlen] = 0;
|
ccline.cmdbuff[ccline.cmdlen] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
args[0] = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
|
pat = vim_strnsave(xp->xp_pattern, xp->xp_pattern_len);
|
||||||
args[1] = xp->xp_line;
|
|
||||||
sprintf((char *)num, "%d", xp->xp_col);
|
args[0].v_type = VAR_STRING;
|
||||||
args[2] = num;
|
args[0].vval.v_string = pat;
|
||||||
|
args[1].v_type = VAR_STRING;
|
||||||
|
args[1].vval.v_string = xp->xp_line;
|
||||||
|
args[2].v_type = VAR_NUMBER;
|
||||||
|
args[2].vval.v_number = xp->xp_col;
|
||||||
|
args[3].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
/* Save the cmdline, we don't know what the function may do. */
|
/* Save the cmdline, we don't know what the function may do. */
|
||||||
save_ccline = ccline;
|
save_ccline = ccline;
|
||||||
@ -5315,7 +5320,7 @@ call_user_expand_func(
|
|||||||
if (ccline.cmdbuff != NULL)
|
if (ccline.cmdbuff != NULL)
|
||||||
ccline.cmdbuff[ccline.cmdlen] = keep;
|
ccline.cmdbuff[ccline.cmdlen] = keep;
|
||||||
|
|
||||||
vim_free(args[0]);
|
vim_free(pat);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4795,12 +4795,11 @@ iconv_end(void)
|
|||||||
static void
|
static void
|
||||||
call_imactivatefunc(int active)
|
call_imactivatefunc(int active)
|
||||||
{
|
{
|
||||||
char_u *argv[1];
|
typval_T argv[2];
|
||||||
|
|
||||||
if (active)
|
argv[0].v_type = VAR_NUMBER;
|
||||||
argv[0] = (char_u *)"1";
|
argv[0].vval.v_number = active ? 1 : 0;
|
||||||
else
|
argv[1].v_type = VAR_NUMBER;
|
||||||
argv[0] = (char_u *)"0";
|
|
||||||
(void)call_func_retnr(p_imaf, 1, argv, FALSE);
|
(void)call_func_retnr(p_imaf, 1, argv, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
10
src/normal.c
10
src/normal.c
@ -2219,7 +2219,7 @@ op_colon(oparg_T *oap)
|
|||||||
op_function(oparg_T *oap UNUSED)
|
op_function(oparg_T *oap UNUSED)
|
||||||
{
|
{
|
||||||
#ifdef FEAT_EVAL
|
#ifdef FEAT_EVAL
|
||||||
char_u *(argv[1]);
|
typval_T argv[2];
|
||||||
# ifdef FEAT_VIRTUALEDIT
|
# ifdef FEAT_VIRTUALEDIT
|
||||||
int save_virtual_op = virtual_op;
|
int save_virtual_op = virtual_op;
|
||||||
# endif
|
# endif
|
||||||
@ -2235,12 +2235,14 @@ op_function(oparg_T *oap UNUSED)
|
|||||||
/* Exclude the end position. */
|
/* Exclude the end position. */
|
||||||
decl(&curbuf->b_op_end);
|
decl(&curbuf->b_op_end);
|
||||||
|
|
||||||
|
argv[0].v_type = VAR_STRING;
|
||||||
if (oap->block_mode)
|
if (oap->block_mode)
|
||||||
argv[0] = (char_u *)"block";
|
argv[0].vval.v_string = (char_u *)"block";
|
||||||
else if (oap->motion_type == MLINE)
|
else if (oap->motion_type == MLINE)
|
||||||
argv[0] = (char_u *)"line";
|
argv[0].vval.v_string = (char_u *)"line";
|
||||||
else
|
else
|
||||||
argv[0] = (char_u *)"char";
|
argv[0].vval.v_string = (char_u *)"char";
|
||||||
|
argv[1].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
# ifdef FEAT_VIRTUALEDIT
|
# ifdef FEAT_VIRTUALEDIT
|
||||||
/* Reset virtual_op so that 'virtualedit' can be changed in the
|
/* Reset virtual_op so that 'virtualedit' can be changed in the
|
||||||
|
@ -19,10 +19,10 @@ varnumber_T eval_to_number(char_u *expr);
|
|||||||
list_T *eval_spell_expr(char_u *badword, char_u *expr);
|
list_T *eval_spell_expr(char_u *badword, char_u *expr);
|
||||||
int get_spellword(list_T *list, char_u **pp);
|
int get_spellword(list_T *list, char_u **pp);
|
||||||
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
typval_T *eval_expr(char_u *arg, char_u **nextcmd);
|
||||||
int call_vim_function(char_u *func, int argc, char_u **argv, int safe, int str_arg_only, typval_T *rettv);
|
int call_vim_function(char_u *func, int argc, typval_T *argv, typval_T *rettv, int safe);
|
||||||
varnumber_T call_func_retnr(char_u *func, int argc, char_u **argv, int safe);
|
varnumber_T call_func_retnr(char_u *func, int argc, typval_T *argv, int safe);
|
||||||
void *call_func_retstr(char_u *func, int argc, char_u **argv, int safe);
|
void *call_func_retstr(char_u *func, int argc, typval_T *argv, int safe);
|
||||||
void *call_func_retlist(char_u *func, int argc, char_u **argv, int safe);
|
void *call_func_retlist(char_u *func, int argc, typval_T *argv, int safe);
|
||||||
int eval_foldexpr(char_u *arg, int *cp);
|
int eval_foldexpr(char_u *arg, int *cp);
|
||||||
void ex_let(exarg_T *eap);
|
void ex_let(exarg_T *eap);
|
||||||
void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first);
|
void list_hashtable_vars(hashtab_T *ht, char_u *prefix, int empty, int *first);
|
||||||
|
@ -117,6 +117,31 @@ func Test_omni_dash()
|
|||||||
set omnifunc=
|
set omnifunc=
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_completefunc_args()
|
||||||
|
let s:args = []
|
||||||
|
func! CompleteFunc(findstart, base)
|
||||||
|
let s:args += [[a:findstart, empty(a:base)]]
|
||||||
|
endfunc
|
||||||
|
new
|
||||||
|
|
||||||
|
set completefunc=CompleteFunc
|
||||||
|
call feedkeys("i\<C-X>\<C-U>\<Esc>", 'x')
|
||||||
|
call assert_equal(s:args[0], [1, 1])
|
||||||
|
call assert_equal(s:args[1][0], 0)
|
||||||
|
set completefunc=
|
||||||
|
|
||||||
|
let s:args = []
|
||||||
|
set omnifunc=CompleteFunc
|
||||||
|
call feedkeys("i\<C-X>\<C-O>\<Esc>", 'x')
|
||||||
|
call assert_equal(s:args[0], [1, 1])
|
||||||
|
call assert_equal(s:args[1][0], 0)
|
||||||
|
set omnifunc=
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
unlet s:args
|
||||||
|
delfunc CompleteFunc
|
||||||
|
endfunc
|
||||||
|
|
||||||
function! s:CompleteDone_CompleteFuncDict( findstart, base )
|
function! s:CompleteDone_CompleteFuncDict( findstart, base )
|
||||||
if a:findstart
|
if a:findstart
|
||||||
return 0
|
return 0
|
||||||
|
@ -761,6 +761,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 */
|
||||||
|
/**/
|
||||||
|
53,
|
||||||
/**/
|
/**/
|
||||||
52,
|
52,
|
||||||
/**/
|
/**/
|
||||||
|
Loading…
x
Reference in New Issue
Block a user