# HG changeset patch # User Bram Moolenaar # Date 1577657704 -3600 # Node ID 847cc7932c42892f81b5974ee37a43d30f3e2c19 # Parent 1219ae40b086704b4cefd7a9d034ea4729d279dd patch 8.2.0056: execution stack is incomplete and inefficient Commit: https://github.com/vim/vim/commit/1a47ae32cdc19b0fd5a82e19fe5fddf45db1a506 Author: Bram Moolenaar Date: Sun Dec 29 23:04:25 2019 +0100 patch 8.2.0056: execution stack is incomplete and inefficient Problem: Execution stack is incomplete and inefficient. Solution: Introduce a proper execution stack and use it instead of sourcing_name/sourcing_lnum. Create a string only when used. diff --git a/src/autocmd.c b/src/autocmd.c --- a/src/autocmd.c +++ b/src/autocmd.c @@ -218,7 +218,7 @@ static AutoPat *last_autopat[NUM_EVENTS] /* * struct used to keep status while executing autocommands for an event. */ -typedef struct AutoPatCmd +struct AutoPatCmd_S { AutoPat *curpat; // next AutoPat to examine AutoCmd *nextcmd; // next AutoCmd to execute @@ -229,8 +229,8 @@ typedef struct AutoPatCmd event_T event; // current event int arg_bufnr; // Initially equal to , set to zero when // buf is deleted. - struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation -} AutoPatCmd; + AutoPatCmd *next; // chain of active apc-s for auto-invalidation +}; static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands @@ -1242,7 +1242,7 @@ do_autocmd_event( ac->cmd = vim_strsave(cmd); #ifdef FEAT_EVAL ac->script_ctx = current_sctx; - ac->script_ctx.sc_lnum += sourcing_lnum; + ac->script_ctx.sc_lnum += SOURCING_LNUM; #endif if (ac->cmd == NULL) { @@ -1805,8 +1805,6 @@ apply_autocmds_group( int save_changed; buf_T *old_curbuf; int retval = FALSE; - char_u *save_sourcing_name; - linenr_T save_sourcing_lnum; char_u *save_autocmd_fname; int save_autocmd_fname_full; int save_autocmd_bufnr; @@ -2020,10 +2018,9 @@ apply_autocmds_group( // Don't redraw while doing autocommands. ++RedrawingDisabled; - save_sourcing_name = sourcing_name; - sourcing_name = NULL; // don't free this one - save_sourcing_lnum = sourcing_lnum; - sourcing_lnum = 0; // no line number here + + // name and lnum are filled in later + estack_push(ETYPE_AUCMD, NULL, 0); #ifdef FEAT_EVAL save_current_sctx = current_sctx; @@ -2126,9 +2123,8 @@ apply_autocmds_group( autocmd_busy = save_autocmd_busy; filechangeshell_busy = FALSE; autocmd_nested = save_autocmd_nested; - vim_free(sourcing_name); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; + vim_free(SOURCING_NAME); + estack_pop(); vim_free(autocmd_fname); autocmd_fname = save_autocmd_fname; autocmd_fname_full = save_autocmd_fname_full; @@ -2256,8 +2252,9 @@ auto_next_pat( AutoCmd *cp; char_u *name; char *s; + char_u **sourcing_namep = &SOURCING_NAME; - VIM_CLEAR(sourcing_name); + VIM_CLEAR(*sourcing_namep); for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) { @@ -2277,16 +2274,16 @@ auto_next_pat( { name = event_nr2name(apc->event); s = _("%s Autocommands for \"%s\""); - sourcing_name = alloc(STRLEN(s) + *sourcing_namep = alloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1); - if (sourcing_name != NULL) + if (*sourcing_namep != NULL) { - sprintf((char *)sourcing_name, s, + sprintf((char *)*sourcing_namep, s, (char *)name, (char *)ap->pat); if (p_verbose >= 8) { verbose_enter(); - smsg(_("Executing %s"), sourcing_name); + smsg(_("Executing %s"), *sourcing_namep); verbose_leave(); } } diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -5279,8 +5279,6 @@ chk_modeline( int vers; int end; int retval = OK; - char_u *save_sourcing_name; - linenr_T save_sourcing_lnum; #ifdef FEAT_EVAL sctx_T save_current_sctx; #endif @@ -5325,10 +5323,8 @@ chk_modeline( if (linecopy == NULL) return FAIL; - save_sourcing_lnum = sourcing_lnum; - save_sourcing_name = sourcing_name; - sourcing_lnum = lnum; // prepare for emsg() - sourcing_name = (char_u *)"modelines"; + // prepare for emsg() + estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum); end = FALSE; while (end == FALSE) @@ -5371,7 +5367,7 @@ chk_modeline( save_current_sctx = current_sctx; current_sctx.sc_sid = SID_MODELINE; current_sctx.sc_seq = 0; - current_sctx.sc_lnum = 0; + current_sctx.sc_lnum = lnum; current_sctx.sc_version = 1; #endif // Make sure no risky things are executed as a side effect. @@ -5389,9 +5385,7 @@ chk_modeline( s = e + 1; // advance to next part } - sourcing_lnum = save_sourcing_lnum; - sourcing_name = save_sourcing_name; - + estack_pop(); vim_free(linecopy); } return retval; diff --git a/src/debugger.c b/src/debugger.c --- a/src/debugger.c +++ b/src/debugger.c @@ -51,6 +51,7 @@ do_debug(char_u *cmd) int n; char_u *cmdline = NULL; char_u *p; + char_u *sname; char *tail = NULL; static int last_cmd = 0; #define CMD_CONT 1 @@ -104,10 +105,12 @@ do_debug(char_u *cmd) vim_free(debug_newval); debug_newval = NULL; } - if (sourcing_name != NULL) - msg((char *)sourcing_name); - if (sourcing_lnum != 0) - smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd); + sname = estack_sfile(); + if (sname != NULL) + msg((char *)sname); + vim_free(sname); + if (SOURCING_LNUM != 0) + smsg(_("line %ld: %s"), SOURCING_LNUM, cmd); else smsg(_("cmd: %s"), cmd); @@ -300,14 +303,14 @@ do_debug(char_u *cmd) } static int -get_maxbacktrace_level(void) +get_maxbacktrace_level(char_u *sname) { char *p, *q; int maxbacktrace = 0; - if (sourcing_name != NULL) + if (sname != NULL) { - p = (char *)sourcing_name; + p = (char *)sname; while ((q = strstr(p, "..")) != NULL) { p = q + 2; @@ -341,27 +344,32 @@ do_checkbacktracelevel(void) } else { - int max = get_maxbacktrace_level(); + char_u *sname = estack_sfile(); + int max = get_maxbacktrace_level(sname); if (debug_backtrace_level > max) { debug_backtrace_level = max; smsg(_("frame at highest level: %d"), max); } + vim_free(sname); } } static void do_showbacktrace(char_u *cmd) { + char_u *sname; char *cur; char *next; int i = 0; - int max = get_maxbacktrace_level(); + int max; - if (sourcing_name != NULL) + sname = estack_sfile(); + max = get_maxbacktrace_level(sname); + if (sname != NULL) { - cur = (char *)sourcing_name; + cur = (char *)sname; while (!got_int) { next = strstr(cur, ".."); @@ -377,9 +385,11 @@ do_showbacktrace(char_u *cmd) *next = '.'; cur = next + 2; } + vim_free(sname); } - if (sourcing_lnum != 0) - smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd); + + if (SOURCING_LNUM != 0) + smsg(_("line %ld: %s"), (long)SOURCING_LNUM, cmd); else smsg(_("cmd: %s"), cmd); } diff --git a/src/ex_docmd.c b/src/ex_docmd.c --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -703,7 +703,7 @@ do_cmdline( } else if (getline_equal(fgetline, cookie, getsourceline)) { - fname = sourcing_name; + fname = SOURCING_NAME; breakpoint = source_breakpoint(real_cookie); dbg_tick = source_dbg_tick(real_cookie); } @@ -819,22 +819,22 @@ do_cmdline( { *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), - fname, sourcing_lnum); + fname, SOURCING_LNUM); *dbg_tick = debug_tick; } next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line; - sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum; + SOURCING_LNUM = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum; // Did we encounter a breakpoint? if (breakpoint != NULL && *breakpoint != 0 - && *breakpoint <= sourcing_lnum) + && *breakpoint <= SOURCING_LNUM) { - dbg_breakpoint(fname, sourcing_lnum); + dbg_breakpoint(fname, SOURCING_LNUM); // Find next breakpoint. *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), - fname, sourcing_lnum); + fname, SOURCING_LNUM); *dbg_tick = debug_tick; } # ifdef FEAT_PROFILE @@ -963,8 +963,8 @@ do_cmdline( } } - if (p_verbose >= 15 && sourcing_name != NULL) - msg_verbose_cmd(sourcing_lnum, cmdline_copy); + if (p_verbose >= 15 && SOURCING_NAME != NULL) + msg_verbose_cmd(SOURCING_LNUM, cmdline_copy); /* * 2. Execute one '|' separated command. @@ -1081,7 +1081,7 @@ do_cmdline( // Check for the next breakpoint after a watchexpression if (breakpoint != NULL && has_watchexpr()) { - *breakpoint = dbg_find_breakpoint(FALSE, fname, sourcing_lnum); + *breakpoint = dbg_find_breakpoint(FALSE, fname, SOURCING_LNUM); *dbg_tick = debug_tick; } @@ -1092,7 +1092,7 @@ do_cmdline( { if (lines_ga.ga_len > 0) { - sourcing_lnum = + SOURCING_LNUM = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; free_cmdlines(&lines_ga); } @@ -1234,8 +1234,6 @@ do_cmdline( if (did_throw) { void *p = NULL; - char_u *saved_sourcing_name; - int saved_sourcing_lnum; struct msglist *messages = NULL, *next; /* @@ -1260,10 +1258,8 @@ do_cmdline( break; } - saved_sourcing_name = sourcing_name; - saved_sourcing_lnum = sourcing_lnum; - sourcing_name = current_exception->throw_name; - sourcing_lnum = current_exception->throw_lnum; + estack_push(ETYPE_EXCEPT, current_exception->throw_name, + current_exception->throw_lnum); current_exception->throw_name = NULL; discard_current_exception(); // uses IObuff if 'verbose' @@ -1287,9 +1283,8 @@ do_cmdline( emsg(p); vim_free(p); } - vim_free(sourcing_name); - sourcing_name = saved_sourcing_name; - sourcing_lnum = saved_sourcing_lnum; + vim_free(SOURCING_NAME); + estack_pop(); } /* @@ -1428,7 +1423,7 @@ get_loop_line(int c, void *cookie, int i KeyTyped = FALSE; ++cp->current_line; wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line; - sourcing_lnum = wp->lnum; + SOURCING_LNUM = wp->lnum; return vim_strsave(wp->line); } @@ -1441,7 +1436,7 @@ store_loop_line(garray_T *gap, char_u *l if (ga_grow(gap, 1) == FAIL) return FAIL; ((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line); - ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum; + ((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = SOURCING_LNUM; ++gap->ga_len; return OK; } @@ -8171,33 +8166,34 @@ eval_vars( break; case SPEC_SFILE: // file name for ":so" command - result = sourcing_name; + result = estack_sfile(); if (result == NULL) { *errormsg = _("E498: no :source file name to substitute for \"\""); return NULL; } + resultbuf = result; // remember allocated string break; case SPEC_SLNUM: // line in file for ":so" command - if (sourcing_name == NULL || sourcing_lnum == 0) + if (SOURCING_NAME == NULL || SOURCING_LNUM == 0) { *errormsg = _("E842: no line number to use for \"\""); return NULL; } - sprintf((char *)strbuf, "%ld", (long)sourcing_lnum); + sprintf((char *)strbuf, "%ld", SOURCING_LNUM); result = strbuf; break; #ifdef FEAT_EVAL case SPEC_SFLNUM: // line in script file - if (current_sctx.sc_lnum + sourcing_lnum == 0) + if (current_sctx.sc_lnum + SOURCING_LNUM == 0) { *errormsg = _("E961: no line number to use for \"\""); return NULL; } sprintf((char *)strbuf, "%ld", - (long)(current_sctx.sc_lnum + sourcing_lnum)); + (long)(current_sctx.sc_lnum + SOURCING_LNUM)); result = strbuf; break; #endif diff --git a/src/ex_eval.c b/src/ex_eval.c --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -534,15 +534,16 @@ throw_exception(void *value, except_type goto nomem; excp->type = type; - excp->throw_name = vim_strsave(sourcing_name == NULL - ? (char_u *)"" : sourcing_name); + excp->throw_name = estack_sfile(); + if (excp->throw_name == NULL) + excp->throw_name = vim_strsave((char_u *)""); if (excp->throw_name == NULL) { if (should_free) vim_free(excp->value); goto nomem; } - excp->throw_lnum = sourcing_lnum; + excp->throw_lnum = SOURCING_LNUM; if (p_verbose >= 13 || debug_break_level > 0) { diff --git a/src/globals.h b/src/globals.h --- a/src/globals.h +++ b/src/globals.h @@ -266,8 +266,15 @@ EXTERN int lines_left INIT(= -1); // EXTERN int msg_no_more INIT(= FALSE); // don't use more prompt, truncate // messages -EXTERN char_u *sourcing_name INIT( = NULL);// name of error message source -EXTERN linenr_T sourcing_lnum INIT(= 0); // line number of the source file +/* + * Stack of execution contexts. Each entry is an estack_T. + * Current context is at ga_len - 1. + */ +EXTERN garray_T exestack INIT(= {0 COMMA 0 COMMA sizeof(estack_T) COMMA 50 COMMA NULL}); +// name of error message source +#define SOURCING_NAME (((estack_T *)exestack.ga_data)[exestack.ga_len - 1].es_name) +// line number in the message source or zero +#define SOURCING_LNUM (((estack_T *)exestack.ga_data)[exestack.ga_len - 1].es_lnum) #ifdef FEAT_EVAL EXTERN int ex_nesting_level INIT(= 0); // nesting level diff --git a/src/highlight.c b/src/highlight.c --- a/src/highlight.c +++ b/src/highlight.c @@ -748,7 +748,7 @@ do_highlight( if (to_id > 0 && !forceit && !init && hl_has_settings(from_id - 1, dodefault)) { - if (sourcing_name == NULL && !dodefault) + if (SOURCING_NAME == NULL && !dodefault) emsg(_("E414: group has settings, highlight link ignored")); } else if (HL_TABLE()[from_id - 1].sg_link != to_id @@ -763,7 +763,7 @@ do_highlight( HL_TABLE()[from_id - 1].sg_link = to_id; #ifdef FEAT_EVAL HL_TABLE()[from_id - 1].sg_script_ctx = current_sctx; - HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += sourcing_lnum; + HL_TABLE()[from_id - 1].sg_script_ctx.sc_lnum += SOURCING_LNUM; #endif HL_TABLE()[from_id - 1].sg_cleared = FALSE; redraw_all_later(SOME_VALID); @@ -1518,7 +1518,7 @@ do_highlight( set_hl_attr(idx); #ifdef FEAT_EVAL HL_TABLE()[idx].sg_script_ctx = current_sctx; - HL_TABLE()[idx].sg_script_ctx.sc_lnum += sourcing_lnum; + HL_TABLE()[idx].sg_script_ctx.sc_lnum += SOURCING_LNUM; #endif } diff --git a/src/kword_test.c b/src/kword_test.c --- a/src/kword_test.c +++ b/src/kword_test.c @@ -76,6 +76,7 @@ test_isword_funcs_utf8(void) int main(void) { + estack_init(); test_isword_funcs_utf8(); return 0; } diff --git a/src/main.c b/src/main.c --- a/src/main.c +++ b/src/main.c @@ -911,6 +911,7 @@ vim_main2(void) void common_init(mparm_T *paramp) { + estack_init(); cmdline_init(); (void)mb_init(); // init mb_bytelen_tab[] to ones @@ -3089,13 +3090,13 @@ exe_pre_commands(mparm_T *parmp) if (cnt > 0) { curwin->w_cursor.lnum = 0; // just in case.. - sourcing_name = (char_u *)_("pre-vimrc command line"); + estack_push(ETYPE_ARGS, (char_u *)_("pre-vimrc command line"), 0); # ifdef FEAT_EVAL current_sctx.sc_sid = SID_CMDARG; # endif for (i = 0; i < cnt; ++i) do_cmdline_cmd(cmds[i]); - sourcing_name = NULL; + estack_pop(); # ifdef FEAT_EVAL current_sctx.sc_sid = 0; # endif @@ -3119,7 +3120,7 @@ exe_commands(mparm_T *parmp) msg_scroll = TRUE; if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) curwin->w_cursor.lnum = 0; - sourcing_name = (char_u *)"command line"; + estack_push(ETYPE_ARGS, (char_u *)"command line", 0); #ifdef FEAT_EVAL current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; @@ -3130,7 +3131,7 @@ exe_commands(mparm_T *parmp) if (parmp->cmds_tofree[i]) vim_free(parmp->commands[i]); } - sourcing_name = NULL; + estack_pop(); #ifdef FEAT_EVAL current_sctx.sc_sid = 0; #endif @@ -3336,8 +3337,6 @@ process_env( int is_viminit) // when TRUE, called for VIMINIT { char_u *initstr; - char_u *save_sourcing_name; - linenr_T save_sourcing_lnum; #ifdef FEAT_EVAL sctx_T save_current_sctx; #endif @@ -3346,10 +3345,7 @@ process_env( { if (is_viminit) vimrc_found(NULL, NULL); - save_sourcing_name = sourcing_name; - save_sourcing_lnum = sourcing_lnum; - sourcing_name = env; - sourcing_lnum = 0; + estack_push(ETYPE_ENV, env, 0); #ifdef FEAT_EVAL save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; @@ -3358,8 +3354,8 @@ process_env( current_sctx.sc_version = 1; #endif do_cmdline_cmd(initstr); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; + + estack_pop(); #ifdef FEAT_EVAL current_sctx = save_current_sctx; #endif diff --git a/src/map.c b/src/map.c --- a/src/map.c +++ b/src/map.c @@ -697,7 +697,7 @@ do_map( #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; - mp->m_script_ctx.sc_lnum += sourcing_lnum; + mp->m_script_ctx.sc_lnum += SOURCING_LNUM; #endif did_it = TRUE; } @@ -796,7 +796,7 @@ do_map( #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; - mp->m_script_ctx.sc_lnum += sourcing_lnum; + mp->m_script_ctx.sc_lnum += SOURCING_LNUM; #endif // add the new entry in front of the abbrlist or maphash[] list @@ -1915,14 +1915,13 @@ check_map_keycodes(void) char_u *p; int i; char_u buf[3]; - char_u *save_name; int abbr; int hash; buf_T *bp; validate_maphash(); - save_name = sourcing_name; - sourcing_name = (char_u *)"mappings"; // avoids giving error messages + // avoids giving error messages + estack_push(ETYPE_INTERNAL, (char_u *)"mappings", 0); // Do this once for each buffer, and then once for global // mappings/abbreviations with bp == NULL @@ -1979,7 +1978,7 @@ check_map_keycodes(void) if (bp == NULL) break; } - sourcing_name = save_name; + estack_pop(); } #if defined(FEAT_EVAL) || defined(PROTO) diff --git a/src/message.c b/src/message.c --- a/src/message.c +++ b/src/message.c @@ -434,15 +434,15 @@ reset_last_sourcing(void) } /* - * Return TRUE if "sourcing_name" differs from "last_sourcing_name". + * Return TRUE if "SOURCING_NAME" differs from "last_sourcing_name". */ static int other_sourcing_name(void) { - if (sourcing_name != NULL) + if (SOURCING_NAME != NULL) { if (last_sourcing_name != NULL) - return STRCMP(sourcing_name, last_sourcing_name) != 0; + return STRCMP(SOURCING_NAME, last_sourcing_name) != 0; return TRUE; } return FALSE; @@ -458,12 +458,19 @@ get_emsg_source(void) { char_u *Buf, *p; - if (sourcing_name != NULL && other_sourcing_name()) + if (SOURCING_NAME != NULL && other_sourcing_name()) { + char_u *sname = estack_sfile(); + char_u *tofree = sname; + + if (sname == NULL) + sname = SOURCING_NAME; + p = (char_u *)_("Error detected while processing %s:"); - Buf = alloc(STRLEN(sourcing_name) + STRLEN(p)); + Buf = alloc(STRLEN(sname) + STRLEN(p)); if (Buf != NULL) - sprintf((char *)Buf, (char *)p, sourcing_name); + sprintf((char *)Buf, (char *)p, sname); + vim_free(tofree); return Buf; } return NULL; @@ -481,14 +488,14 @@ get_emsg_lnum(void) // lnum is 0 when executing a command from the command line // argument, we don't want a line number then - if (sourcing_name != NULL - && (other_sourcing_name() || sourcing_lnum != last_sourcing_lnum) - && sourcing_lnum != 0) + if (SOURCING_NAME != NULL + && (other_sourcing_name() || SOURCING_LNUM != last_sourcing_lnum) + && SOURCING_LNUM != 0) { p = (char_u *)_("line %4ld:"); Buf = alloc(STRLEN(p) + 20); if (Buf != NULL) - sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); + sprintf((char *)Buf, (char *)p, (long)SOURCING_LNUM); return Buf; } return NULL; @@ -516,17 +523,17 @@ msg_source(int attr) { msg_attr((char *)p, HL_ATTR(HLF_N)); vim_free(p); - last_sourcing_lnum = sourcing_lnum; // only once for each line + last_sourcing_lnum = SOURCING_LNUM; // only once for each line } // remember the last sourcing name printed, also when it's empty - if (sourcing_name == NULL || other_sourcing_name()) + if (SOURCING_NAME == NULL || other_sourcing_name()) { vim_free(last_sourcing_name); - if (sourcing_name == NULL) + if (SOURCING_NAME == NULL) last_sourcing_name = NULL; else - last_sourcing_name = vim_strsave(sourcing_name); + last_sourcing_name = vim_strsave(SOURCING_NAME); } --no_wait_return; } @@ -2312,7 +2319,7 @@ inc_msg_scrolled(void) #ifdef FEAT_EVAL if (*get_vim_var_str(VV_SCROLLSTART) == NUL) { - char_u *p = sourcing_name; + char_u *p = SOURCING_NAME; char_u *tofree = NULL; int len; @@ -2327,7 +2334,7 @@ inc_msg_scrolled(void) if (tofree != NULL) { vim_snprintf((char *)tofree, len, _("%s line %ld"), - p, (long)sourcing_lnum); + p, (long)SOURCING_LNUM); p = tofree; } } diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -2435,7 +2435,7 @@ set_option_sctx_idx(int opt_idx, int opt int indir = (int)options[opt_idx].indir; sctx_T new_script_ctx = script_ctx; - new_script_ctx.sc_lnum += sourcing_lnum; + new_script_ctx.sc_lnum += SOURCING_LNUM; // Remember where the option was set. For local options need to do that // in the buffer or window structure. diff --git a/src/profiler.c b/src/profiler.c --- a/src/profiler.c +++ b/src/profiler.c @@ -602,10 +602,10 @@ func_line_start(void *cookie) funccall_T *fcp = (funccall_T *)cookie; ufunc_T *fp = fcp->func; - if (fp->uf_profiling && sourcing_lnum >= 1 - && sourcing_lnum <= fp->uf_lines.ga_len) + if (fp->uf_profiling && SOURCING_LNUM >= 1 + && SOURCING_LNUM <= fp->uf_lines.ga_len) { - fp->uf_tml_idx = sourcing_lnum - 1; + fp->uf_tml_idx = SOURCING_LNUM - 1; // Skip continuation lines. while (fp->uf_tml_idx > 0 && FUNCLINE(fp, fp->uf_tml_idx) == NULL) --fp->uf_tml_idx; @@ -906,13 +906,13 @@ script_line_start(void) if (current_sctx.sc_sid <= 0 || current_sctx.sc_sid > script_items.ga_len) return; si = &SCRIPT_ITEM(current_sctx.sc_sid); - if (si->sn_prof_on && sourcing_lnum >= 1) + if (si->sn_prof_on && SOURCING_LNUM >= 1) { // Grow the array before starting the timer, so that the time spent // here isn't counted. (void)ga_grow(&si->sn_prl_ga, - (int)(sourcing_lnum - si->sn_prl_ga.ga_len)); - si->sn_prl_idx = sourcing_lnum - 1; + (int)(SOURCING_LNUM - si->sn_prl_ga.ga_len)); + si->sn_prl_idx = SOURCING_LNUM - 1; while (si->sn_prl_ga.ga_len <= si->sn_prl_idx && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) { diff --git a/src/proto/scriptfile.pro b/src/proto/scriptfile.pro --- a/src/proto/scriptfile.pro +++ b/src/proto/scriptfile.pro @@ -1,4 +1,9 @@ /* scriptfile.c */ +void estack_init(void); +estack_T *estack_push(etype_T type, char_u *name, long lnum); +void estack_push_ufunc(etype_T type, ufunc_T *ufunc, long lnum); +void estack_pop(void); +char_u *estack_sfile(void); void ex_runtime(exarg_T *eap); int do_in_path(char_u *path, char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); int do_in_runtimepath(char_u *name, int flags, void (*callback)(char_u *fname, void *ck), void *cookie); diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -19,6 +19,122 @@ static garray_T ga_loaded = {0, 0, size #endif /* + * Initialize the execution stack. + */ + void +estack_init(void) +{ + estack_T *entry; + + if (ga_grow(&exestack, 10) == FAIL) + mch_exit(0); + entry = ((estack_T *)exestack.ga_data) + exestack.ga_len; + entry->es_type = ETYPE_TOP; + entry->es_name = NULL; + entry->es_lnum = 0; + entry->es_info.ufunc = NULL; + ++exestack.ga_len; +} + +/* + * Add an item to the execution stack. + * Returns the new entry or NULL when out of memory. + */ + estack_T * +estack_push(etype_T type, char_u *name, long lnum) +{ + estack_T *entry; + + // If memory allocation fails then we'll pop more than we push, eventually + // at the top level it will be OK again. + if (ga_grow(&exestack, 1) == OK) + { + entry = ((estack_T *)exestack.ga_data) + exestack.ga_len; + entry->es_type = type; + entry->es_name = name; + entry->es_lnum = lnum; + entry->es_info.ufunc = NULL; + ++exestack.ga_len; + return entry; + } + return NULL; +} + +/* + * Add a user function to the execution stack. + */ + void +estack_push_ufunc(etype_T type, ufunc_T *ufunc, long lnum) +{ + estack_T *entry = estack_push(type, + ufunc->uf_name_exp != NULL + ? ufunc->uf_name_exp : ufunc->uf_name, lnum); + if (entry != NULL) + entry->es_info.ufunc = ufunc; +} + +/* + * Take an item off of the execution stack. + */ + void +estack_pop(void) +{ + if (exestack.ga_len > 1) + --exestack.ga_len; +} + +/* + * Get the current value for in allocated memory. + */ + char_u * +estack_sfile(void) +{ + int len; + int idx; + estack_T *entry; + char *res; + int done; + + entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1; + if (entry->es_name == NULL) + return NULL; + if (entry->es_info.ufunc == NULL) + return vim_strsave(entry->es_name); + + // For a function we compose the call stack, as it was done in the past: + // "function One[123]..Two[456]..Three" + len = STRLEN(entry->es_name) + 10; + for (idx = exestack.ga_len - 2; idx >= 0; --idx) + { + entry = ((estack_T *)exestack.ga_data) + idx; + if (entry->es_name == NULL || entry->es_info.ufunc == NULL) + { + ++idx; + break; + } + len += STRLEN(entry->es_name) + 15; + } + + res = (char *)alloc(len); + if (res != NULL) + { + STRCPY(res, "function "); + while (idx < exestack.ga_len - 1) + { + done = STRLEN(res); + entry = ((estack_T *)exestack.ga_data) + idx; + vim_snprintf(res + done, len - done, "%s[%ld]..", + entry->es_name, entry->es_lnum); + ++idx; + } + done = STRLEN(res); + entry = ((estack_T *)exestack.ga_data) + idx; + vim_snprintf(res + done, len - done, "%s", entry->es_name); + } + return (char_u *)res; +} + +/* * ":runtime [what] {name}" */ void @@ -947,8 +1063,6 @@ do_source( int is_vimrc) // DOSO_ value { struct source_cookie cookie; - char_u *save_sourcing_name; - linenr_T save_sourcing_lnum; char_u *p; char_u *fname_exp; char_u *firstline = NULL; @@ -1039,11 +1153,11 @@ do_source( if (p_verbose > 0) { verbose_enter(); - if (sourcing_name == NULL) + if (SOURCING_NAME == NULL) smsg(_("could not source \"%s\""), fname); else smsg(_("line %ld: could not source \"%s\""), - sourcing_lnum, fname); + SOURCING_LNUM, fname); verbose_leave(); } goto theend; @@ -1055,11 +1169,10 @@ do_source( if (p_verbose > 1) { verbose_enter(); - if (sourcing_name == NULL) + if (SOURCING_NAME == NULL) smsg(_("sourcing \"%s\""), fname); else - smsg(_("line %ld: sourcing \"%s\""), - sourcing_lnum, fname); + smsg(_("line %ld: sourcing \"%s\""), SOURCING_LNUM, fname); verbose_leave(); } if (is_vimrc == DOSO_VIMRC) @@ -1090,10 +1203,7 @@ do_source( #endif // Keep the sourcing name/lnum, for recursive calls. - save_sourcing_name = sourcing_name; - sourcing_name = fname_exp; - save_sourcing_lnum = sourcing_lnum; - sourcing_lnum = 0; + estack_push(ETYPE_SCRIPT, fname_exp, 0); #ifdef STARTUPTIME if (time_fd != NULL) @@ -1233,14 +1343,13 @@ do_source( if (got_int) emsg(_(e_interr)); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; + estack_pop(); if (p_verbose > 1) { verbose_enter(); smsg(_("finished sourcing %s"), fname); - if (sourcing_name != NULL) - smsg(_("continuing in %s"), sourcing_name); + if (SOURCING_NAME != NULL) + smsg(_("continuing in %s"), SOURCING_NAME); verbose_leave(); } #ifdef STARTUPTIME @@ -1381,7 +1490,7 @@ get_sourced_lnum(char_u *(*fgetline)(int { return fgetline == getsourceline ? ((struct source_cookie *)cookie)->sourcing_lnum - : sourcing_lnum; + : SOURCING_LNUM; } static char_u * @@ -1507,7 +1616,7 @@ getsourceline(int c UNUSED, void *cookie // If breakpoints have been added/deleted need to check for it. if (sp->dbg_tick < debug_tick) { - sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); + sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, SOURCING_LNUM); sp->dbg_tick = debug_tick; } # ifdef FEAT_PROFILE @@ -1517,7 +1626,7 @@ getsourceline(int c UNUSED, void *cookie #endif // Set the current sourcing line number. - sourcing_lnum = sp->sourcing_lnum + 1; + SOURCING_LNUM = sp->sourcing_lnum + 1; // Get current line. If there is a read-ahead line, use it, otherwise get // one now. @@ -1602,11 +1711,11 @@ getsourceline(int c UNUSED, void *cookie #ifdef FEAT_EVAL // Did we encounter a breakpoint? - if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) + if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) { - dbg_breakpoint(sp->fname, sourcing_lnum); + dbg_breakpoint(sp->fname, SOURCING_LNUM); // Find next breakpoint. - sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); + sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, SOURCING_LNUM); sp->dbg_tick = debug_tick; } #endif diff --git a/src/spellfile.c b/src/spellfile.c --- a/src/spellfile.c +++ b/src/spellfile.c @@ -349,8 +349,6 @@ spell_load_file( int i; int n; int len; - char_u *save_sourcing_name = sourcing_name; - linenr_T save_sourcing_lnum = sourcing_lnum; slang_T *lp = NULL; int c = 0; int res; @@ -393,8 +391,7 @@ spell_load_file( lp = old_lp; // Set sourcing_name, so that error messages mention the file name. - sourcing_name = fname; - sourcing_lnum = 0; + estack_push(ETYPE_SPELL, fname, 0); /* *
: @@ -581,8 +578,7 @@ endFAIL: endOK: if (fd != NULL) fclose(fd); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; + estack_pop(); return lp; } diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -1496,6 +1496,8 @@ typedef struct // used for s: variables int uf_refcount; // reference count, see func_name_refcount() funccall_T *uf_scoped; // l: local variables for closure + char_u *uf_name_exp; // if "uf_name[]" starts with SNR the name with + // "" as a string, otherwise NULL char_u uf_name[1]; // name of function (actually longer); can // start with 123_ ( is K_SPECIAL // KS_EXTRA KE_SNR) @@ -1665,6 +1667,38 @@ struct partial_S dict_T *pt_dict; // dict for "self" }; +typedef struct AutoPatCmd_S AutoPatCmd; + +/* + * Entry in the execution stack "exestack". + */ +typedef enum { + ETYPE_TOP, // toplevel + ETYPE_SCRIPT, // sourcing script, use es_info.sctx + ETYPE_UFUNC, // user function, use es_info.ufunc + ETYPE_AUCMD, // autocomand, use es_info.aucmd + ETYPE_MODELINE, // modeline, use es_info.sctx + ETYPE_EXCEPT, // exception, use es_info.exception + ETYPE_ARGS, // command line argument + ETYPE_ENV, // environment variable + ETYPE_INTERNAL, // internal operation + ETYPE_SPELL, // loading spell file +} etype_T; + +typedef struct { + long es_lnum; // replaces "sourcing_lnum" + char_u *es_name; // replaces "sourcing_name" + etype_T es_type; + union { + sctx_T *sctx; // script and modeline info +#if defined(FEAT_EVAL) + ufunc_T *ufunc; // function info +#endif + AutoPatCmd *aucmd; // autocommand info + except_T *except; // exception info + } es_info; +} estack_T; + // Information returned by get_tty_info(). typedef struct { int backspace; // what the Backspace key produces diff --git a/src/term.c b/src/term.c --- a/src/term.c +++ b/src/term.c @@ -2277,7 +2277,7 @@ add_termcap_entry(char_u *name, int forc } #endif - if (sourcing_name == NULL) + if (SOURCING_NAME == NULL) { #ifdef HAVE_TGETENT if (error_msg != NULL) diff --git a/src/testdir/test_debugger.vim b/src/testdir/test_debugger.vim --- a/src/testdir/test_debugger.vim +++ b/src/testdir/test_debugger.vim @@ -14,7 +14,7 @@ func RunDbgCmd(buf, cmd, ...) " Verify the expected output let lnum = 20 - len(a:1) for l in a:1 - call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}) + call WaitForAssert({-> assert_equal(l, term_getline(a:buf, lnum))}, 200) let lnum += 1 endfor endif diff --git a/src/testing.c b/src/testing.c --- a/src/testing.c +++ b/src/testing.c @@ -21,22 +21,24 @@ static void prepare_assert_error(garray_T *gap) { - char buf[NUMBUFLEN]; + char buf[NUMBUFLEN]; + char_u *sname = estack_sfile(); ga_init2(gap, 1, 100); - if (sourcing_name != NULL) + if (sname != NULL) { - ga_concat(gap, sourcing_name); - if (sourcing_lnum > 0) + ga_concat(gap, sname); + if (SOURCING_LNUM > 0) ga_concat(gap, (char_u *)" "); } - if (sourcing_lnum > 0) + if (SOURCING_LNUM > 0) { - sprintf(buf, "line %ld", (long)sourcing_lnum); + sprintf(buf, "line %ld", (long)SOURCING_LNUM); ga_concat(gap, (char_u *)buf); } - if (sourcing_name != NULL || sourcing_lnum > 0) + if (sname != NULL || SOURCING_LNUM > 0) ga_concat(gap, (char_u *)": "); + vim_free(sname); } /* diff --git a/src/usercmd.c b/src/usercmd.c --- a/src/usercmd.c +++ b/src/usercmd.c @@ -191,7 +191,7 @@ find_ucmd( { xp->xp_arg = uc->uc_compl_arg; xp->xp_script_ctx = uc->uc_script_ctx; - xp->xp_script_ctx.sc_lnum += sourcing_lnum; + xp->xp_script_ctx.sc_lnum += SOURCING_LNUM; } # endif // Do not search for further abbreviations @@ -956,7 +956,7 @@ uc_add_command( cmd->uc_compl = compl; #ifdef FEAT_EVAL cmd->uc_script_ctx = current_sctx; - cmd->uc_script_ctx.sc_lnum += sourcing_lnum; + cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM; cmd->uc_compl_arg = compl_arg; #endif cmd->uc_addr_type = addr_type; diff --git a/src/userfunc.c b/src/userfunc.c --- a/src/userfunc.c +++ b/src/userfunc.c @@ -226,6 +226,22 @@ register_closure(ufunc_T *fp) return OK; } + static void +set_ufunc_name(ufunc_T *fp, char_u *name) +{ + STRCPY(fp->uf_name, name); + + if (name[0] == K_SPECIAL) + { + fp->uf_name_exp = alloc(STRLEN(name) + 3); + if (fp->uf_name_exp != NULL) + { + STRCPY(fp->uf_name_exp, ""); + STRCAT(fp->uf_name_exp, fp->uf_name + 3); + } + } +} + /* * Parse a lambda expression and get a Funcref from "*arg". * Return OK or FAIL. Returns NOTDONE for dict or {expr}. @@ -309,7 +325,7 @@ get_lambda_tv(char_u **arg, typval_T *re vim_strncpy(p + 7, s, e - s); fp->uf_refcount = 1; - STRCPY(fp->uf_name, name); + set_ufunc_name(fp, name); hash_add(&func_hashtab, UF2HIKEY(fp)); fp->uf_args = newargs; ga_init(&fp->uf_def_args); @@ -333,7 +349,7 @@ get_lambda_tv(char_u **arg, typval_T *re fp->uf_flags = flags; fp->uf_calls = 0; fp->uf_script_ctx = current_sctx; - fp->uf_script_ctx.sc_lnum += sourcing_lnum - newlines.ga_len; + fp->uf_script_ctx.sc_lnum += SOURCING_LNUM - newlines.ga_len; pt->pt_func = fp; pt->pt_refcount = 1; @@ -759,8 +775,6 @@ call_user_func( linenr_T lastline, // last line of range dict_T *selfdict) // Dictionary for "self" { - char_u *save_sourcing_name; - linenr_T save_sourcing_lnum; sctx_T save_current_sctx; int using_sandbox = FALSE; funccall_T *fc; @@ -774,7 +788,6 @@ call_user_func( int islambda = FALSE; char_u numbuf[NUMBUFLEN]; char_u *name; - size_t len; #ifdef FEAT_PROFILE proftime_T wait_start; proftime_T call_start; @@ -948,9 +961,6 @@ call_user_func( // Don't redraw while executing the function. ++RedrawingDisabled; - save_sourcing_name = sourcing_name; - save_sourcing_lnum = sourcing_lnum; - sourcing_lnum = 1; if (fp->uf_flags & FC_SANDBOX) { @@ -958,65 +968,51 @@ call_user_func( ++sandbox; } - // need space for function name + ("function " + 3) or "[number]" - len = (save_sourcing_name == NULL ? 0 : STRLEN(save_sourcing_name)) - + STRLEN(fp->uf_name) + 20; - sourcing_name = alloc(len); - if (sourcing_name != NULL) + estack_push_ufunc(ETYPE_UFUNC, fp, 1); + if (p_verbose >= 12) { - if (save_sourcing_name != NULL - && STRNCMP(save_sourcing_name, "function ", 9) == 0) - sprintf((char *)sourcing_name, "%s[%d]..", - save_sourcing_name, (int)save_sourcing_lnum); - else - STRCPY(sourcing_name, "function "); - cat_func_name(sourcing_name + STRLEN(sourcing_name), fp); - - if (p_verbose >= 12) + ++no_wait_return; + verbose_enter_scroll(); + + smsg(_("calling %s"), SOURCING_NAME); + if (p_verbose >= 14) { - ++no_wait_return; - verbose_enter_scroll(); - - smsg(_("calling %s"), sourcing_name); - if (p_verbose >= 14) + char_u buf[MSG_BUF_LEN]; + char_u numbuf2[NUMBUFLEN]; + char_u *tofree; + char_u *s; + + msg_puts("("); + for (i = 0; i < argcount; ++i) { - char_u buf[MSG_BUF_LEN]; - char_u numbuf2[NUMBUFLEN]; - char_u *tofree; - char_u *s; - - msg_puts("("); - for (i = 0; i < argcount; ++i) + if (i > 0) + msg_puts(", "); + if (argvars[i].v_type == VAR_NUMBER) + msg_outnum((long)argvars[i].vval.v_number); + else { - if (i > 0) - msg_puts(", "); - if (argvars[i].v_type == VAR_NUMBER) - msg_outnum((long)argvars[i].vval.v_number); - else + // Do not want errors such as E724 here. + ++emsg_off; + s = tv2string(&argvars[i], &tofree, numbuf2, 0); + --emsg_off; + if (s != NULL) { - // Do not want errors such as E724 here. - ++emsg_off; - s = tv2string(&argvars[i], &tofree, numbuf2, 0); - --emsg_off; - if (s != NULL) + if (vim_strsize(s) > MSG_BUF_CLEN) { - if (vim_strsize(s) > MSG_BUF_CLEN) - { - trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); - s = buf; - } - msg_puts((char *)s); - vim_free(tofree); + trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); + s = buf; } + msg_puts((char *)s); + vim_free(tofree); } } - msg_puts(")"); } - msg_puts("\n"); // don't overwrite this either - - verbose_leave_scroll(); - --no_wait_return; + msg_puts(")"); } + msg_puts("\n"); // don't overwrite this either + + verbose_leave_scroll(); + --no_wait_return; } #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -1085,9 +1081,9 @@ call_user_func( verbose_enter_scroll(); if (aborting()) - smsg(_("%s aborted"), sourcing_name); + smsg(_("%s aborted"), SOURCING_NAME); else if (fc->rettv->v_type == VAR_NUMBER) - smsg(_("%s returning #%ld"), sourcing_name, + smsg(_("%s returning #%ld"), SOURCING_NAME, (long)fc->rettv->vval.v_number); else { @@ -1109,7 +1105,7 @@ call_user_func( trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); s = buf; } - smsg(_("%s returning %s"), sourcing_name, s); + smsg(_("%s returning %s"), SOURCING_NAME, s); vim_free(tofree); } } @@ -1119,9 +1115,7 @@ call_user_func( --no_wait_return; } - vim_free(sourcing_name); - sourcing_name = save_sourcing_name; - sourcing_lnum = save_sourcing_lnum; + estack_pop(); current_sctx = save_current_sctx; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) @@ -1130,12 +1124,12 @@ call_user_func( if (using_sandbox) --sandbox; - if (p_verbose >= 12 && sourcing_name != NULL) + if (p_verbose >= 12 && SOURCING_NAME != NULL) { ++no_wait_return; verbose_enter_scroll(); - smsg(_("continuing in %s"), sourcing_name); + smsg(_("continuing in %s"), SOURCING_NAME); msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); @@ -1204,13 +1198,11 @@ func_clear_items(ufunc_T *fp) ga_clear_strings(&(fp->uf_args)); ga_clear_strings(&(fp->uf_def_args)); ga_clear_strings(&(fp->uf_lines)); + VIM_CLEAR(fp->uf_name_exp); #ifdef FEAT_PROFILE - vim_free(fp->uf_tml_count); - fp->uf_tml_count = NULL; - vim_free(fp->uf_tml_total); - fp->uf_tml_total = NULL; - vim_free(fp->uf_tml_self); - fp->uf_tml_self = NULL; + VIM_CLEAR(fp->uf_tml_count); + VIM_CLEAR(fp->uf_tml_total); + VIM_CLEAR(fp->uf_tml_self); #endif } @@ -1736,11 +1728,8 @@ list_func_head(ufunc_T *fp, int indent) if (indent) msg_puts(" "); msg_puts("function "); - if (fp->uf_name[0] == K_SPECIAL) - { - msg_puts_attr("", HL_ATTR(HLF_8)); - msg_puts((char *)fp->uf_name + 3); - } + if (fp->uf_name_exp != NULL) + msg_puts((char *)fp->uf_name_exp); else msg_puts((char *)fp->uf_name); msg_putchar('('); @@ -2308,7 +2297,7 @@ ex_function(exarg_T *eap) } // Save the starting line number. - sourcing_lnum_top = sourcing_lnum; + sourcing_lnum_top = SOURCING_LNUM; indent = 2; nesting = 0; @@ -2351,10 +2340,10 @@ ex_function(exarg_T *eap) goto erret; } - // Detect line continuation: sourcing_lnum increased more than one. + // Detect line continuation: SOURCING_LNUM increased more than one. sourcing_lnum_off = get_sourced_lnum(eap->getline, eap->cookie); - if (sourcing_lnum < sourcing_lnum_off) - sourcing_lnum_off -= sourcing_lnum; + if (SOURCING_LNUM < sourcing_lnum_off) + sourcing_lnum_off -= SOURCING_LNUM; else sourcing_lnum_off = 0; @@ -2631,16 +2620,16 @@ ex_function(exarg_T *eap) // Check that the autoload name matches the script name. j = FAIL; - if (sourcing_name != NULL) + if (SOURCING_NAME != NULL) { scriptname = autoload_name(name); if (scriptname != NULL) { p = vim_strchr(scriptname, '/'); plen = (int)STRLEN(p); - slen = (int)STRLEN(sourcing_name); + slen = (int)STRLEN(SOURCING_NAME); if (slen > plen && fnamecmp(p, - sourcing_name + slen - plen) == 0) + SOURCING_NAME + slen - plen) == 0) j = OK; vim_free(scriptname); } @@ -2685,7 +2674,7 @@ ex_function(exarg_T *eap) } // insert the new function in the function list - STRCPY(fp->uf_name, name); + set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); @@ -3353,7 +3342,7 @@ get_func_line( if (fcp->dbg_tick != debug_tick) { fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, - sourcing_lnum); + SOURCING_LNUM); fcp->dbg_tick = debug_tick; } #ifdef FEAT_PROFILE @@ -3376,7 +3365,7 @@ get_func_line( else { retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); - sourcing_lnum = fcp->linenr; + SOURCING_LNUM = fcp->linenr; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) func_line_start(cookie); @@ -3385,12 +3374,12 @@ get_func_line( } // Did we encounter a breakpoint? - if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum) + if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) { - dbg_breakpoint(fp->uf_name, sourcing_lnum); + dbg_breakpoint(fp->uf_name, SOURCING_LNUM); // Find next breakpoint. fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, - sourcing_lnum); + SOURCING_LNUM); fcp->dbg_tick = debug_tick; } diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -743,6 +743,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 56, +/**/ 55, /**/ 54,