diff options
Diffstat (limited to 'src/vim9execute.c')
-rw-r--r-- | src/vim9execute.c | 1507 |
1 files changed, 816 insertions, 691 deletions
diff --git a/src/vim9execute.c b/src/vim9execute.c index 60b58f98a3..6a11e8a6bc 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -34,6 +34,14 @@ typedef struct { int tcd_return; // when TRUE return from end of :finally } trycmd_T; +// Data local to a function. +// On a function call, if not empty, is saved on the stack and restored when +// returning. +typedef struct { + int floc_restore_cmdmod; + cmdmod_T floc_save_cmdmod; + int floc_restore_cmdmod_stacklen; +} funclocal_T; // A stack is used to store: // - arguments passed to a :def function @@ -60,8 +68,10 @@ typedef struct { struct ectx_S { garray_T ec_stack; // stack of typval_T values int ec_frame_idx; // index in ec_stack: context of ec_dfunc_idx + int ec_initial_frame_idx; // frame index when called outer_T *ec_outer; // outer scope used for closures, allocated + funclocal_T ec_funclocal; garray_T ec_trystack; // stack of trycmd_T values int ec_in_catch; // when TRUE in catch or finally block @@ -71,6 +81,10 @@ struct ectx_S { int ec_iidx; // index in ec_instr: instruction to execute garray_T ec_funcrefs; // partials that might be a closure + + int ec_did_emsg_before; + int ec_trylevel_at_start; + where_T ec_where; }; #ifdef FEAT_PROFILE @@ -125,15 +139,6 @@ exe_newlist(int count, ectx_T *ectx) return OK; } -// Data local to a function. -// On a function call, if not empty, is saved on the stack and restored when -// returning. -typedef struct { - int floc_restore_cmdmod; - cmdmod_T floc_save_cmdmod; - int floc_restore_cmdmod_stacklen; -} funclocal_T; - /* * Call compiled function "cdf_idx" from compiled code. * This adds a stack frame and sets the instruction pointer to the start of the @@ -154,7 +159,6 @@ call_dfunc( int cdf_idx, partial_T *pt, int argcount_arg, - funclocal_T *funclocal, ectx_T *ectx) { int argcount = argcount_arg; @@ -254,13 +258,13 @@ call_dfunc( return FAIL; // Only make a copy of funclocal if it contains something to restore. - if (funclocal->floc_restore_cmdmod) + if (ectx->ec_funclocal.floc_restore_cmdmod) { floc = ALLOC_ONE(funclocal_T); if (floc == NULL) return FAIL; - *floc = *funclocal; - funclocal->floc_restore_cmdmod = FALSE; + *floc = ectx->ec_funclocal; + ectx->ec_funclocal.floc_restore_cmdmod = FALSE; } // Move the vararg-list to below the missing optional arguments. @@ -527,7 +531,7 @@ funcstack_check_refcount(funcstack_T *funcstack) * Return from the current function. */ static int -func_return(funclocal_T *funclocal, ectx_T *ectx) +func_return(ectx_T *ectx) { int idx; int ret_idx; @@ -598,10 +602,10 @@ func_return(funclocal_T *funclocal, ectx_T *ectx) ectx->ec_instr = INSTRUCTIONS(prev_dfunc); if (floc == NULL) - funclocal->floc_restore_cmdmod = FALSE; + ectx->ec_funclocal.floc_restore_cmdmod = FALSE; else { - *funclocal = *floc; + ectx->ec_funclocal = *floc; vim_free(floc); } @@ -698,7 +702,6 @@ call_ufunc( ufunc_T *ufunc, partial_T *pt, int argcount, - funclocal_T *funclocal, ectx_T *ectx, isn_T *iptr) { @@ -738,7 +741,7 @@ call_ufunc( iptr->isn_arg.dfunc.cdf_idx = ufunc->uf_dfunc_idx; iptr->isn_arg.dfunc.cdf_argcount = argcount; } - return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, funclocal, ectx); + return call_dfunc(ufunc->uf_dfunc_idx, pt, argcount, ectx); } if (call_prepare(argcount, argvars, ectx) == FAIL) @@ -800,7 +803,6 @@ vim9_aborting(int prev_called_emsg) call_by_name( char_u *name, int argcount, - funclocal_T *funclocal, ectx_T *ectx, isn_T *iptr) { @@ -853,7 +855,7 @@ call_by_name( } } - return call_ufunc(ufunc, NULL, argcount, funclocal, ectx, iptr); + return call_ufunc(ufunc, NULL, argcount, ectx, iptr); } return FAIL; @@ -863,7 +865,6 @@ call_by_name( call_partial( typval_T *tv, int argcount_arg, - funclocal_T *funclocal, ectx_T *ectx) { int argcount = argcount_arg; @@ -893,7 +894,7 @@ call_partial( } if (pt->pt_func != NULL) - return call_ufunc(pt->pt_func, pt, argcount, funclocal, ectx, NULL); + return call_ufunc(pt->pt_func, pt, argcount, ectx, NULL); name = pt->pt_name; } @@ -911,7 +912,7 @@ call_partial( if (error != FCERR_NONE) res = FAIL; else - res = call_by_name(fname, argcount, funclocal, ectx, NULL); + res = call_by_name(fname, argcount, ectx, NULL); vim_free(tofree); } @@ -1184,14 +1185,13 @@ get_script_svar(scriptref_T *sref, ectx_T *ectx) call_eval_func( char_u *name, int argcount, - funclocal_T *funclocal, ectx_T *ectx, isn_T *iptr) { int called_emsg_before = called_emsg; int res; - res = call_by_name(name, argcount, funclocal, ectx, iptr); + res = call_by_name(name, argcount, ectx, iptr); if (res == FAIL && called_emsg == called_emsg_before) { dictitem_T *v; @@ -1207,7 +1207,7 @@ call_eval_func( semsg(_(e_unknownfunc), name); return FAIL; } - return call_partial(&v->di_tv, argcount, funclocal, ectx); + return call_partial(&v->di_tv, argcount, ectx); } return res; } @@ -1257,255 +1257,35 @@ fill_partial_and_closure(partial_T *pt, ufunc_T *ufunc, ectx_T *ectx) return OK; } - -/* - * Call a "def" function from old Vim script. - * Return OK or FAIL. - */ - int -call_def_function( - ufunc_T *ufunc, - int argc_arg, // nr of arguments - typval_T *argv, // arguments - partial_T *partial, // optional partial for context - typval_T *rettv) // return value -{ - ectx_T ectx; // execution context - int argc = argc_arg; - int initial_frame_idx; - typval_T *tv; - int idx; - int ret = FAIL; - int defcount = ufunc->uf_args.ga_len - argc; - sctx_T save_current_sctx = current_sctx; - int breakcheck_count = 0; - int did_emsg_before = did_emsg_cumul + did_emsg; - int save_suppress_errthrow = suppress_errthrow; - msglist_T **saved_msg_list = NULL; - msglist_T *private_msg_list = NULL; - funclocal_T funclocal; - int save_emsg_silent_def = emsg_silent_def; - int save_did_emsg_def = did_emsg_def; - int trylevel_at_start = trylevel; - int orig_funcdepth; - where_T where; +// used for substitute_instr +typedef struct subs_expr_S { + ectx_T *subs_ectx; + isn_T *subs_instr; + int subs_status; +} subs_expr_T; // Get pointer to item in the stack. -#define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) +#define STACK_TV(idx) (((typval_T *)ectx->ec_stack.ga_data) + idx) // Get pointer to item at the bottom of the stack, -1 is the bottom. #undef STACK_TV_BOT -#define STACK_TV_BOT(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_stack.ga_len + idx) +#define STACK_TV_BOT(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_stack.ga_len + idx) // Get pointer to a local variable on the stack. Negative for arguments. -#define STACK_TV_VAR(idx) (((typval_T *)ectx.ec_stack.ga_data) + ectx.ec_frame_idx + STACK_FRAME_SIZE + idx) - - if (ufunc->uf_def_status == UF_NOT_COMPILED - || ufunc->uf_def_status == UF_COMPILE_ERROR - || (func_needs_compiling(ufunc, PROFILING(ufunc)) - && compile_def_function(ufunc, FALSE, PROFILING(ufunc), NULL) - == FAIL)) - { - if (did_emsg_cumul + did_emsg == did_emsg_before) - semsg(_(e_function_is_not_compiled_str), - printable_func_name(ufunc)); - return FAIL; - } - - { - // Check the function was really compiled. - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + ufunc->uf_dfunc_idx; - if (INSTRUCTIONS(dfunc) == NULL) - { - iemsg("using call_def_function() on not compiled function"); - return FAIL; - } - } - - // If depth of calling is getting too high, don't execute the function. - orig_funcdepth = funcdepth_get(); - if (funcdepth_increment() == FAIL) - return FAIL; +#define STACK_TV_VAR(idx) (((typval_T *)ectx->ec_stack.ga_data) + ectx->ec_frame_idx + STACK_FRAME_SIZE + idx) - CLEAR_FIELD(funclocal); - CLEAR_FIELD(ectx); - ectx.ec_dfunc_idx = ufunc->uf_dfunc_idx; - ga_init2(&ectx.ec_stack, sizeof(typval_T), 500); - if (ga_grow(&ectx.ec_stack, 20) == FAIL) - { - funcdepth_decrement(); - return FAIL; - } - ga_init2(&ectx.ec_trystack, sizeof(trycmd_T), 10); - ga_init2(&ectx.ec_funcrefs, sizeof(partial_T *), 10); - - idx = argc - ufunc->uf_args.ga_len; - if (idx > 0 && ufunc->uf_va_name == NULL) - { - if (idx == 1) - emsg(_(e_one_argument_too_many)); - else - semsg(_(e_nr_arguments_too_many), idx); - goto failed_early; - } - - // Put arguments on the stack, but no more than what the function expects. - // A lambda can be called with more arguments than it uses. - for (idx = 0; idx < argc - && (ufunc->uf_va_name != NULL || idx < ufunc->uf_args.ga_len); - ++idx) - { - if (idx >= ufunc->uf_args.ga_len - ufunc->uf_def_args.ga_len - && argv[idx].v_type == VAR_SPECIAL - && argv[idx].vval.v_number == VVAL_NONE) - { - // Use the default value. - STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; - } - else - { - if (ufunc->uf_arg_types != NULL && idx < ufunc->uf_args.ga_len - && check_typval_arg_type( - ufunc->uf_arg_types[idx], &argv[idx], idx + 1) == FAIL) - goto failed_early; - copy_tv(&argv[idx], STACK_TV_BOT(0)); - } - ++ectx.ec_stack.ga_len; - } - - // Turn varargs into a list. Empty list if no args. - if (ufunc->uf_va_name != NULL) - { - int vararg_count = argc - ufunc->uf_args.ga_len; - - if (vararg_count < 0) - vararg_count = 0; - else - argc -= vararg_count; - if (exe_newlist(vararg_count, &ectx) == FAIL) - goto failed_early; - - // Check the type of the list items. - tv = STACK_TV_BOT(-1); - if (ufunc->uf_va_type != NULL - && ufunc->uf_va_type != &t_list_any - && ufunc->uf_va_type->tt_member != &t_any - && tv->vval.v_list != NULL) - { - type_T *expected = ufunc->uf_va_type->tt_member; - listitem_T *li = tv->vval.v_list->lv_first; - - for (idx = 0; idx < vararg_count; ++idx) - { - if (check_typval_arg_type(expected, &li->li_tv, - argc + idx + 1) == FAIL) - goto failed_early; - li = li->li_next; - } - } - - if (defcount > 0) - // Move varargs list to below missing default arguments. - *STACK_TV_BOT(defcount - 1) = *STACK_TV_BOT(-1); - --ectx.ec_stack.ga_len; - } - - // Make space for omitted arguments, will store default value below. - // Any varargs list goes after them. - if (defcount > 0) - for (idx = 0; idx < defcount; ++idx) - { - STACK_TV_BOT(0)->v_type = VAR_UNKNOWN; - ++ectx.ec_stack.ga_len; - } - if (ufunc->uf_va_name != NULL) - ++ectx.ec_stack.ga_len; - - // Frame pointer points to just after arguments. - ectx.ec_frame_idx = ectx.ec_stack.ga_len; - initial_frame_idx = ectx.ec_frame_idx; - - { - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + ufunc->uf_dfunc_idx; - ufunc_T *base_ufunc = dfunc->df_ufunc; - - // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done - // by copy_func(). - if (partial != NULL || base_ufunc->uf_partial != NULL) - { - ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); - if (ectx.ec_outer == NULL) - goto failed_early; - if (partial != NULL) - { - if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) - { - if (current_ectx->ec_outer != NULL) - *ectx.ec_outer = *current_ectx->ec_outer; - } - else - *ectx.ec_outer = partial->pt_outer; - } - else - *ectx.ec_outer = base_ufunc->uf_partial->pt_outer; - ectx.ec_outer->out_up_is_copy = TRUE; - } - } - - // dummy frame entries - for (idx = 0; idx < STACK_FRAME_SIZE; ++idx) - { - STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; - ++ectx.ec_stack.ga_len; - } - - { - // Reserve space for local variables and any closure reference count. - dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) - + ufunc->uf_dfunc_idx; - - for (idx = 0; idx < dfunc->df_varcount; ++idx) - STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; - ectx.ec_stack.ga_len += dfunc->df_varcount; - if (dfunc->df_has_closure) - { - STACK_TV_VAR(idx)->v_type = VAR_NUMBER; - STACK_TV_VAR(idx)->vval.v_number = 0; - ++ectx.ec_stack.ga_len; - } - - ectx.ec_instr = INSTRUCTIONS(dfunc); - } - - // Following errors are in the function, not the caller. - // Commands behave like vim9script. - estack_push_ufunc(ufunc, 1); - current_sctx = ufunc->uf_script_ctx; - current_sctx.sc_version = SCRIPT_VERSION_VIM9; - - // Use a specific location for storing error messages to be converted to an - // exception. - saved_msg_list = msg_list; - msg_list = &private_msg_list; - - // Do turn errors into exceptions. - suppress_errthrow = FALSE; - - // Do not delete the function while executing it. - ++ufunc->uf_calls; - - // When ":silent!" was used before calling then we still abort the - // function. If ":silent!" is used in the function then we don't. - emsg_silent_def = emsg_silent; - did_emsg_def = 0; - - where.wt_index = 0; - where.wt_variable = FALSE; +/* + * Execute instructions in execution context "ectx". + * Return OK or FAIL; + */ + static int +exec_instructions(ectx_T *ectx) +{ + int breakcheck_count = 0; + typval_T *tv; // Start execution at the first instruction. - ectx.ec_iidx = 0; + ectx->ec_iidx = 0; for (;;) { @@ -1521,7 +1301,7 @@ call_def_function( // Turn CTRL-C into an exception. got_int = FALSE; if (throw_exception("Vim:Interrupt", ET_INTERRUPT, NULL) == FAIL) - goto failed; + return FAIL; did_throw = TRUE; } @@ -1530,52 +1310,52 @@ call_def_function( // Turn an error message into an exception. did_emsg = FALSE; if (throw_exception(*msg_list, ET_ERROR, NULL) == FAIL) - goto failed; + return FAIL; did_throw = TRUE; *msg_list = NULL; } - 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 // the current function. if (trystack->ga_len > 0) trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; - if (trycmd != NULL && trycmd->tcd_frame_idx == ectx.ec_frame_idx) + if (trycmd != NULL && trycmd->tcd_frame_idx == ectx->ec_frame_idx) { // jump to ":catch" or ":finally" - ectx.ec_in_catch = TRUE; - ectx.ec_iidx = trycmd->tcd_catch_idx; + ectx->ec_in_catch = TRUE; + ectx->ec_iidx = trycmd->tcd_catch_idx; } else { // Not inside try or need to return from current functions. // Push a dummy return value. - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); tv->v_type = VAR_NUMBER; tv->vval.v_number = 0; - ++ectx.ec_stack.ga_len; - if (ectx.ec_frame_idx == initial_frame_idx) + ++ectx->ec_stack.ga_len; + if (ectx->ec_frame_idx == ectx->ec_initial_frame_idx) { // At the toplevel we are done. need_rethrow = TRUE; - if (handle_closure_in_use(&ectx, FALSE) == FAIL) - goto failed; + if (handle_closure_in_use(ectx, FALSE) == FAIL) + return FAIL; goto done; } - if (func_return(&funclocal, &ectx) == FAIL) - goto failed; + if (func_return(ectx) == FAIL) + return FAIL; } continue; } - iptr = &ectx.ec_instr[ectx.ec_iidx++]; + iptr = &ectx->ec_instr[ectx->ec_iidx++]; switch (iptr->isn_type) { // execute Ex command line @@ -1597,6 +1377,38 @@ call_def_function( } break; + // execute :substitute with an expression + case ISN_SUBSTITUTE: + { + subs_T *subs = &iptr->isn_arg.subs; + source_cookie_T cookie; + struct subs_expr_S *save_instr = substitute_instr; + struct subs_expr_S subs_instr; + int res; + + subs_instr.subs_ectx = ectx; + subs_instr.subs_instr = subs->subs_instr; + subs_instr.subs_status = OK; + substitute_instr = &subs_instr; + + SOURCING_LNUM = iptr->isn_lnum; + // This is very much like ISN_EXEC + CLEAR_FIELD(cookie); + cookie.sourcing_lnum = iptr->isn_lnum - 1; + res = do_cmdline(subs->subs_cmd, + getsourceline, &cookie, + DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED); + substitute_instr = save_instr; + + if (res == FAIL || did_emsg + || subs_instr.subs_status == FAIL) + goto on_error; + } + break; + + case ISN_FINISH: + goto done; + // execute Ex command from pieces on the stack case ISN_EXECCONCAT: { @@ -1626,7 +1438,7 @@ call_def_function( { cmd = alloc(len + 1); if (cmd == NULL) - goto failed; + return FAIL; len = 0; } } @@ -1643,6 +1455,7 @@ call_def_function( int count = iptr->isn_arg.echo.echo_count; int atstart = TRUE; int needclr = TRUE; + int idx; for (idx = 0; idx < count; ++idx) { @@ -1653,7 +1466,7 @@ call_def_function( } if (needclr) msg_clr_eos(); - ectx.ec_stack.ga_len -= count; + ectx->ec_stack.ga_len -= count; } break; @@ -1670,6 +1483,7 @@ call_def_function( char_u *p; int len; int failed = FALSE; + int idx; ga_init2(&ga, 1, 80); for (idx = 0; idx < count; ++idx) @@ -1702,7 +1516,7 @@ call_def_function( } clear_tv(tv); } - ectx.ec_stack.ga_len -= count; + ectx->ec_stack.ga_len -= count; if (failed) { ga_clear(&ga); @@ -1742,18 +1556,18 @@ call_def_function( // load local variable or argument case ISN_LOAD: - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(STACK_TV_VAR(iptr->isn_arg.number), STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; break; // load v: variable case ISN_LOADV: - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(get_vim_var_tv(iptr->isn_arg.number), STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; break; // load s: variable in Vim9 script @@ -1762,14 +1576,14 @@ call_def_function( scriptref_T *sref = iptr->isn_arg.script.scriptref; svar_T *sv; - sv = get_script_svar(sref, &ectx); + sv = get_script_svar(sref, ectx); if (sv == NULL) - goto failed; + return FAIL; allocate_if_null(sv->sv_tv); - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(sv->sv_tv, STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } break; @@ -1789,10 +1603,10 @@ call_def_function( } else { - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(&di->di_tv, STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } } break; @@ -1826,7 +1640,7 @@ call_def_function( namespace = 't'; break; default: // Cannot reach here - goto failed; + return FAIL; } di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE); @@ -1839,10 +1653,10 @@ call_def_function( } else { - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(&di->di_tv, STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } } break; @@ -1852,13 +1666,13 @@ call_def_function( { char_u *name = iptr->isn_arg.string; - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; SOURCING_LNUM = iptr->isn_lnum; if (eval_variable(name, (int)STRLEN(name), STACK_TV_BOT(0), NULL, EVAL_VAR_VERBOSE) == FAIL) goto on_error; - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } break; @@ -1877,16 +1691,16 @@ call_def_function( case ISN_LOADWDICT: d = curwin->w_vars; break; case ISN_LOADTDICT: d = curtab->tp_vars; break; default: // Cannot reach here - goto failed; + return FAIL; } - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); tv->v_type = VAR_DICT; tv->v_lock = 0; tv->vval.v_dict = d; ++d->dv_refcount; - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } break; @@ -1898,12 +1712,12 @@ call_def_function( // This is not expected to fail, name is checked during // compilation: don't set SOURCING_LNUM. - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; if (eval_option(&name, &optval, TRUE) == FAIL) - goto failed; + return FAIL; *STACK_TV_BOT(0) = optval; - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } break; @@ -1913,19 +1727,19 @@ call_def_function( typval_T optval; char_u *name = iptr->isn_arg.string; - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; // name is always valid, checked when compiling (void)eval_env_var(&name, &optval, TRUE); *STACK_TV_BOT(0) = optval; - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } break; // load @register case ISN_LOADREG: - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); tv->v_type = VAR_STRING; tv->v_lock = 0; @@ -1933,12 +1747,12 @@ call_def_function( // empty string. tv->vval.v_string = get_reg_contents( iptr->isn_arg.number, GREG_EXPR_SRC); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; break; // store local variable case ISN_STORE: - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; tv = STACK_TV_VAR(iptr->isn_arg.number); clear_tv(tv); *tv = *STACK_TV_BOT(0); @@ -1952,7 +1766,7 @@ call_def_function( char_u *name = iptr->isn_arg.loadstore.ls_name; dictitem_T *di = find_var_in_ht(ht, 0, name + 2, TRUE); - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; if (di == NULL) store_var(name, STACK_TV_BOT(0)); else @@ -1975,10 +1789,10 @@ call_def_function( scriptref_T *sref = iptr->isn_arg.script.scriptref; svar_T *sv; - sv = get_script_svar(sref, &ectx); + sv = get_script_svar(sref, ectx); if (sv == NULL) - goto failed; - --ectx.ec_stack.ga_len; + return FAIL; + --ectx->ec_stack.ga_len; // "const" and "final" are checked at compile time, locking // the value needs to be checked here. @@ -2001,7 +1815,7 @@ call_def_function( char_u *s = NULL; char *msg; - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; tv = STACK_TV_BOT(0); if (tv->v_type == VAR_STRING) { @@ -2026,7 +1840,7 @@ call_def_function( // store $ENV case ISN_STOREENV: - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; tv = STACK_TV_BOT(0); vim_setenv_ext(iptr->isn_arg.string, tv_get_string(tv)); clear_tv(tv); @@ -2037,7 +1851,7 @@ call_def_function( { int reg = iptr->isn_arg.number; - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; tv = STACK_TV_BOT(0); write_reg_contents(reg == '@' ? '"' : reg, tv_get_string(tv), -1, FALSE); @@ -2047,7 +1861,7 @@ call_def_function( // store v: variable case ISN_STOREV: - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; if (set_vim_var_tv(iptr->isn_arg.number, STACK_TV_BOT(0)) == FAIL) // should not happen, type is checked when compiling @@ -2079,10 +1893,10 @@ call_def_function( ht = &curtab->tp_vars->dv_hashtab; break; default: // Cannot reach here - goto failed; + return FAIL; } - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; di = find_var_in_ht(ht, 0, name, TRUE); if (di == NULL) store_var(iptr->isn_arg.string, STACK_TV_BOT(0)); @@ -2102,7 +1916,7 @@ call_def_function( SOURCING_LNUM = iptr->isn_lnum; set_var(iptr->isn_arg.string, STACK_TV_BOT(-1), TRUE); clear_tv(STACK_TV_BOT(-1)); - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; break; // store number in local variable @@ -2184,7 +1998,7 @@ call_def_function( goto on_error; // append to list, only fails when out of memory if (list_append_tv(list, tv) == FAIL) - goto failed; + return FAIL; clear_tv(tv); } } @@ -2219,7 +2033,7 @@ call_def_function( goto on_error; // add to dict, only fails when out of memory if (dict_add_tv(dict, (char *)key, tv) == FAIL) - goto failed; + return FAIL; clear_tv(tv); } } @@ -2263,7 +2077,7 @@ call_def_function( clear_tv(tv_idx); clear_tv(tv_dest); - ectx.ec_stack.ga_len -= 3; + ectx->ec_stack.ga_len -= 3; if (status == FAIL) { clear_tv(tv); @@ -2328,7 +2142,7 @@ call_def_function( clear_tv(tv_idx1); clear_tv(tv_idx2); clear_tv(tv_dest); - ectx.ec_stack.ga_len -= 4; + ectx->ec_stack.ga_len -= 4; clear_tv(tv); if (status == FAIL) @@ -2341,7 +2155,7 @@ call_def_function( case ISN_STOREOUTER: { int depth = iptr->isn_arg.outer.outer_depth; - outer_T *outer = ectx.ec_outer; + outer_T *outer = ectx->ec_outer; while (depth > 1 && outer != NULL) { @@ -2352,21 +2166,21 @@ call_def_function( { SOURCING_LNUM = iptr->isn_lnum; iemsg("LOADOUTER depth more than scope levels"); - goto failed; + return FAIL; } tv = ((typval_T *)outer->out_stack->ga_data) + outer->out_frame_idx + STACK_FRAME_SIZE + iptr->isn_arg.outer.outer_idx; if (iptr->isn_type == ISN_LOADOUTER) { - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; copy_tv(tv, STACK_TV_BOT(0)); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; } else { - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; clear_tv(tv); *tv = *STACK_TV_BOT(0); } @@ -2453,7 +2267,7 @@ call_def_function( clear_tv(tv_idx); clear_tv(tv_dest); - ectx.ec_stack.ga_len -= 2; + ectx->ec_stack.ga_len -= 2; if (status == FAIL) goto on_error; } @@ -2505,7 +2319,7 @@ call_def_function( clear_tv(tv_idx1); clear_tv(tv_idx2); clear_tv(tv_dest); - ectx.ec_stack.ga_len -= 3; + ectx->ec_stack.ga_len -= 3; if (status == FAIL) goto on_error; } @@ -2521,11 +2335,11 @@ call_def_function( case ISN_PUSHFUNC: case ISN_PUSHCHANNEL: case ISN_PUSHJOB: - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); tv->v_lock = 0; - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; switch (iptr->isn_type) { case ISN_PUSHNR: @@ -2597,8 +2411,8 @@ call_def_function( // create a list from items on the stack; uses a single allocation // for the list header and the items case ISN_NEWLIST: - if (exe_newlist(iptr->isn_arg.number, &ectx) == FAIL) - goto failed; + if (exe_newlist(iptr->isn_arg.number, ectx) == FAIL) + return FAIL; break; // create a dict from items on the stack @@ -2608,9 +2422,10 @@ call_def_function( dict_T *dict = dict_alloc(); dictitem_T *item; char_u *key; + int idx; if (dict == NULL) - goto failed; + return FAIL; for (idx = 0; idx < count; ++idx) { // have already checked key type is VAR_STRING @@ -2631,7 +2446,7 @@ call_def_function( if (item == NULL) { dict_unref(dict); - goto failed; + return FAIL; } item->di_tv = *STACK_TV_BOT(2 * (idx - count) + 1); item->di_tv.v_lock = 0; @@ -2639,16 +2454,16 @@ call_def_function( { // can this ever happen? dict_unref(dict); - goto failed; + return FAIL; } } if (count > 0) - ectx.ec_stack.ga_len -= 2 * count - 1; - else if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + ectx->ec_stack.ga_len -= 2 * count - 1; + else if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; else - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; tv = STACK_TV_BOT(-1); tv->v_type = VAR_DICT; tv->v_lock = 0; @@ -2663,8 +2478,7 @@ call_def_function( if (call_dfunc(iptr->isn_arg.dfunc.cdf_idx, NULL, iptr->isn_arg.dfunc.cdf_argcount, - &funclocal, - &ectx) == FAIL) + ectx) == FAIL) goto on_error; break; @@ -2673,7 +2487,7 @@ call_def_function( SOURCING_LNUM = iptr->isn_lnum; if (call_bfunc(iptr->isn_arg.bfunc.cbf_idx, iptr->isn_arg.bfunc.cbf_argcount, - &ectx) == FAIL) + ectx) == FAIL) goto on_error; break; @@ -2693,12 +2507,11 @@ call_def_function( else { // Get the funcref from the stack. - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; partial_tv = *STACK_TV_BOT(0); tv = &partial_tv; } - r = call_partial(tv, pfunc->cpf_argcount, - &funclocal, &ectx); + r = call_partial(tv, pfunc->cpf_argcount, ectx); if (tv == &partial_tv) clear_tv(&partial_tv); if (r == FAIL) @@ -2710,7 +2523,7 @@ call_def_function( // PCALL finished, arguments have been consumed and replaced by // the return value. Now clear the funcref from the stack, // and move the return value in its place. - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; clear_tv(STACK_TV_BOT(-1)); *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); break; @@ -2722,17 +2535,17 @@ call_def_function( SOURCING_LNUM = iptr->isn_lnum; if (call_eval_func(cufunc->cuf_name, cufunc->cuf_argcount, - &funclocal, &ectx, iptr) == FAIL) + ectx, iptr) == FAIL) goto on_error; } break; // return from a :def function call case ISN_RETURN_ZERO: - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) - goto failed; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; tv->v_type = VAR_NUMBER; tv->vval.v_number = 0; tv->v_lock = 0; @@ -2740,20 +2553,20 @@ call_def_function( case ISN_RETURN: { - garray_T *trystack = &ectx.ec_trystack; + garray_T *trystack = &ectx->ec_trystack; trycmd_T *trycmd = NULL; if (trystack->ga_len > 0) trycmd = ((trycmd_T *)trystack->ga_data) + trystack->ga_len - 1; if (trycmd != NULL - && trycmd->tcd_frame_idx == ectx.ec_frame_idx) + && trycmd->tcd_frame_idx == ectx->ec_frame_idx) { // jump to ":finally" or ":endtry" if (trycmd->tcd_finally_idx != 0) - ectx.ec_iidx = trycmd->tcd_finally_idx; + ectx->ec_iidx = trycmd->tcd_finally_idx; else - ectx.ec_iidx = trycmd->tcd_endtry_idx; + ectx->ec_iidx = trycmd->tcd_endtry_idx; trycmd->tcd_return = TRUE; } else @@ -2769,18 +2582,18 @@ call_def_function( + iptr->isn_arg.funcref.fr_func; if (pt == NULL) - goto failed; - if (GA_GROW(&ectx.ec_stack, 1) == FAIL) + return FAIL; + if (GA_GROW(&ectx->ec_stack, 1) == FAIL) { vim_free(pt); - goto failed; + return FAIL; } if (fill_partial_and_closure(pt, pt_dfunc->df_ufunc, - &ectx) == FAIL) - goto failed; + ectx) == FAIL) + return FAIL; tv = STACK_TV_BOT(0); - ++ectx.ec_stack.ga_len; + ++ectx->ec_stack.ga_len; tv->vval.v_partial = pt; tv->v_type = VAR_PARTIAL; tv->v_lock = 0; @@ -2793,8 +2606,8 @@ call_def_function( newfunc_T *newfunc = &iptr->isn_arg.newfunc; if (copy_func(newfunc->nf_lambda, newfunc->nf_global, - &ectx) == FAIL) - goto failed; + ectx) == FAIL) + return FAIL; } break; @@ -2841,11 +2654,11 @@ call_def_function( { // drop the value from the stack clear_tv(tv); - --ectx.ec_stack.ga_len; + --ectx->ec_stack.ga_len; } } if (jump) - ectx.ec_iidx = iptr->isn_arg.jump.jump_where; |