mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.0419: various memory leaks in Vim9 script code
Problem: Various memory leaks in Vim9 script code. Solution: Fix the leaks. (Ozaki Kiichi, closes #5814)
This commit is contained in:
@@ -9,6 +9,7 @@ imported_T *find_imported(char_u *name, size_t len, cctx_T *cctx);
|
|||||||
char_u *to_name_const_end(char_u *arg);
|
char_u *to_name_const_end(char_u *arg);
|
||||||
int assignment_len(char_u *p, int *heredoc);
|
int assignment_len(char_u *p, int *heredoc);
|
||||||
void compile_def_function(ufunc_T *ufunc, int set_return_type);
|
void compile_def_function(ufunc_T *ufunc, int set_return_type);
|
||||||
|
void delete_instr(isn_T *isn);
|
||||||
void delete_def_function(ufunc_T *ufunc);
|
void delete_def_function(ufunc_T *ufunc);
|
||||||
void free_def_functions(void);
|
void free_def_functions(void);
|
||||||
/* vim: set ft=c : */
|
/* vim: set ft=c : */
|
||||||
|
@@ -1526,6 +1526,7 @@ free_scriptnames(void)
|
|||||||
vim_free(si->sn_vars);
|
vim_free(si->sn_vars);
|
||||||
|
|
||||||
vim_free(si->sn_name);
|
vim_free(si->sn_name);
|
||||||
|
free_imports(i);
|
||||||
free_string_option(si->sn_save_cpo);
|
free_string_option(si->sn_save_cpo);
|
||||||
# ifdef FEAT_PROFILE
|
# ifdef FEAT_PROFILE
|
||||||
ga_clear(&si->sn_prl_ga);
|
ga_clear(&si->sn_prl_ga);
|
||||||
|
@@ -1308,6 +1308,7 @@ typedef struct {
|
|||||||
int cb_free_name; // cb_name was allocated
|
int cb_free_name; // cb_name was allocated
|
||||||
} callback_T;
|
} callback_T;
|
||||||
|
|
||||||
|
typedef struct isn_S isn_T; // instruction
|
||||||
typedef struct dfunc_S dfunc_T; // :def function
|
typedef struct dfunc_S dfunc_T; // :def function
|
||||||
|
|
||||||
typedef struct jobvar_S job_T;
|
typedef struct jobvar_S job_T;
|
||||||
|
@@ -942,6 +942,16 @@ def Test_while_loop()
|
|||||||
assert_equal('1_3_', result)
|
assert_equal('1_3_', result)
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_interrupt_loop()
|
||||||
|
let x = 0
|
||||||
|
while 1
|
||||||
|
x += 1
|
||||||
|
if x == 100
|
||||||
|
feedkeys("\<C-C>", 'L')
|
||||||
|
endif
|
||||||
|
endwhile
|
||||||
|
enddef
|
||||||
|
|
||||||
def Test_substitute_cmd()
|
def Test_substitute_cmd()
|
||||||
new
|
new
|
||||||
setline(1, 'something')
|
setline(1, 'something')
|
||||||
@@ -964,4 +974,24 @@ def Test_substitute_cmd()
|
|||||||
delete('Xvim9lines')
|
delete('Xvim9lines')
|
||||||
enddef
|
enddef
|
||||||
|
|
||||||
|
def Test_redef_failure()
|
||||||
|
call writefile(['def Func0(): string', 'return "Func0"', 'enddef'], 'Xdef')
|
||||||
|
so Xdef
|
||||||
|
call writefile(['def Func1(): string', 'return "Func1"', 'enddef'], 'Xdef')
|
||||||
|
so Xdef
|
||||||
|
call writefile(['def! Func0(): string', 'enddef'], 'Xdef')
|
||||||
|
call assert_fails('so Xdef', 'E1027:')
|
||||||
|
call writefile(['def Func2(): string', 'return "Func2"', 'enddef'], 'Xdef')
|
||||||
|
so Xdef
|
||||||
|
call delete('Xdef')
|
||||||
|
|
||||||
|
call assert_equal(0, Func0())
|
||||||
|
call assert_equal('Func1', Func1())
|
||||||
|
call assert_equal('Func2', Func2())
|
||||||
|
|
||||||
|
delfunc! Func0
|
||||||
|
delfunc! Func1
|
||||||
|
delfunc! Func2
|
||||||
|
enddef
|
||||||
|
|
||||||
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
|
||||||
|
@@ -738,6 +738,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 */
|
||||||
|
/**/
|
||||||
|
419,
|
||||||
/**/
|
/**/
|
||||||
418,
|
418,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -203,7 +203,7 @@ typedef struct {
|
|||||||
/*
|
/*
|
||||||
* Instruction
|
* Instruction
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
struct isn_S {
|
||||||
isntype_T isn_type;
|
isntype_T isn_type;
|
||||||
int isn_lnum;
|
int isn_lnum;
|
||||||
union {
|
union {
|
||||||
@@ -231,7 +231,7 @@ typedef struct {
|
|||||||
loadstore_T loadstore;
|
loadstore_T loadstore;
|
||||||
script_T script;
|
script_T script;
|
||||||
} isn_arg;
|
} isn_arg;
|
||||||
} isn_T;
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Info about a function defined with :def. Used in "def_functions".
|
* Info about a function defined with :def. Used in "def_functions".
|
||||||
|
@@ -129,6 +129,7 @@ static char e_syntax_at[] = N_("E1002: Syntax error at %s");
|
|||||||
static int compile_expr1(char_u **arg, cctx_T *cctx);
|
static int compile_expr1(char_u **arg, cctx_T *cctx);
|
||||||
static int compile_expr2(char_u **arg, cctx_T *cctx);
|
static int compile_expr2(char_u **arg, cctx_T *cctx);
|
||||||
static int compile_expr3(char_u **arg, cctx_T *cctx);
|
static int compile_expr3(char_u **arg, cctx_T *cctx);
|
||||||
|
static void delete_def_function_contents(dfunc_T *dfunc);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lookup variable "name" in the local scope and return the index.
|
* Lookup variable "name" in the local scope and return the index.
|
||||||
@@ -1305,6 +1306,36 @@ reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type)
|
|||||||
return idx;
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove local variables above "new_top".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
unwind_locals(cctx_T *cctx, int new_top)
|
||||||
|
{
|
||||||
|
if (cctx->ctx_locals.ga_len > new_top)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
lvar_T *lvar;
|
||||||
|
|
||||||
|
for (idx = new_top; idx < cctx->ctx_locals.ga_len; ++idx)
|
||||||
|
{
|
||||||
|
lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + idx;
|
||||||
|
vim_free(lvar->lv_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cctx->ctx_locals.ga_len = new_top;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free all local variables.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
free_local(cctx_T *cctx)
|
||||||
|
{
|
||||||
|
unwind_locals(cctx, 0);
|
||||||
|
ga_clear(&cctx->ctx_locals);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Skip over a type definition and return a pointer to just after it.
|
* Skip over a type definition and return a pointer to just after it.
|
||||||
*/
|
*/
|
||||||
@@ -1671,6 +1702,23 @@ find_imported(char_u *name, size_t len, cctx_T *cctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free all imported variables.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
free_imported(cctx_T *cctx)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < cctx->ctx_imports.ga_len; ++idx)
|
||||||
|
{
|
||||||
|
imported_T *import = ((imported_T *)cctx->ctx_imports.ga_data) + idx;
|
||||||
|
|
||||||
|
vim_free(import->imp_name);
|
||||||
|
}
|
||||||
|
ga_clear(&cctx->ctx_imports);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Generate an instruction to load script-local variable "name".
|
* Generate an instruction to load script-local variable "name".
|
||||||
*/
|
*/
|
||||||
@@ -2127,7 +2175,10 @@ compile_lambda(char_u **arg, cctx_T *cctx)
|
|||||||
// Get the funcref in "rettv".
|
// Get the funcref in "rettv".
|
||||||
if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
|
if (get_lambda_tv(arg, &rettv, TRUE) == FAIL)
|
||||||
return FAIL;
|
return FAIL;
|
||||||
|
|
||||||
ufunc = rettv.vval.v_partial->pt_func;
|
ufunc = rettv.vval.v_partial->pt_func;
|
||||||
|
++ufunc->uf_refcount;
|
||||||
|
clear_tv(&rettv);
|
||||||
|
|
||||||
// The function will have one line: "return {expr}".
|
// The function will have one line: "return {expr}".
|
||||||
// Compile it into instructions.
|
// Compile it into instructions.
|
||||||
@@ -2169,10 +2220,12 @@ compile_lambda_call(char_u **arg, cctx_T *cctx)
|
|||||||
return FAIL;
|
return FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The function will have one line: "return {expr}".
|
|
||||||
// Compile it into instructions.
|
|
||||||
ufunc = rettv.vval.v_partial->pt_func;
|
ufunc = rettv.vval.v_partial->pt_func;
|
||||||
++ufunc->uf_refcount;
|
++ufunc->uf_refcount;
|
||||||
|
clear_tv(&rettv);
|
||||||
|
|
||||||
|
// The function will have one line: "return {expr}".
|
||||||
|
// Compile it into instructions.
|
||||||
compile_def_function(ufunc, TRUE);
|
compile_def_function(ufunc, TRUE);
|
||||||
|
|
||||||
// compile the arguments
|
// compile the arguments
|
||||||
@@ -2181,7 +2234,6 @@ compile_lambda_call(char_u **arg, cctx_T *cctx)
|
|||||||
// call the compiled function
|
// call the compiled function
|
||||||
ret = generate_CALL(cctx, ufunc, argcount);
|
ret = generate_CALL(cctx, ufunc, argcount);
|
||||||
|
|
||||||
clear_tv(&rettv);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3398,7 +3450,6 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
{
|
{
|
||||||
int cc;
|
int cc;
|
||||||
long numval;
|
long numval;
|
||||||
char_u *stringval = NULL;
|
|
||||||
|
|
||||||
dest = dest_option;
|
dest = dest_option;
|
||||||
if (cmdidx == CMD_const)
|
if (cmdidx == CMD_const)
|
||||||
@@ -3420,7 +3471,7 @@ compile_assignment(char_u *arg, exarg_T *eap, cmdidx_T cmdidx, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
cc = *p;
|
cc = *p;
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
opt_type = get_option_value(arg + 1, &numval, &stringval, opt_flags);
|
opt_type = get_option_value(arg + 1, &numval, NULL, opt_flags);
|
||||||
*p = cc;
|
*p = cc;
|
||||||
if (opt_type == -3)
|
if (opt_type == -3)
|
||||||
{
|
{
|
||||||
@@ -4217,7 +4268,7 @@ compile_elseif(char_u *arg, cctx_T *cctx)
|
|||||||
emsg(_(e_elseif_without_if));
|
emsg(_(e_elseif_without_if));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
if (cctx->ctx_skip == MAYBE)
|
if (cctx->ctx_skip == MAYBE)
|
||||||
{
|
{
|
||||||
@@ -4265,7 +4316,7 @@ compile_else(char_u *arg, cctx_T *cctx)
|
|||||||
emsg(_(e_else_without_if));
|
emsg(_(e_else_without_if));
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
// jump from previous block to the end, unless the else block is empty
|
// jump from previous block to the end, unless the else block is empty
|
||||||
if (cctx->ctx_skip == MAYBE)
|
if (cctx->ctx_skip == MAYBE)
|
||||||
@@ -4307,7 +4358,7 @@ compile_endif(char_u *arg, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
ifscope = &scope->se_u.se_if;
|
ifscope = &scope->se_u.se_if;
|
||||||
cctx->ctx_scope = scope->se_outer;
|
cctx->ctx_scope = scope->se_outer;
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
if (scope->se_u.se_if.is_if_label >= 0)
|
if (scope->se_u.se_if.is_if_label >= 0)
|
||||||
{
|
{
|
||||||
@@ -4435,7 +4486,7 @@ compile_endfor(char_u *arg, cctx_T *cctx)
|
|||||||
}
|
}
|
||||||
forscope = &scope->se_u.se_for;
|
forscope = &scope->se_u.se_for;
|
||||||
cctx->ctx_scope = scope->se_outer;
|
cctx->ctx_scope = scope->se_outer;
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
// At end of ":for" scope jump back to the FOR instruction.
|
// At end of ":for" scope jump back to the FOR instruction.
|
||||||
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
generate_JUMP(cctx, JUMP_ALWAYS, forscope->fs_top_label);
|
||||||
@@ -4506,7 +4557,7 @@ compile_endwhile(char_u *arg, cctx_T *cctx)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
cctx->ctx_scope = scope->se_outer;
|
cctx->ctx_scope = scope->se_outer;
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
|
|
||||||
// At end of ":for" scope jump back to the FOR instruction.
|
// At end of ":for" scope jump back to the FOR instruction.
|
||||||
generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
|
generate_JUMP(cctx, JUMP_ALWAYS, scope->se_u.se_while.ws_top_label);
|
||||||
@@ -4599,7 +4650,7 @@ compile_endblock(cctx_T *cctx)
|
|||||||
scope_T *scope = cctx->ctx_scope;
|
scope_T *scope = cctx->ctx_scope;
|
||||||
|
|
||||||
cctx->ctx_scope = scope->se_outer;
|
cctx->ctx_scope = scope->se_outer;
|
||||||
cctx->ctx_locals.ga_len = scope->se_local_count;
|
unwind_locals(cctx, scope->se_local_count);
|
||||||
vim_free(scope);
|
vim_free(scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4942,9 +4993,11 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
|
|
||||||
if (ufunc->uf_dfunc_idx >= 0)
|
if (ufunc->uf_dfunc_idx >= 0)
|
||||||
{
|
{
|
||||||
// redefining a function that was compiled before
|
// Redefining a function that was compiled before.
|
||||||
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx;
|
||||||
dfunc->df_deleted = FALSE;
|
|
||||||
|
// Free old instructions.
|
||||||
|
delete_def_function_contents(dfunc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -5305,6 +5358,7 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
generate_instr(&cctx, ISN_RETURN);
|
generate_instr(&cctx, ISN_RETURN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dfunc->df_deleted = FALSE;
|
||||||
dfunc->df_instr = instr->ga_data;
|
dfunc->df_instr = instr->ga_data;
|
||||||
dfunc->df_instr_count = instr->ga_len;
|
dfunc->df_instr_count = instr->ga_len;
|
||||||
dfunc->df_varcount = cctx.ctx_max_local;
|
dfunc->df_varcount = cctx.ctx_max_local;
|
||||||
@@ -5314,27 +5368,35 @@ compile_def_function(ufunc_T *ufunc, int set_return_type)
|
|||||||
erret:
|
erret:
|
||||||
if (ret == FAIL)
|
if (ret == FAIL)
|
||||||
{
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < instr->ga_len; ++idx)
|
||||||
|
delete_instr(((isn_T *)instr->ga_data) + idx);
|
||||||
ga_clear(instr);
|
ga_clear(instr);
|
||||||
|
|
||||||
ufunc->uf_dfunc_idx = -1;
|
ufunc->uf_dfunc_idx = -1;
|
||||||
--def_functions.ga_len;
|
if (!dfunc->df_deleted)
|
||||||
|
--def_functions.ga_len;
|
||||||
|
|
||||||
|
// Don't execute this function body.
|
||||||
|
ga_clear_strings(&ufunc->uf_lines);
|
||||||
|
|
||||||
if (errormsg != NULL)
|
if (errormsg != NULL)
|
||||||
emsg(errormsg);
|
emsg(errormsg);
|
||||||
else if (called_emsg == called_emsg_before)
|
else if (called_emsg == called_emsg_before)
|
||||||
emsg(_("E1028: compile_def_function failed"));
|
emsg(_("E1028: compile_def_function failed"));
|
||||||
|
|
||||||
// don't execute this function body
|
|
||||||
ufunc->uf_lines.ga_len = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
current_sctx = save_current_sctx;
|
current_sctx = save_current_sctx;
|
||||||
|
free_imported(&cctx);
|
||||||
|
free_local(&cctx);
|
||||||
ga_clear(&cctx.ctx_type_stack);
|
ga_clear(&cctx.ctx_type_stack);
|
||||||
ga_clear(&cctx.ctx_locals);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Delete an instruction, free what it contains.
|
* Delete an instruction, free what it contains.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
delete_instr(isn_T *isn)
|
delete_instr(isn_T *isn)
|
||||||
{
|
{
|
||||||
switch (isn->isn_type)
|
switch (isn->isn_type)
|
||||||
@@ -5442,33 +5504,58 @@ delete_instr(isn_T *isn)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free all instructions for "dfunc".
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
delete_def_function_contents(dfunc_T *dfunc)
|
||||||
|
{
|
||||||
|
int idx;
|
||||||
|
|
||||||
|
ga_clear(&dfunc->df_def_args_isn);
|
||||||
|
|
||||||
|
if (dfunc->df_instr != NULL)
|
||||||
|
{
|
||||||
|
for (idx = 0; idx < dfunc->df_instr_count; ++idx)
|
||||||
|
delete_instr(dfunc->df_instr + idx);
|
||||||
|
VIM_CLEAR(dfunc->df_instr);
|
||||||
|
}
|
||||||
|
|
||||||
|
dfunc->df_deleted = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* When a user function is deleted, delete any associated def function.
|
* When a user function is deleted, delete any associated def function.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
delete_def_function(ufunc_T *ufunc)
|
delete_def_function(ufunc_T *ufunc)
|
||||||
{
|
{
|
||||||
int idx;
|
|
||||||
|
|
||||||
if (ufunc->uf_dfunc_idx >= 0)
|
if (ufunc->uf_dfunc_idx >= 0)
|
||||||
{
|
{
|
||||||
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data)
|
||||||
+ ufunc->uf_dfunc_idx;
|
+ ufunc->uf_dfunc_idx;
|
||||||
ga_clear(&dfunc->df_def_args_isn);
|
|
||||||
|
|
||||||
for (idx = 0; idx < dfunc->df_instr_count; ++idx)
|
delete_def_function_contents(dfunc);
|
||||||
delete_instr(dfunc->df_instr + idx);
|
|
||||||
VIM_CLEAR(dfunc->df_instr);
|
|
||||||
|
|
||||||
dfunc->df_deleted = TRUE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(EXITFREE) || defined(PROTO)
|
#if defined(EXITFREE) || defined(PROTO)
|
||||||
|
/*
|
||||||
|
* Free all functions defined with ":def".
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
free_def_functions(void)
|
free_def_functions(void)
|
||||||
{
|
{
|
||||||
vim_free(def_functions.ga_data);
|
int idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < def_functions.ga_len; ++idx)
|
||||||
|
{
|
||||||
|
dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + idx;
|
||||||
|
|
||||||
|
delete_def_function_contents(dfunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
ga_clear(&def_functions);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@@ -283,6 +283,7 @@ call_ufunc(ufunc_T *ufunc, int argcount, ectx_T *ectx, isn_T *iptr)
|
|||||||
// that was defined later: we can call it directly next time.
|
// that was defined later: we can call it directly next time.
|
||||||
if (iptr != NULL)
|
if (iptr != NULL)
|
||||||
{
|
{
|
||||||
|
delete_instr(iptr);
|
||||||
iptr->isn_type = ISN_DCALL;
|
iptr->isn_type = ISN_DCALL;
|
||||||
iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
|
iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx;
|
||||||
iptr->isn_arg.dfunc.cdf_argcount = argcount;
|
iptr->isn_arg.dfunc.cdf_argcount = argcount;
|
||||||
@@ -480,11 +481,21 @@ call_def_function(
|
|||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
isn_T *iptr;
|
isn_T *iptr;
|
||||||
trycmd_T *trycmd = NULL;
|
|
||||||
|
veryfast_breakcheck();
|
||||||
|
if (got_int)
|
||||||
|
{
|
||||||
|
// Turn CTRL-C into an exception.
|
||||||
|
got_int = FALSE;
|
||||||
|
if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) != FAIL)
|
||||||
|
goto failed;
|
||||||
|
did_throw = TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
if (did_throw && !ectx.ec_in_catch)
|
if (did_throw && !ectx.ec_in_catch)
|
||||||
{
|
{
|
||||||
garray_T *trystack = &ectx.ec_trystack;
|
garray_T *trystack = &ectx.ec_trystack;
|
||||||
|
trycmd_T *trycmd = NULL;
|
||||||
|
|
||||||
// An exception jumps to the first catch, finally, or returns from
|
// An exception jumps to the first catch, finally, or returns from
|
||||||
// the current function.
|
// the current function.
|
||||||
@@ -782,8 +793,9 @@ call_def_function(
|
|||||||
// store $ENV
|
// store $ENV
|
||||||
case ISN_STOREENV:
|
case ISN_STOREENV:
|
||||||
--ectx.ec_stack.ga_len;
|
--ectx.ec_stack.ga_len;
|
||||||
vim_setenv_ext(iptr->isn_arg.string,
|
tv = STACK_TV_BOT(0);
|
||||||
tv_get_string(STACK_TV_BOT(0)));
|
vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv));
|
||||||
|
clear_tv(tv);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// store @r
|
// store @r
|
||||||
@@ -1038,6 +1050,7 @@ call_def_function(
|
|||||||
case ISN_RETURN:
|
case ISN_RETURN:
|
||||||
{
|
{
|
||||||
garray_T *trystack = &ectx.ec_trystack;
|
garray_T *trystack = &ectx.ec_trystack;
|
||||||
|
trycmd_T *trycmd = NULL;
|
||||||
|
|
||||||
if (trystack->ga_len > 0)
|
if (trystack->ga_len > 0)
|
||||||
trycmd = ((trycmd_T *)trystack->ga_data)
|
trycmd = ((trycmd_T *)trystack->ga_data)
|
||||||
@@ -1146,6 +1159,8 @@ call_def_function(
|
|||||||
// start of ":try" block
|
// start of ":try" block
|
||||||
case ISN_TRY:
|
case ISN_TRY:
|
||||||
{
|
{
|
||||||
|
trycmd_T *trycmd = NULL;
|
||||||
|
|
||||||
if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
|
if (ga_grow(&ectx.ec_trystack, 1) == FAIL)
|
||||||
goto failed;
|
goto failed;
|
||||||
trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
|
trycmd = ((trycmd_T *)ectx.ec_trystack.ga_data)
|
||||||
@@ -1180,7 +1195,7 @@ call_def_function(
|
|||||||
|
|
||||||
if (trystack->ga_len > 0)
|
if (trystack->ga_len > 0)
|
||||||
{
|
{
|
||||||
trycmd = ((trycmd_T *)trystack->ga_data)
|
trycmd_T *trycmd = ((trycmd_T *)trystack->ga_data)
|
||||||
+ trystack->ga_len - 1;
|
+ trystack->ga_len - 1;
|
||||||
trycmd->tcd_caught = TRUE;
|
trycmd->tcd_caught = TRUE;
|
||||||
}
|
}
|
||||||
@@ -1196,6 +1211,8 @@ call_def_function(
|
|||||||
|
|
||||||
if (trystack->ga_len > 0)
|
if (trystack->ga_len > 0)
|
||||||
{
|
{
|
||||||
|
trycmd_T *trycmd = NULL;
|
||||||
|
|
||||||
--trystack->ga_len;
|
--trystack->ga_len;
|
||||||
--trylevel;
|
--trylevel;
|
||||||
trycmd = ((trycmd_T *)trystack->ga_data)
|
trycmd = ((trycmd_T *)trystack->ga_data)
|
||||||
@@ -1677,6 +1694,7 @@ failed:
|
|||||||
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
|
for (idx = 0; idx < ectx.ec_stack.ga_len; ++idx)
|
||||||
clear_tv(STACK_TV(idx));
|
clear_tv(STACK_TV(idx));
|
||||||
vim_free(ectx.ec_stack.ga_data);
|
vim_free(ectx.ec_stack.ga_data);
|
||||||
|
vim_free(ectx.ec_trystack.ga_data);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -119,11 +119,13 @@ free_imports(int sid)
|
|||||||
|
|
||||||
for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
|
for (idx = 0; idx < si->sn_imports.ga_len; ++idx)
|
||||||
{
|
{
|
||||||
imported_T *imp = ((imported_T *)si->sn_imports.ga_data + idx);
|
imported_T *imp = ((imported_T *)si->sn_imports.ga_data) + idx;
|
||||||
|
|
||||||
vim_free(imp->imp_name);
|
vim_free(imp->imp_name);
|
||||||
}
|
}
|
||||||
ga_clear(&si->sn_imports);
|
ga_clear(&si->sn_imports);
|
||||||
|
ga_clear(&si->sn_var_vals);
|
||||||
|
ga_clear(&si->sn_type_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Reference in New Issue
Block a user