mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0650: Vim9: script function can be deleted
Problem: Vim9: script function can be deleted. Solution: Disallow deleting script function. Delete functions when sourcing a script again.
This commit is contained in:
@@ -2679,6 +2679,7 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
int use_string = FALSE;
|
int use_string = FALSE;
|
||||||
partial_T *arg_pt = NULL;
|
partial_T *arg_pt = NULL;
|
||||||
char_u *trans_name = NULL;
|
char_u *trans_name = NULL;
|
||||||
|
int is_global = FALSE;
|
||||||
|
|
||||||
if (argvars[0].v_type == VAR_FUNC)
|
if (argvars[0].v_type == VAR_FUNC)
|
||||||
{
|
{
|
||||||
@@ -2702,21 +2703,10 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref)
|
if ((use_string && vim_strchr(s, AUTOLOAD_CHAR) == NULL) || is_funcref)
|
||||||
{
|
{
|
||||||
name = s;
|
name = s;
|
||||||
trans_name = trans_function_name(&name, FALSE,
|
trans_name = trans_function_name(&name, &is_global, FALSE,
|
||||||
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
|
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
|
||||||
if (*name != NUL)
|
if (*name != NUL)
|
||||||
s = NULL;
|
s = NULL;
|
||||||
else if (trans_name != NULL
|
|
||||||
&& ASCII_ISUPPER(*s)
|
|
||||||
&& current_sctx.sc_version == SCRIPT_VERSION_VIM9
|
|
||||||
&& find_func(trans_name, NULL) == NULL)
|
|
||||||
{
|
|
||||||
// With Vim9 script "MyFunc" can be script-local to the current
|
|
||||||
// script or global. The script-local name is not found, assume
|
|
||||||
// global.
|
|
||||||
vim_free(trans_name);
|
|
||||||
trans_name = vim_strsave(s);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))
|
if (s == NULL || *s == NUL || (use_string && VIM_ISDIGIT(*s))
|
||||||
@@ -2724,8 +2714,8 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
semsg(_(e_invarg2), use_string ? tv_get_string(&argvars[0]) : s);
|
semsg(_(e_invarg2), use_string ? tv_get_string(&argvars[0]) : s);
|
||||||
// Don't check an autoload name for existence here.
|
// Don't check an autoload name for existence here.
|
||||||
else if (trans_name != NULL && (is_funcref
|
else if (trans_name != NULL && (is_funcref
|
||||||
? find_func(trans_name, NULL) == NULL
|
? find_func(trans_name, is_global, NULL) == NULL
|
||||||
: !translated_function_exists(trans_name)))
|
: !translated_function_exists(trans_name, is_global)))
|
||||||
semsg(_("E700: Unknown function: %s"), s);
|
semsg(_("E700: Unknown function: %s"), s);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -2862,7 +2852,7 @@ common_function(typval_T *argvars, typval_T *rettv, int is_funcref)
|
|||||||
}
|
}
|
||||||
else if (is_funcref)
|
else if (is_funcref)
|
||||||
{
|
{
|
||||||
pt->pt_func = find_func(trans_name, NULL);
|
pt->pt_func = find_func(trans_name, is_global, NULL);
|
||||||
func_ptr_ref(pt->pt_func);
|
func_ptr_ref(pt->pt_func);
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
}
|
}
|
||||||
|
@@ -7,11 +7,12 @@ char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_au
|
|||||||
void emsg_funcname(char *ermsg, char_u *name);
|
void emsg_funcname(char *ermsg, char_u *name);
|
||||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
|
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, funcexe_T *funcexe);
|
||||||
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
||||||
ufunc_T *find_func(char_u *name, cctx_T *cctx);
|
ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
|
||||||
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
|
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
|
||||||
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 delete_script_functions(int sid);
|
||||||
void free_all_functions(void);
|
void free_all_functions(void);
|
||||||
int builtin_function(char_u *name, int len);
|
int builtin_function(char_u *name, int len);
|
||||||
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);
|
||||||
@@ -19,11 +20,11 @@ int get_callback_depth(void);
|
|||||||
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
|
int call_callback(callback_T *callback, int len, typval_T *rettv, int argcount, typval_T *argvars);
|
||||||
void user_func_error(int error, char_u *name);
|
void user_func_error(int error, char_u *name);
|
||||||
int call_func(char_u *funcname, int len, typval_T *rettv, int argcount_in, typval_T *argvars_in, funcexe_T *funcexe);
|
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 *is_global, int skip, int flags, funcdict_T *fdp, partial_T **partial);
|
||||||
char_u *untrans_function_name(char_u *name);
|
char_u *untrans_function_name(char_u *name);
|
||||||
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);
|
||||||
int translated_function_exists(char_u *name);
|
int translated_function_exists(char_u *name, int is_global);
|
||||||
int has_varargs(ufunc_T *ufunc);
|
int has_varargs(ufunc_T *ufunc);
|
||||||
int function_exists(char_u *name, int no_deref);
|
int function_exists(char_u *name, int no_deref);
|
||||||
char_u *get_expanded_name(char_u *name, int check);
|
char_u *get_expanded_name(char_u *name, int check);
|
||||||
|
@@ -1275,6 +1275,7 @@ do_source(
|
|||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
dictitem_T *di;
|
dictitem_T *di;
|
||||||
int todo;
|
int todo;
|
||||||
|
int is_vim9 = si->sn_version == SCRIPT_VERSION_VIM9;
|
||||||
|
|
||||||
// loading the same script again
|
// loading the same script again
|
||||||
si->sn_had_command = FALSE;
|
si->sn_had_command = FALSE;
|
||||||
@@ -1293,6 +1294,10 @@ do_source(
|
|||||||
|
|
||||||
// old imports are no longer valid
|
// old imports are no longer valid
|
||||||
free_imports(sid);
|
free_imports(sid);
|
||||||
|
|
||||||
|
// in Vim9 script functions are marked deleted
|
||||||
|
if (is_vim9)
|
||||||
|
delete_script_functions(sid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -207,12 +207,12 @@ def Test_expr4_equal()
|
|||||||
assert_equal(true, g:adict == #{bbb: 8, aaa: 2})
|
assert_equal(true, g:adict == #{bbb: 8, aaa: 2})
|
||||||
assert_equal(false, #{ccc: 9, aaa: 2} == g:adict)
|
assert_equal(false, #{ccc: 9, aaa: 2} == g:adict)
|
||||||
|
|
||||||
assert_equal(true, function('Test_expr4_equal') == function('Test_expr4_equal'))
|
assert_equal(true, function('g:Test_expr4_equal') == function('g:Test_expr4_equal'))
|
||||||
assert_equal(false, function('Test_expr4_equal') == function('Test_expr4_is'))
|
assert_equal(false, function('g:Test_expr4_equal') == function('g:Test_expr4_is'))
|
||||||
|
|
||||||
assert_equal(true, function('Test_expr4_equal', [123]) == function('Test_expr4_equal', [123]))
|
assert_equal(true, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_equal', [123]))
|
||||||
assert_equal(false, function('Test_expr4_equal', [123]) == function('Test_expr4_is', [123]))
|
assert_equal(false, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_is', [123]))
|
||||||
assert_equal(false, function('Test_expr4_equal', [123]) == function('Test_expr4_equal', [999]))
|
assert_equal(false, function('g:Test_expr4_equal', [123]) == function('g:Test_expr4_equal', [999]))
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
" test != comperator
|
" test != comperator
|
||||||
@@ -274,12 +274,12 @@ def Test_expr4_notequal()
|
|||||||
assert_equal(false, g:adict != #{bbb: 8, aaa: 2})
|
assert_equal(false, g:adict != #{bbb: 8, aaa: 2})
|
||||||
assert_equal(true, #{ccc: 9, aaa: 2} != g:adict)
|
assert_equal(true, #{ccc: 9, aaa: 2} != g:adict)
|
||||||
|
|
||||||
assert_equal(false, function('Test_expr4_equal') != function('Test_expr4_equal'))
|
assert_equal(false, function('g:Test_expr4_equal') != function('g:Test_expr4_equal'))
|
||||||
assert_equal(true, function('Test_expr4_equal') != function('Test_expr4_is'))
|
assert_equal(true, function('g:Test_expr4_equal') != function('g:Test_expr4_is'))
|
||||||
|
|
||||||
assert_equal(false, function('Test_expr4_equal', [123]) != function('Test_expr4_equal', [123]))
|
assert_equal(false, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_equal', [123]))
|
||||||
assert_equal(true, function('Test_expr4_equal', [123]) != function('Test_expr4_is', [123]))
|
assert_equal(true, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_is', [123]))
|
||||||
assert_equal(true, function('Test_expr4_equal', [123]) != function('Test_expr4_equal', [999]))
|
assert_equal(true, function('g:Test_expr4_equal', [123]) != function('g:Test_expr4_equal', [999]))
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
" test > comperator
|
" test > comperator
|
||||||
@@ -929,15 +929,15 @@ endfunc
|
|||||||
|
|
||||||
def Test_expr7_trailing()
|
def Test_expr7_trailing()
|
||||||
" user function call
|
" user function call
|
||||||
assert_equal(123, CallMe(123))
|
assert_equal(123, g:CallMe(123))
|
||||||
assert_equal(123, CallMe( 123))
|
assert_equal(123, g:CallMe( 123))
|
||||||
assert_equal(123, CallMe(123 ))
|
assert_equal(123, g:CallMe(123 ))
|
||||||
assert_equal('yesno', CallMe2('yes', 'no'))
|
assert_equal('yesno', g:CallMe2('yes', 'no'))
|
||||||
assert_equal('yesno', CallMe2( 'yes', 'no' ))
|
assert_equal('yesno', g:CallMe2( 'yes', 'no' ))
|
||||||
assert_equal('nothing', CallMe('nothing'))
|
assert_equal('nothing', g:CallMe('nothing'))
|
||||||
|
|
||||||
" partial call
|
" partial call
|
||||||
let Part = function('CallMe')
|
let Part = function('g:CallMe')
|
||||||
assert_equal('yes', Part('yes'))
|
assert_equal('yes', Part('yes'))
|
||||||
|
|
||||||
" funcref call, using list index
|
" funcref call, using list index
|
||||||
|
@@ -353,7 +353,7 @@ endfunc
|
|||||||
def Test_delfunc()
|
def Test_delfunc()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
def GoneSoon()
|
def g:GoneSoon()
|
||||||
echo 'hello'
|
echo 'hello'
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
@@ -361,7 +361,7 @@ def Test_delfunc()
|
|||||||
GoneSoon()
|
GoneSoon()
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
delfunc GoneSoon
|
delfunc g:GoneSoon
|
||||||
CallGoneSoon()
|
CallGoneSoon()
|
||||||
END
|
END
|
||||||
writefile(lines, 'XToDelFunc')
|
writefile(lines, 'XToDelFunc')
|
||||||
|
@@ -53,7 +53,7 @@ def Test_assignment()
|
|||||||
endif
|
endif
|
||||||
let Funky1: func
|
let Funky1: func
|
||||||
let Funky2: func = function('len')
|
let Funky2: func = function('len')
|
||||||
let Party2: func = funcref('Test_syntax')
|
let Party2: func = funcref('g:Test_syntax')
|
||||||
|
|
||||||
# type becomes list<any>
|
# type becomes list<any>
|
||||||
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
let somelist = rand() > 0 ? [1, 2, 3] : ['a', 'b', 'c']
|
||||||
@@ -282,6 +282,49 @@ def Test_unlet()
|
|||||||
assert_equal('', $ENVVAR)
|
assert_equal('', $ENVVAR)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_delfunction()
|
||||||
|
" Check function is defined in script namespace
|
||||||
|
CheckScriptSuccess([
|
||||||
|
'vim9script',
|
||||||
|
'func CheckMe()',
|
||||||
|
' return 123',
|
||||||
|
'endfunc',
|
||||||
|
'assert_equal(123, s:CheckMe())',
|
||||||
|
])
|
||||||
|
|
||||||
|
" Check function in script namespace cannot be deleted
|
||||||
|
CheckScriptFailure([
|
||||||
|
'vim9script',
|
||||||
|
'func DeleteMe1()',
|
||||||
|
'endfunc',
|
||||||
|
'delfunction DeleteMe1',
|
||||||
|
], 'E1084:')
|
||||||
|
CheckScriptFailure([
|
||||||
|
'vim9script',
|
||||||
|
'func DeleteMe2()',
|
||||||
|
'endfunc',
|
||||||
|
'def DoThat()',
|
||||||
|
' delfunction DeleteMe2',
|
||||||
|
'enddef',
|
||||||
|
'DoThat()',
|
||||||
|
], 'E1084:')
|
||||||
|
CheckScriptFailure([
|
||||||
|
'vim9script',
|
||||||
|
'def DeleteMe3()',
|
||||||
|
'enddef',
|
||||||
|
'delfunction DeleteMe3',
|
||||||
|
], 'E1084:')
|
||||||
|
CheckScriptFailure([
|
||||||
|
'vim9script',
|
||||||
|
'def DeleteMe4()',
|
||||||
|
'enddef',
|
||||||
|
'def DoThat()',
|
||||||
|
' delfunction DeleteMe4',
|
||||||
|
'enddef',
|
||||||
|
'DoThat()',
|
||||||
|
], 'E1084:')
|
||||||
|
enddef
|
||||||
|
|
||||||
func Test_wrong_type()
|
func Test_wrong_type()
|
||||||
call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
|
call CheckDefFailure(['let var: list<nothing>'], 'E1010:')
|
||||||
call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
|
call CheckDefFailure(['let var: list<list<nothing>>'], 'E1010:')
|
||||||
@@ -649,7 +692,7 @@ def Test_vim9script_fails()
|
|||||||
assert_fails('export something', 'E1043')
|
assert_fails('export something', 'E1043')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
def Test_vim9script_reload()
|
def Test_vim9script_reload_import()
|
||||||
let lines =<< trim END
|
let lines =<< trim END
|
||||||
vim9script
|
vim9script
|
||||||
const var = ''
|
const var = ''
|
||||||
@@ -700,6 +743,47 @@ def Test_vim9script_reload()
|
|||||||
delete('Ximport.vim')
|
delete('Ximport.vim')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_vim9script_reload_delfunc()
|
||||||
|
let first_lines =<< trim END
|
||||||
|
vim9script
|
||||||
|
def FuncYes(): string
|
||||||
|
return 'yes'
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
let middle_lines =<< trim END
|
||||||
|
def FuncNo(): string
|
||||||
|
return 'no'
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
let final_lines =<< trim END
|
||||||
|
def g:DoCheck(no_exists: bool)
|
||||||
|
assert_equal('yes', FuncYes())
|
||||||
|
if no_exists
|
||||||
|
assert_equal('no', FuncNo())
|
||||||
|
else
|
||||||
|
assert_fails('call FuncNo()', 'E117:')
|
||||||
|
endif
|
||||||
|
enddef
|
||||||
|
END
|
||||||
|
|
||||||
|
# FuncNo() is defined
|
||||||
|
writefile(first_lines + middle_lines + final_lines, 'Xreloaded.vim')
|
||||||
|
source Xreloaded.vim
|
||||||
|
g:DoCheck(true)
|
||||||
|
|
||||||
|
# FuncNo() is not redefined
|
||||||
|
writefile(first_lines + final_lines, 'Xreloaded.vim')
|
||||||
|
source Xreloaded.vim
|
||||||
|
g:DoCheck(false)
|
||||||
|
|
||||||
|
# FuncNo() is back
|
||||||
|
writefile(first_lines + middle_lines + final_lines, 'Xreloaded.vim')
|
||||||
|
source Xreloaded.vim
|
||||||
|
g:DoCheck(true)
|
||||||
|
|
||||||
|
delete('Xreloaded.vim')
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_import_absolute()
|
def Test_import_absolute()
|
||||||
let import_lines = [
|
let import_lines = [
|
||||||
'vim9script',
|
'vim9script',
|
||||||
@@ -1445,15 +1529,15 @@ def Test_vim9_comment()
|
|||||||
|
|
||||||
CheckScriptSuccess([
|
CheckScriptSuccess([
|
||||||
'vim9script',
|
'vim9script',
|
||||||
'func DeleteMe()',
|
'func g:DeleteMeA()',
|
||||||
'endfunc',
|
'endfunc',
|
||||||
'delfunction DeleteMe # comment',
|
'delfunction g:DeleteMeA # comment',
|
||||||
])
|
])
|
||||||
CheckScriptFailure([
|
CheckScriptFailure([
|
||||||
'vim9script',
|
'vim9script',
|
||||||
'func DeleteMe()',
|
'func g:DeleteMeB()',
|
||||||
'endfunc',
|
'endfunc',
|
||||||
'delfunction DeleteMe# comment',
|
'delfunction g:DeleteMeB# comment',
|
||||||
], 'E488:')
|
], 'E488:')
|
||||||
|
|
||||||
CheckScriptSuccess([
|
CheckScriptSuccess([
|
||||||
|
@@ -789,7 +789,7 @@ f_test_refcount(typval_T *argvars, typval_T *rettv)
|
|||||||
{
|
{
|
||||||
ufunc_T *fp;
|
ufunc_T *fp;
|
||||||
|
|
||||||
fp = find_func(argvars[0].vval.v_string, NULL);
|
fp = find_func(argvars[0].vval.v_string, FALSE, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
retval = fp->uf_refcount;
|
retval = fp->uf_refcount;
|
||||||
}
|
}
|
||||||
|
115
src/userfunc.c
115
src/userfunc.c
@@ -25,6 +25,7 @@
|
|||||||
#define FC_DEAD 0x80 // function kept only for reference to dfunc
|
#define FC_DEAD 0x80 // function kept only for reference to dfunc
|
||||||
#define FC_EXPORT 0x100 // "export def Func()"
|
#define FC_EXPORT 0x100 // "export def Func()"
|
||||||
#define FC_NOARGS 0x200 // no a: variables in lambda
|
#define FC_NOARGS 0x200 // no a: variables in lambda
|
||||||
|
#define FC_VIM9 0x400 // defined in vim9 script file
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* All user-defined functions are found in this hashtable.
|
* All user-defined functions are found in this hashtable.
|
||||||
@@ -710,16 +711,17 @@ find_func_with_sid(char_u *name, int sid)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Find a function by name, return pointer to it in ufuncs.
|
* Find a function by name, return pointer to it in ufuncs.
|
||||||
|
* When "is_global" is true don't find script-local or imported functions.
|
||||||
* Return NULL for unknown function.
|
* Return NULL for unknown function.
|
||||||
*/
|
*/
|
||||||
static ufunc_T *
|
static ufunc_T *
|
||||||
find_func_even_dead(char_u *name, cctx_T *cctx)
|
find_func_even_dead(char_u *name, int is_global, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
ufunc_T *func;
|
ufunc_T *func;
|
||||||
imported_T *imported;
|
imported_T *imported;
|
||||||
|
|
||||||
if (in_vim9script())
|
if (in_vim9script() && !is_global)
|
||||||
{
|
{
|
||||||
// Find script-local function before global one.
|
// Find script-local function before global one.
|
||||||
func = find_func_with_sid(name, current_sctx.sc_sid);
|
func = find_func_with_sid(name, current_sctx.sc_sid);
|
||||||
@@ -750,9 +752,9 @@ find_func_even_dead(char_u *name, cctx_T *cctx)
|
|||||||
* Return NULL for unknown or dead function.
|
* Return NULL for unknown or dead function.
|
||||||
*/
|
*/
|
||||||
ufunc_T *
|
ufunc_T *
|
||||||
find_func(char_u *name, cctx_T *cctx)
|
find_func(char_u *name, int is_global, cctx_T *cctx)
|
||||||
{
|
{
|
||||||
ufunc_T *fp = find_func_even_dead(name, cctx);
|
ufunc_T *fp = find_func_even_dead(name, is_global, cctx);
|
||||||
|
|
||||||
if (fp != NULL && (fp->uf_flags & FC_DEAD) == 0)
|
if (fp != NULL && (fp->uf_flags & FC_DEAD) == 0)
|
||||||
return fp;
|
return fp;
|
||||||
@@ -1575,6 +1577,38 @@ get_current_funccal(void)
|
|||||||
return current_funccal;
|
return current_funccal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Mark all functions of script "sid" as deleted.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
delete_script_functions(int sid)
|
||||||
|
{
|
||||||
|
hashitem_T *hi;
|
||||||
|
ufunc_T *fp;
|
||||||
|
long_u todo;
|
||||||
|
char buf[30];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
buf[0] = K_SPECIAL;
|
||||||
|
buf[1] = KS_EXTRA;
|
||||||
|
buf[2] = (int)KE_SNR;
|
||||||
|
sprintf(buf + 3, "%d_", sid);
|
||||||
|
len = STRLEN(buf);
|
||||||
|
|
||||||
|
todo = func_hashtab.ht_used;
|
||||||
|
for (hi = func_hashtab.ht_array; todo > 0; ++hi)
|
||||||
|
if (!HASHITEM_EMPTY(hi))
|
||||||
|
{
|
||||||
|
if (STRNCMP(fp->uf_name, buf, len) == 0)
|
||||||
|
{
|
||||||
|
fp = HI2UF(hi);
|
||||||
|
fp->uf_flags |= FC_DEAD;
|
||||||
|
func_clear(fp, TRUE);
|
||||||
|
}
|
||||||
|
--todo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE) || defined(PROTO)
|
#if defined(EXITFREE) || defined(PROTO)
|
||||||
void
|
void
|
||||||
free_all_functions(void)
|
free_all_functions(void)
|
||||||
@@ -1884,22 +1918,22 @@ call_func(
|
|||||||
* User defined function.
|
* User defined function.
|
||||||
*/
|
*/
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
fp = find_func(rfname, NULL);
|
fp = find_func(rfname, FALSE, NULL);
|
||||||
|
|
||||||
// Trigger FuncUndefined event, may load the function.
|
// Trigger FuncUndefined event, may load the function.
|
||||||
if (fp == NULL
|
if (fp == NULL
|
||||||
&& apply_autocmds(EVENT_FUNCUNDEFINED,
|
&& apply_autocmds(EVENT_FUNCUNDEFINED,
|
||||||
rfname, rfname, TRUE, NULL)
|
rfname, rfname, TRUE, NULL)
|
||||||
&& !aborting())
|
&& !aborting())
|
||||||
{
|
{
|
||||||
// executed an autocommand, search for the function again
|
// executed an autocommand, search for the function again
|
||||||
fp = find_func(rfname, NULL);
|
fp = find_func(rfname, FALSE, NULL);
|
||||||
}
|
}
|
||||||
// Try loading a package.
|
// Try loading a package.
|
||||||
if (fp == NULL && script_autoload(rfname, TRUE) && !aborting())
|
if (fp == NULL && script_autoload(rfname, TRUE) && !aborting())
|
||||||
{
|
{
|
||||||
// loaded a package, search for the function again
|
// loaded a package, search for the function again
|
||||||
fp = find_func(rfname, NULL);
|
fp = find_func(rfname, FALSE, NULL);
|
||||||
}
|
}
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
{
|
{
|
||||||
@@ -1908,7 +1942,7 @@ call_func(
|
|||||||
// If using Vim9 script try not local to the script.
|
// If using Vim9 script try not local to the script.
|
||||||
// TODO: should not do this if the name started with "s:".
|
// TODO: should not do this if the name started with "s:".
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
fp = find_func(p, NULL);
|
fp = find_func(p, FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp != NULL && (fp->uf_flags & FC_DELETED))
|
if (fp != NULL && (fp->uf_flags & FC_DELETED))
|
||||||
@@ -2079,6 +2113,8 @@ list_func_head(ufunc_T *fp, int indent)
|
|||||||
* Get a function name, translating "<SID>" and "<SNR>".
|
* Get a function name, translating "<SID>" and "<SNR>".
|
||||||
* Also handles a Funcref in a List or Dictionary.
|
* Also handles a Funcref in a List or Dictionary.
|
||||||
* Returns the function name in allocated memory, or NULL for failure.
|
* Returns the function name in allocated memory, or NULL for failure.
|
||||||
|
* Set "*is_global" to TRUE when the function must be global, unless
|
||||||
|
* "is_global" is NULL.
|
||||||
* flags:
|
* flags:
|
||||||
* TFN_INT: internal function name OK
|
* TFN_INT: internal function name OK
|
||||||
* TFN_QUIET: be quiet
|
* TFN_QUIET: be quiet
|
||||||
@@ -2089,6 +2125,7 @@ list_func_head(ufunc_T *fp, int indent)
|
|||||||
char_u *
|
char_u *
|
||||||
trans_function_name(
|
trans_function_name(
|
||||||
char_u **pp,
|
char_u **pp,
|
||||||
|
int *is_global,
|
||||||
int skip, // only find the end, don't evaluate
|
int skip, // only find the end, don't evaluate
|
||||||
int flags,
|
int flags,
|
||||||
funcdict_T *fdp, // return: info about dictionary used
|
funcdict_T *fdp, // return: info about dictionary used
|
||||||
@@ -2239,7 +2276,11 @@ trans_function_name(
|
|||||||
{
|
{
|
||||||
// skip over "s:" and "g:"
|
// skip over "s:" and "g:"
|
||||||
if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
|
if (lead == 2 || (lv.ll_name[0] == 'g' && lv.ll_name[1] == ':'))
|
||||||
|
{
|
||||||
|
if (is_global != NULL && lv.ll_name[0] == 'g')
|
||||||
|
*is_global = TRUE;
|
||||||
lv.ll_name += 2;
|
lv.ll_name += 2;
|
||||||
|
}
|
||||||
len = (int)(end - lv.ll_name);
|
len = (int)(end - lv.ll_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2347,6 +2388,7 @@ ex_function(exarg_T *eap)
|
|||||||
int saved_did_emsg;
|
int saved_did_emsg;
|
||||||
int saved_wait_return = need_wait_return;
|
int saved_wait_return = need_wait_return;
|
||||||
char_u *name = NULL;
|
char_u *name = NULL;
|
||||||
|
int is_global = FALSE;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
char_u *arg;
|
char_u *arg;
|
||||||
char_u *line_arg = NULL;
|
char_u *line_arg = NULL;
|
||||||
@@ -2463,7 +2505,8 @@ ex_function(exarg_T *eap)
|
|||||||
* g:func global function name, same as "func"
|
* g:func global function name, same as "func"
|
||||||
*/
|
*/
|
||||||
p = eap->arg;
|
p = eap->arg;
|
||||||
name = trans_function_name(&p, eap->skip, TFN_NO_AUTOLOAD, &fudi, NULL);
|
name = trans_function_name(&p, &is_global, eap->skip,
|
||||||
|
TFN_NO_AUTOLOAD, &fudi, NULL);
|
||||||
paren = (vim_strchr(p, '(') != NULL);
|
paren = (vim_strchr(p, '(') != NULL);
|
||||||
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
|
if (name == NULL && (fudi.fd_dict == NULL || !paren) && !eap->skip)
|
||||||
{
|
{
|
||||||
@@ -2503,7 +2546,7 @@ ex_function(exarg_T *eap)
|
|||||||
*p = NUL;
|
*p = NUL;
|
||||||
if (!eap->skip && !got_int)
|
if (!eap->skip && !got_int)
|
||||||
{
|
{
|
||||||
fp = find_func(name, NULL);
|
fp = find_func(name, is_global, NULL);
|
||||||
if (fp == NULL && ASCII_ISUPPER(*eap->arg))
|
if (fp == NULL && ASCII_ISUPPER(*eap->arg))
|
||||||
{
|
{
|
||||||
char_u *up = untrans_function_name(name);
|
char_u *up = untrans_function_name(name);
|
||||||
@@ -2511,7 +2554,7 @@ ex_function(exarg_T *eap)
|
|||||||
// With Vim9 script the name was made script-local, if not
|
// With Vim9 script the name was made script-local, if not
|
||||||
// found try again with the original name.
|
// found try again with the original name.
|
||||||
if (up != NULL)
|
if (up != NULL)
|
||||||
fp = find_func(up, NULL);
|
fp = find_func(up, FALSE, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
@@ -2675,7 +2718,7 @@ ex_function(exarg_T *eap)
|
|||||||
{
|
{
|
||||||
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
|
if (fudi.fd_dict != NULL && fudi.fd_newkey == NULL)
|
||||||
emsg(_(e_funcdict));
|
emsg(_(e_funcdict));
|
||||||
else if (name != NULL && find_func(name, NULL) != NULL)
|
else if (name != NULL && find_func(name, is_global, NULL) != NULL)
|
||||||
emsg_funcname(e_funcexts, name);
|
emsg_funcname(e_funcexts, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2825,7 +2868,7 @@ ex_function(exarg_T *eap)
|
|||||||
if (*p == '!')
|
if (*p == '!')
|
||||||
p = skipwhite(p + 1);
|
p = skipwhite(p + 1);
|
||||||
p += eval_fname_script(p);
|
p += eval_fname_script(p);
|
||||||
vim_free(trans_function_name(&p, TRUE, 0, NULL, NULL));
|
vim_free(trans_function_name(&p, NULL, TRUE, 0, NULL, NULL));
|
||||||
if (*skipwhite(p) == '(')
|
if (*skipwhite(p) == '(')
|
||||||
{
|
{
|
||||||
if (nesting == MAX_FUNC_NESTING - 1)
|
if (nesting == MAX_FUNC_NESTING - 1)
|
||||||
@@ -2963,7 +3006,7 @@ ex_function(exarg_T *eap)
|
|||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fp = find_func_even_dead(name, NULL);
|
fp = find_func_even_dead(name, is_global, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
int dead = fp->uf_flags & FC_DEAD;
|
int dead = fp->uf_flags & FC_DEAD;
|
||||||
@@ -3208,6 +3251,8 @@ ex_function(exarg_T *eap)
|
|||||||
fp->uf_varargs = varargs;
|
fp->uf_varargs = varargs;
|
||||||
if (sandbox)
|
if (sandbox)
|
||||||
flags |= FC_SANDBOX;
|
flags |= FC_SANDBOX;
|
||||||
|
if (in_vim9script() && !ASCII_ISUPPER(*fp->uf_name))
|
||||||
|
flags |= FC_VIM9;
|
||||||
fp->uf_flags = flags;
|
fp->uf_flags = flags;
|
||||||
fp->uf_calls = 0;
|
fp->uf_calls = 0;
|
||||||
fp->uf_cleared = FALSE;
|
fp->uf_cleared = FALSE;
|
||||||
@@ -3261,11 +3306,11 @@ eval_fname_script(char_u *p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
translated_function_exists(char_u *name)
|
translated_function_exists(char_u *name, int is_global)
|
||||||
{
|
{
|
||||||
if (builtin_function(name, -1))
|
if (builtin_function(name, -1))
|
||||||
return has_internal_func(name);
|
return has_internal_func(name);
|
||||||
return find_func(name, NULL) != NULL;
|
return find_func(name, is_global, NULL) != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3289,17 +3334,18 @@ function_exists(char_u *name, int no_deref)
|
|||||||
char_u *p;
|
char_u *p;
|
||||||
int n = FALSE;
|
int n = FALSE;
|
||||||
int flag;
|
int flag;
|
||||||
|
int is_global = FALSE;
|
||||||
|
|
||||||
flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
|
flag = TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD;
|
||||||
if (no_deref)
|
if (no_deref)
|
||||||
flag |= TFN_NO_DEREF;
|
flag |= TFN_NO_DEREF;
|
||||||
p = trans_function_name(&nm, FALSE, flag, NULL, NULL);
|
p = trans_function_name(&nm, &is_global, FALSE, flag, NULL, NULL);
|
||||||
nm = skipwhite(nm);
|
nm = skipwhite(nm);
|
||||||
|
|
||||||
// Only accept "funcname", "funcname ", "funcname (..." and
|
// Only accept "funcname", "funcname ", "funcname (..." and
|
||||||
// "funcname(...", not "funcname!...".
|
// "funcname(...", not "funcname!...".
|
||||||
if (p != NULL && (*nm == NUL || *nm == '('))
|
if (p != NULL && (*nm == NUL || *nm == '('))
|
||||||
n = translated_function_exists(p);
|
n = translated_function_exists(p, is_global);
|
||||||
vim_free(p);
|
vim_free(p);
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@@ -3310,12 +3356,14 @@ get_expanded_name(char_u *name, int check)
|
|||||||
{
|
{
|
||||||
char_u *nm = name;
|
char_u *nm = name;
|
||||||
char_u *p;
|
char_u *p;
|
||||||
|
int is_global = FALSE;
|
||||||
|
|
||||||
p = trans_function_name(&nm, FALSE, TFN_INT|TFN_QUIET, NULL, NULL);
|
p = trans_function_name(&nm, &is_global, FALSE,
|
||||||
|
TFN_INT|TFN_QUIET, NULL, NULL);
|
||||||
|
|
||||||
if (p != NULL && *nm == NUL)
|
if (p != NULL && *nm == NUL
|
||||||
if (!check || translated_function_exists(p))
|
&& (!check || translated_function_exists(p, is_global)))
|
||||||
return p;
|
return p;
|
||||||
|
|
||||||
vim_free(p);
|
vim_free(p);
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -3376,9 +3424,10 @@ ex_delfunction(exarg_T *eap)
|
|||||||
char_u *p;
|
char_u *p;
|
||||||
char_u *name;
|
char_u *name;
|
||||||
funcdict_T fudi;
|
funcdict_T fudi;
|
||||||
|
int is_global = FALSE;
|
||||||
|
|
||||||
p = eap->arg;
|
p = eap->arg;
|
||||||
name = trans_function_name(&p, eap->skip, 0, &fudi, NULL);
|
name = trans_function_name(&p, &is_global, eap->skip, 0, &fudi, NULL);
|
||||||
vim_free(fudi.fd_newkey);
|
vim_free(fudi.fd_newkey);
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
{
|
{
|
||||||
@@ -3397,7 +3446,7 @@ ex_delfunction(exarg_T *eap)
|
|||||||
*p = NUL;
|
*p = NUL;
|
||||||
|
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
fp = find_func(name, NULL);
|
fp = find_func(name, is_global, NULL);
|
||||||
vim_free(name);
|
vim_free(name);
|
||||||
|
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
@@ -3413,6 +3462,11 @@ ex_delfunction(exarg_T *eap)
|
|||||||
semsg(_("E131: Cannot delete function %s: It is in use"), eap->arg);
|
semsg(_("E131: Cannot delete function %s: It is in use"), eap->arg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (fp->uf_flags & FC_VIM9)
|
||||||
|
{
|
||||||
|
semsg(_("E1084: Cannot delete Vim9 script function %s"), eap->arg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fudi.fd_dict != NULL)
|
if (fudi.fd_dict != NULL)
|
||||||
{
|
{
|
||||||
@@ -3452,7 +3506,7 @@ func_unref(char_u *name)
|
|||||||
|
|
||||||
if (name == NULL || !func_name_refcount(name))
|
if (name == NULL || !func_name_refcount(name))
|
||||||
return;
|
return;
|
||||||
fp = find_func(name, NULL);
|
fp = find_func(name, FALSE, NULL);
|
||||||
if (fp == NULL && isdigit(*name))
|
if (fp == NULL && isdigit(*name))
|
||||||
{
|
{
|
||||||
#ifdef EXITFREE
|
#ifdef EXITFREE
|
||||||
@@ -3495,7 +3549,7 @@ func_ref(char_u *name)
|
|||||||
|
|
||||||
if (name == NULL || !func_name_refcount(name))
|
if (name == NULL || !func_name_refcount(name))
|
||||||
return;
|
return;
|
||||||
fp = find_func(name, NULL);
|
fp = find_func(name, FALSE, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
++fp->uf_refcount;
|
++fp->uf_refcount;
|
||||||
else if (isdigit(*name))
|
else if (isdigit(*name))
|
||||||
@@ -3611,7 +3665,8 @@ ex_call(exarg_T *eap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
tofree = trans_function_name(&arg, eap->skip, TFN_INT, &fudi, &partial);
|
tofree = trans_function_name(&arg, NULL, eap->skip,
|
||||||
|
TFN_INT, &fudi, &partial);
|
||||||
if (fudi.fd_newkey != NULL)
|
if (fudi.fd_newkey != NULL)
|
||||||
{
|
{
|
||||||
// Still need to give an error message for missing key.
|
// Still need to give an error message for missing key.
|
||||||
@@ -3969,7 +4024,7 @@ make_partial(dict_T *selfdict_in, typval_T *rettv)
|
|||||||
: rettv->vval.v_partial->pt_name;
|
: rettv->vval.v_partial->pt_name;
|
||||||
// Translate "s:func" to the stored function name.
|
// Translate "s:func" to the stored function name.
|
||||||
fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
|
fname = fname_trans_sid(fname, fname_buf, &tofree, &error);
|
||||||
fp = find_func(fname, NULL);
|
fp = find_func(fname, FALSE, NULL);
|
||||||
vim_free(tofree);
|
vim_free(tofree);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4391,7 +4446,7 @@ set_ref_in_func(char_u *name, ufunc_T *fp_in, int copyID)
|
|||||||
if (fp_in == NULL)
|
if (fp_in == NULL)
|
||||||
{
|
{
|
||||||
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
fname = fname_trans_sid(name, fname_buf, &tofree, &error);
|
||||||
fp = find_func(fname, NULL);
|
fp = find_func(fname, FALSE, NULL);
|
||||||
}
|
}
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
|
@@ -746,6 +746,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 */
|
||||||
|
/**/
|
||||||
|
650,
|
||||||
/**/
|
/**/
|
||||||
649,
|
649,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -2210,7 +2210,7 @@ compile_load_scriptvar(
|
|||||||
static int
|
static int
|
||||||
generate_funcref(cctx_T *cctx, char_u *name)
|
generate_funcref(cctx_T *cctx, char_u *name)
|
||||||
{
|
{
|
||||||
ufunc_T *ufunc = find_func(name, cctx);
|
ufunc_T *ufunc = find_func(name, FALSE, cctx);
|
||||||
|
|
||||||
if (ufunc == NULL)
|
if (ufunc == NULL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
@@ -2452,7 +2452,7 @@ compile_call(char_u **arg, size_t varlen, cctx_T *cctx, int argcount_init)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we can find the function by name generate the right call.
|
// If we can find the function by name generate the right call.
|
||||||
ufunc = find_func(name, cctx);
|
ufunc = find_func(name, FALSE, cctx);
|
||||||
if (ufunc != NULL)
|
if (ufunc != NULL)
|
||||||
{
|
{
|
||||||
res = generate_CALL(cctx, ufunc, argcount);
|
res = generate_CALL(cctx, ufunc, argcount);
|
||||||
|
@@ -400,7 +400,7 @@ call_by_name(char_u *name, int argcount, ectx_T *ectx, isn_T *iptr)
|
|||||||
return call_bfunc(func_idx, argcount, ectx);
|
return call_bfunc(func_idx, argcount, ectx);
|
||||||
}
|
}
|
||||||
|
|
||||||
ufunc = find_func(name, NULL);
|
ufunc = find_func(name, FALSE, NULL);
|
||||||
if (ufunc != NULL)
|
if (ufunc != NULL)
|
||||||
return call_ufunc(ufunc, argcount, ectx, iptr);
|
return call_ufunc(ufunc, argcount, ectx, iptr);
|
||||||
|
|
||||||
@@ -1944,8 +1944,9 @@ ex_disassemble(exarg_T *eap)
|
|||||||
int current;
|
int current;
|
||||||
int line_idx = 0;
|
int line_idx = 0;
|
||||||
int prev_current = 0;
|
int prev_current = 0;
|
||||||
|
int is_global = FALSE;
|
||||||
|
|
||||||
fname = trans_function_name(&arg, FALSE,
|
fname = trans_function_name(&arg, &is_global, FALSE,
|
||||||
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
|
TFN_INT | TFN_QUIET | TFN_NO_AUTOLOAD | TFN_NO_DEREF, NULL, NULL);
|
||||||
if (fname == NULL)
|
if (fname == NULL)
|
||||||
{
|
{
|
||||||
@@ -1953,14 +1954,14 @@ ex_disassemble(exarg_T *eap)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
ufunc = find_func(fname, NULL);
|
ufunc = find_func(fname, is_global, NULL);
|
||||||
if (ufunc == NULL)
|
if (ufunc == NULL)
|
||||||
{
|
{
|
||||||
char_u *p = untrans_function_name(fname);
|
char_u *p = untrans_function_name(fname);
|
||||||
|
|
||||||
if (p != NULL)
|
if (p != NULL)
|
||||||
// Try again without making it script-local.
|
// Try again without making it script-local.
|
||||||
ufunc = find_func(p, NULL);
|
ufunc = find_func(p, FALSE, NULL);
|
||||||
}
|
}
|
||||||
vim_free(fname);
|
vim_free(fname);
|
||||||
if (ufunc == NULL)
|
if (ufunc == NULL)
|
||||||
|
@@ -217,7 +217,7 @@ find_exported(
|
|||||||
funcname[1] = KS_EXTRA;
|
funcname[1] = KS_EXTRA;
|
||||||
funcname[2] = (int)KE_SNR;
|
funcname[2] = (int)KE_SNR;
|
||||||
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
|
sprintf((char *)funcname + 3, "%ld_%s", (long)sid, name);
|
||||||
*ufunc = find_func(funcname, NULL);
|
*ufunc = find_func(funcname, FALSE, NULL);
|
||||||
if (funcname != buffer)
|
if (funcname != buffer)
|
||||||
vim_free(funcname);
|
vim_free(funcname);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user