To: vim_dev@googlegroups.com Subject: Patch 8.2.0056 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.2.0056 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. Files: src/structs.h, src/globals.h, src/autocmd.c, src/buffer.c src/debugger.c, src/ex_docmd.c, src/ex_eval.c, src/highlight.c, src/main.c, src/map.c, src/message.c, src/proto/scriptfile.pro, src/scriptfile.c, src/option.c, src/profiler.c, src/spellfile.c, src/term.c, src/testing.c, src/usercmd.c, src/userfunc.c, src/kword_test.c, src/testdir/test_debugger.vim *** ../vim-8.2.0055/src/structs.h 2019-12-25 18:14:10.481839651 +0100 --- src/structs.h 2019-12-29 19:12:06.660504770 +0100 *************** *** 1496,1501 **** --- 1496,1503 ---- // 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,1670 **** --- 1667,1704 ---- 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 *** ../vim-8.2.0055/src/globals.h 2019-12-27 13:49:19.984946890 +0100 --- src/globals.h 2019-12-29 16:39:23.656982200 +0100 *************** *** 266,273 **** 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 #ifdef FEAT_EVAL EXTERN int ex_nesting_level INIT(= 0); // nesting level --- 266,280 ---- EXTERN int msg_no_more INIT(= FALSE); // don't use more prompt, truncate // messages ! /* ! * 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 *** ../vim-8.2.0055/src/autocmd.c 2019-11-30 20:32:37.000000000 +0100 --- src/autocmd.c 2019-12-29 16:39:45.052886815 +0100 *************** *** 218,224 **** /* * struct used to keep status while executing autocommands for an event. */ ! typedef struct AutoPatCmd { AutoPat *curpat; // next AutoPat to examine AutoCmd *nextcmd; // next AutoCmd to execute --- 218,224 ---- /* * struct used to keep status while executing autocommands for an event. */ ! struct AutoPatCmd_S { AutoPat *curpat; // next AutoPat to examine AutoCmd *nextcmd; // next AutoCmd to execute *************** *** 229,236 **** 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; static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands --- 229,236 ---- event_T event; // current event int arg_bufnr; // Initially equal to , set to zero when // buf is deleted. ! AutoPatCmd *next; // chain of active apc-s for auto-invalidation ! }; static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands *************** *** 1242,1248 **** ac->cmd = vim_strsave(cmd); #ifdef FEAT_EVAL ac->script_ctx = current_sctx; ! ac->script_ctx.sc_lnum += sourcing_lnum; #endif if (ac->cmd == NULL) { --- 1242,1248 ---- ac->cmd = vim_strsave(cmd); #ifdef FEAT_EVAL ac->script_ctx = current_sctx; ! ac->script_ctx.sc_lnum += SOURCING_LNUM; #endif if (ac->cmd == NULL) { *************** *** 1805,1812 **** 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; --- 1805,1810 ---- *************** *** 2020,2029 **** // 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 #ifdef FEAT_EVAL save_current_sctx = current_sctx; --- 2018,2026 ---- // Don't redraw while doing autocommands. ++RedrawingDisabled; ! ! // name and lnum are filled in later ! estack_push(ETYPE_AUCMD, NULL, 0); #ifdef FEAT_EVAL save_current_sctx = current_sctx; *************** *** 2126,2134 **** 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(autocmd_fname); autocmd_fname = save_autocmd_fname; autocmd_fname_full = save_autocmd_fname_full; --- 2123,2130 ---- autocmd_busy = save_autocmd_busy; filechangeshell_busy = FALSE; autocmd_nested = save_autocmd_nested; ! vim_free(SOURCING_NAME); ! estack_pop(); vim_free(autocmd_fname); autocmd_fname = save_autocmd_fname; autocmd_fname_full = save_autocmd_fname_full; *************** *** 2256,2263 **** AutoCmd *cp; char_u *name; char *s; ! VIM_CLEAR(sourcing_name); for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) { --- 2252,2260 ---- AutoCmd *cp; char_u *name; char *s; + char_u **sourcing_namep = &SOURCING_NAME; ! VIM_CLEAR(*sourcing_namep); for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next) { *************** *** 2277,2292 **** { name = event_nr2name(apc->event); s = _("%s Autocommands for \"%s\""); ! sourcing_name = alloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1); ! if (sourcing_name != NULL) { ! sprintf((char *)sourcing_name, s, (char *)name, (char *)ap->pat); if (p_verbose >= 8) { verbose_enter(); ! smsg(_("Executing %s"), sourcing_name); verbose_leave(); } } --- 2274,2289 ---- { name = event_nr2name(apc->event); s = _("%s Autocommands for \"%s\""); ! *sourcing_namep = alloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1); ! if (*sourcing_namep != NULL) { ! sprintf((char *)*sourcing_namep, s, (char *)name, (char *)ap->pat); if (p_verbose >= 8) { verbose_enter(); ! smsg(_("Executing %s"), *sourcing_namep); verbose_leave(); } } *** ../vim-8.2.0055/src/buffer.c 2019-12-29 13:56:28.692861883 +0100 --- src/buffer.c 2019-12-29 16:17:22.877768244 +0100 *************** *** 5279,5286 **** 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 --- 5279,5284 ---- *************** *** 5325,5334 **** 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"; end = FALSE; while (end == FALSE) --- 5323,5330 ---- if (linecopy == NULL) return FAIL; ! // prepare for emsg() ! estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum); end = FALSE; while (end == FALSE) *************** *** 5371,5377 **** save_current_sctx = current_sctx; current_sctx.sc_sid = SID_MODELINE; current_sctx.sc_seq = 0; ! current_sctx.sc_lnum = 0; current_sctx.sc_version = 1; #endif // Make sure no risky things are executed as a side effect. --- 5367,5373 ---- save_current_sctx = current_sctx; current_sctx.sc_sid = SID_MODELINE; current_sctx.sc_seq = 0; ! current_sctx.sc_lnum = lnum; current_sctx.sc_version = 1; #endif // Make sure no risky things are executed as a side effect. *************** *** 5389,5397 **** s = e + 1; // advance to next part } ! sourcing_lnum = save_sourcing_lnum; ! sourcing_name = save_sourcing_name; ! vim_free(linecopy); } return retval; --- 5385,5391 ---- s = e + 1; // advance to next part } ! estack_pop(); vim_free(linecopy); } return retval; *** ../vim-8.2.0055/src/debugger.c 2019-12-25 18:14:10.481839651 +0100 --- src/debugger.c 2019-12-29 21:00:17.504117635 +0100 *************** *** 51,56 **** --- 51,57 ---- 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,113 **** 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); else smsg(_("cmd: %s"), cmd); --- 105,116 ---- vim_free(debug_newval); debug_newval = NULL; } ! 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,313 **** } static int ! get_maxbacktrace_level(void) { char *p, *q; int maxbacktrace = 0; ! if (sourcing_name != NULL) { ! p = (char *)sourcing_name; while ((q = strstr(p, "..")) != NULL) { p = q + 2; --- 303,316 ---- } static int ! get_maxbacktrace_level(char_u *sname) { char *p, *q; int maxbacktrace = 0; ! if (sname != NULL) { ! p = (char *)sname; while ((q = strstr(p, "..")) != NULL) { p = q + 2; *************** *** 341,367 **** } else { ! int max = get_maxbacktrace_level(); if (debug_backtrace_level > max) { debug_backtrace_level = max; smsg(_("frame at highest level: %d"), max); } } } static void do_showbacktrace(char_u *cmd) { char *cur; char *next; int i = 0; ! int max = get_maxbacktrace_level(); ! if (sourcing_name != NULL) { ! cur = (char *)sourcing_name; while (!got_int) { next = strstr(cur, ".."); --- 344,375 ---- } else { ! 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; ! sname = estack_sfile(); ! max = get_maxbacktrace_level(sname); ! if (sname != NULL) { ! cur = (char *)sname; while (!got_int) { next = strstr(cur, ".."); *************** *** 377,385 **** *next = '.'; cur = next + 2; } } ! if (sourcing_lnum != 0) ! smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd); else smsg(_("cmd: %s"), cmd); } --- 385,395 ---- *next = '.'; cur = next + 2; } + vim_free(sname); } ! ! if (SOURCING_LNUM != 0) ! smsg(_("line %ld: %s"), (long)SOURCING_LNUM, cmd); else smsg(_("cmd: %s"), cmd); } *** ../vim-8.2.0055/src/ex_docmd.c 2019-12-16 17:10:30.291144418 +0100 --- src/ex_docmd.c 2019-12-29 18:44:31.113192680 +0100 *************** *** 703,709 **** } else if (getline_equal(fgetline, cookie, getsourceline)) { ! fname = sourcing_name; breakpoint = source_breakpoint(real_cookie); dbg_tick = source_dbg_tick(real_cookie); } --- 703,709 ---- } else if (getline_equal(fgetline, cookie, getsourceline)) { ! fname = SOURCING_NAME; breakpoint = source_breakpoint(real_cookie); dbg_tick = source_dbg_tick(real_cookie); } *************** *** 819,840 **** { *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), ! 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; // Did we encounter a breakpoint? if (breakpoint != NULL && *breakpoint != 0 ! && *breakpoint <= sourcing_lnum) { ! dbg_breakpoint(fname, sourcing_lnum); // Find next breakpoint. *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), ! fname, sourcing_lnum); *dbg_tick = debug_tick; } # ifdef FEAT_PROFILE --- 819,840 ---- { *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), ! 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; // Did we encounter a breakpoint? if (breakpoint != NULL && *breakpoint != 0 ! && *breakpoint <= SOURCING_LNUM) { ! dbg_breakpoint(fname, SOURCING_LNUM); // Find next breakpoint. *breakpoint = dbg_find_breakpoint( getline_equal(fgetline, cookie, getsourceline), ! fname, SOURCING_LNUM); *dbg_tick = debug_tick; } # ifdef FEAT_PROFILE *************** *** 963,970 **** } } ! if (p_verbose >= 15 && sourcing_name != NULL) ! msg_verbose_cmd(sourcing_lnum, cmdline_copy); /* * 2. Execute one '|' separated command. --- 963,970 ---- } } ! if (p_verbose >= 15 && SOURCING_NAME != NULL) ! msg_verbose_cmd(SOURCING_LNUM, cmdline_copy); /* * 2. Execute one '|' separated command. *************** *** 1081,1087 **** // Check for the next breakpoint after a watchexpression if (breakpoint != NULL && has_watchexpr()) { ! *breakpoint = dbg_find_breakpoint(FALSE, fname, sourcing_lnum); *dbg_tick = debug_tick; } --- 1081,1087 ---- // Check for the next breakpoint after a watchexpression if (breakpoint != NULL && has_watchexpr()) { ! *breakpoint = dbg_find_breakpoint(FALSE, fname, SOURCING_LNUM); *dbg_tick = debug_tick; } *************** *** 1092,1098 **** { if (lines_ga.ga_len > 0) { ! sourcing_lnum = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; free_cmdlines(&lines_ga); } --- 1092,1098 ---- { if (lines_ga.ga_len > 0) { ! SOURCING_LNUM = ((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum; free_cmdlines(&lines_ga); } *************** *** 1234,1241 **** if (did_throw) { void *p = NULL; - char_u *saved_sourcing_name; - int saved_sourcing_lnum; struct msglist *messages = NULL, *next; /* --- 1234,1239 ---- *************** *** 1260,1269 **** break; } ! saved_sourcing_name = sourcing_name; ! saved_sourcing_lnum = sourcing_lnum; ! sourcing_name = current_exception->throw_name; ! sourcing_lnum = current_exception->throw_lnum; current_exception->throw_name = NULL; discard_current_exception(); // uses IObuff if 'verbose' --- 1258,1265 ---- break; } ! 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,1295 **** emsg(p); vim_free(p); } ! vim_free(sourcing_name); ! sourcing_name = saved_sourcing_name; ! sourcing_lnum = saved_sourcing_lnum; } /* --- 1283,1290 ---- emsg(p); vim_free(p); } ! vim_free(SOURCING_NAME); ! estack_pop(); } /* *************** *** 1428,1434 **** KeyTyped = FALSE; ++cp->current_line; wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line; ! sourcing_lnum = wp->lnum; return vim_strsave(wp->line); } --- 1423,1429 ---- KeyTyped = FALSE; ++cp->current_line; wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line; ! SOURCING_LNUM = wp->lnum; return vim_strsave(wp->line); } *************** *** 1441,1447 **** 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; ++gap->ga_len; return OK; } --- 1436,1442 ---- 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; ++gap->ga_len; return OK; } *************** *** 8171,8203 **** break; case SPEC_SFILE: // file name for ":so" command ! result = sourcing_name; if (result == NULL) { *errormsg = _("E498: no :source file name to substitute for \"\""); return NULL; } break; case SPEC_SLNUM: // line in file for ":so" command ! if (sourcing_name == NULL || sourcing_lnum == 0) { *errormsg = _("E842: no line number to use for \"\""); return NULL; } ! sprintf((char *)strbuf, "%ld", (long)sourcing_lnum); result = strbuf; break; #ifdef FEAT_EVAL case SPEC_SFLNUM: // line in script file ! 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)); result = strbuf; break; #endif --- 8166,8199 ---- break; case SPEC_SFILE: // file name for ":so" command ! 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) { *errormsg = _("E842: no line number to use for \"\""); return NULL; } ! 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) { *errormsg = _("E961: no line number to use for \"\""); return NULL; } sprintf((char *)strbuf, "%ld", ! (long)(current_sctx.sc_lnum + SOURCING_LNUM)); result = strbuf; break; #endif *** ../vim-8.2.0055/src/ex_eval.c 2019-12-16 17:10:30.291144418 +0100 --- src/ex_eval.c 2019-12-29 22:50:57.021592930 +0100 *************** *** 534,548 **** goto nomem; excp->type = type; ! excp->throw_name = vim_strsave(sourcing_name == NULL ! ? (char_u *)"" : sourcing_name); if (excp->throw_name == NULL) { if (should_free) vim_free(excp->value); goto nomem; } ! excp->throw_lnum = sourcing_lnum; if (p_verbose >= 13 || debug_break_level > 0) { --- 534,549 ---- goto nomem; excp->type = type; ! 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; if (p_verbose >= 13 || debug_break_level > 0) { *** ../vim-8.2.0055/src/highlight.c 2019-12-24 15:38:18.059988789 +0100 --- src/highlight.c 2019-12-29 16:41:16.584486153 +0100 *************** *** 748,754 **** if (to_id > 0 && !forceit && !init && hl_has_settings(from_id - 1, 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 --- 748,754 ---- if (to_id > 0 && !forceit && !init && hl_has_settings(from_id - 1, 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,769 **** 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; #endif HL_TABLE()[from_id - 1].sg_cleared = FALSE; redraw_all_later(SOME_VALID); --- 763,769 ---- 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; #endif HL_TABLE()[from_id - 1].sg_cleared = FALSE; redraw_all_later(SOME_VALID); *************** *** 1518,1524 **** 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; #endif } --- 1518,1524 ---- 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; #endif } *** ../vim-8.2.0055/src/main.c 2019-12-23 22:59:14.264820697 +0100 --- src/main.c 2019-12-29 16:26:59.455699649 +0100 *************** *** 911,916 **** --- 911,917 ---- void common_init(mparm_T *paramp) { + estack_init(); cmdline_init(); (void)mb_init(); // init mb_bytelen_tab[] to ones *************** *** 3089,3101 **** if (cnt > 0) { curwin->w_cursor.lnum = 0; // just in case.. ! sourcing_name = (char_u *)_("pre-vimrc command line"); # ifdef FEAT_EVAL current_sctx.sc_sid = SID_CMDARG; # endif for (i = 0; i < cnt; ++i) do_cmdline_cmd(cmds[i]); ! sourcing_name = NULL; # ifdef FEAT_EVAL current_sctx.sc_sid = 0; # endif --- 3090,3102 ---- if (cnt > 0) { curwin->w_cursor.lnum = 0; // just in case.. ! 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]); ! estack_pop(); # ifdef FEAT_EVAL current_sctx.sc_sid = 0; # endif *************** *** 3119,3125 **** msg_scroll = TRUE; if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) curwin->w_cursor.lnum = 0; ! sourcing_name = (char_u *)"command line"; #ifdef FEAT_EVAL current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; --- 3120,3126 ---- msg_scroll = TRUE; if (parmp->tagname == NULL && curwin->w_cursor.lnum <= 1) curwin->w_cursor.lnum = 0; ! estack_push(ETYPE_ARGS, (char_u *)"command line", 0); #ifdef FEAT_EVAL current_sctx.sc_sid = SID_CARG; current_sctx.sc_seq = 0; *************** *** 3130,3136 **** if (parmp->cmds_tofree[i]) vim_free(parmp->commands[i]); } ! sourcing_name = NULL; #ifdef FEAT_EVAL current_sctx.sc_sid = 0; #endif --- 3131,3137 ---- if (parmp->cmds_tofree[i]) vim_free(parmp->commands[i]); } ! estack_pop(); #ifdef FEAT_EVAL current_sctx.sc_sid = 0; #endif *************** *** 3336,3343 **** 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 --- 3337,3342 ---- *************** *** 3346,3355 **** { if (is_viminit) vimrc_found(NULL, NULL); ! save_sourcing_name = sourcing_name; ! save_sourcing_lnum = sourcing_lnum; ! sourcing_name = env; ! sourcing_lnum = 0; #ifdef FEAT_EVAL save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; --- 3345,3351 ---- { if (is_viminit) vimrc_found(NULL, NULL); ! estack_push(ETYPE_ENV, env, 0); #ifdef FEAT_EVAL save_current_sctx = current_sctx; current_sctx.sc_sid = SID_ENV; *************** *** 3358,3365 **** current_sctx.sc_version = 1; #endif do_cmdline_cmd(initstr); ! sourcing_name = save_sourcing_name; ! sourcing_lnum = save_sourcing_lnum; #ifdef FEAT_EVAL current_sctx = save_current_sctx; #endif --- 3354,3361 ---- current_sctx.sc_version = 1; #endif do_cmdline_cmd(initstr); ! ! estack_pop(); #ifdef FEAT_EVAL current_sctx = save_current_sctx; #endif *** ../vim-8.2.0055/src/map.c 2019-11-02 22:51:27.000000000 +0100 --- src/map.c 2019-12-29 16:41:26.320444196 +0100 *************** *** 697,703 **** #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; ! mp->m_script_ctx.sc_lnum += sourcing_lnum; #endif did_it = TRUE; } --- 697,703 ---- #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; ! mp->m_script_ctx.sc_lnum += SOURCING_LNUM; #endif did_it = TRUE; } *************** *** 796,802 **** #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; ! mp->m_script_ctx.sc_lnum += sourcing_lnum; #endif // add the new entry in front of the abbrlist or maphash[] list --- 796,802 ---- #ifdef FEAT_EVAL mp->m_expr = expr; mp->m_script_ctx = current_sctx; ! mp->m_script_ctx.sc_lnum += SOURCING_LNUM; #endif // add the new entry in front of the abbrlist or maphash[] list *************** *** 1915,1928 **** 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 // Do this once for each buffer, and then once for global // mappings/abbreviations with bp == NULL --- 1915,1927 ---- char_u *p; int i; char_u buf[3]; int abbr; int hash; buf_T *bp; validate_maphash(); ! // 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,1985 **** if (bp == NULL) break; } ! sourcing_name = save_name; } #if defined(FEAT_EVAL) || defined(PROTO) --- 1978,1984 ---- if (bp == NULL) break; } ! estack_pop(); } #if defined(FEAT_EVAL) || defined(PROTO) *** ../vim-8.2.0055/src/message.c 2019-12-23 22:59:14.260820709 +0100 --- src/message.c 2019-12-29 20:09:53.238576174 +0100 *************** *** 434,448 **** } /* ! * Return TRUE if "sourcing_name" differs from "last_sourcing_name". */ static int other_sourcing_name(void) { ! if (sourcing_name != NULL) { if (last_sourcing_name != NULL) ! return STRCMP(sourcing_name, last_sourcing_name) != 0; return TRUE; } return FALSE; --- 434,448 ---- } /* ! * Return TRUE if "SOURCING_NAME" differs from "last_sourcing_name". */ static int other_sourcing_name(void) { ! if (SOURCING_NAME != NULL) { if (last_sourcing_name != NULL) ! return STRCMP(SOURCING_NAME, last_sourcing_name) != 0; return TRUE; } return FALSE; *************** *** 458,469 **** { char_u *Buf, *p; ! if (sourcing_name != NULL && other_sourcing_name()) { p = (char_u *)_("Error detected while processing %s:"); ! Buf = alloc(STRLEN(sourcing_name) + STRLEN(p)); if (Buf != NULL) ! sprintf((char *)Buf, (char *)p, sourcing_name); return Buf; } return NULL; --- 458,476 ---- { char_u *Buf, *p; ! 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(sname) + STRLEN(p)); if (Buf != NULL) ! sprintf((char *)Buf, (char *)p, sname); ! vim_free(tofree); return Buf; } return NULL; *************** *** 481,494 **** // 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) { p = (char_u *)_("line %4ld:"); Buf = alloc(STRLEN(p) + 20); if (Buf != NULL) ! sprintf((char *)Buf, (char *)p, (long)sourcing_lnum); return Buf; } return NULL; --- 488,501 ---- // 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) { p = (char_u *)_("line %4ld:"); Buf = alloc(STRLEN(p) + 20); if (Buf != NULL) ! sprintf((char *)Buf, (char *)p, (long)SOURCING_LNUM); return Buf; } return NULL; *************** *** 516,532 **** { msg_attr((char *)p, HL_ATTR(HLF_N)); vim_free(p); ! 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()) { vim_free(last_sourcing_name); ! if (sourcing_name == NULL) last_sourcing_name = NULL; else ! last_sourcing_name = vim_strsave(sourcing_name); } --no_wait_return; } --- 523,539 ---- { msg_attr((char *)p, HL_ATTR(HLF_N)); vim_free(p); ! 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()) { vim_free(last_sourcing_name); ! if (SOURCING_NAME == NULL) last_sourcing_name = NULL; else ! last_sourcing_name = vim_strsave(SOURCING_NAME); } --no_wait_return; } *************** *** 2312,2318 **** #ifdef FEAT_EVAL if (*get_vim_var_str(VV_SCROLLSTART) == NUL) { ! char_u *p = sourcing_name; char_u *tofree = NULL; int len; --- 2319,2325 ---- #ifdef FEAT_EVAL if (*get_vim_var_str(VV_SCROLLSTART) == NUL) { ! char_u *p = SOURCING_NAME; char_u *tofree = NULL; int len; *************** *** 2327,2333 **** if (tofree != NULL) { vim_snprintf((char *)tofree, len, _("%s line %ld"), ! p, (long)sourcing_lnum); p = tofree; } } --- 2334,2340 ---- if (tofree != NULL) { vim_snprintf((char *)tofree, len, _("%s line %ld"), ! p, (long)SOURCING_LNUM); p = tofree; } } *** ../vim-8.2.0055/src/proto/scriptfile.pro 2019-12-12 12:55:32.000000000 +0100 --- src/proto/scriptfile.pro 2019-12-29 18:48:29.056368319 +0100 *************** *** 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); *** ../vim-8.2.0055/src/scriptfile.c 2019-12-05 21:04:06.000000000 +0100 --- src/scriptfile.c 2019-12-29 20:57:44.184820163 +0100 *************** *** 19,24 **** --- 19,140 ---- #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,954 **** 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; --- 1063,1068 ---- *************** *** 1039,1049 **** if (p_verbose > 0) { verbose_enter(); ! if (sourcing_name == NULL) smsg(_("could not source \"%s\""), fname); else smsg(_("line %ld: could not source \"%s\""), ! sourcing_lnum, fname); verbose_leave(); } goto theend; --- 1153,1163 ---- if (p_verbose > 0) { verbose_enter(); ! if (SOURCING_NAME == NULL) smsg(_("could not source \"%s\""), fname); else smsg(_("line %ld: could not source \"%s\""), ! SOURCING_LNUM, fname); verbose_leave(); } goto theend; *************** *** 1055,1065 **** if (p_verbose > 1) { verbose_enter(); ! if (sourcing_name == NULL) smsg(_("sourcing \"%s\""), fname); else ! smsg(_("line %ld: sourcing \"%s\""), ! sourcing_lnum, fname); verbose_leave(); } if (is_vimrc == DOSO_VIMRC) --- 1169,1178 ---- if (p_verbose > 1) { verbose_enter(); ! if (SOURCING_NAME == NULL) smsg(_("sourcing \"%s\""), fname); else ! smsg(_("line %ld: sourcing \"%s\""), SOURCING_LNUM, fname); verbose_leave(); } if (is_vimrc == DOSO_VIMRC) *************** *** 1090,1099 **** #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; #ifdef STARTUPTIME if (time_fd != NULL) --- 1203,1209 ---- #endif // Keep the sourcing name/lnum, for recursive calls. ! estack_push(ETYPE_SCRIPT, fname_exp, 0); #ifdef STARTUPTIME if (time_fd != NULL) *************** *** 1233,1246 **** if (got_int) emsg(_(e_interr)); ! sourcing_name = save_sourcing_name; ! sourcing_lnum = save_sourcing_lnum; if (p_verbose > 1) { verbose_enter(); smsg(_("finished sourcing %s"), fname); ! if (sourcing_name != NULL) ! smsg(_("continuing in %s"), sourcing_name); verbose_leave(); } #ifdef STARTUPTIME --- 1343,1355 ---- if (got_int) emsg(_(e_interr)); ! estack_pop(); if (p_verbose > 1) { verbose_enter(); smsg(_("finished sourcing %s"), fname); ! if (SOURCING_NAME != NULL) ! smsg(_("continuing in %s"), SOURCING_NAME); verbose_leave(); } #ifdef STARTUPTIME *************** *** 1381,1387 **** { return fgetline == getsourceline ? ((struct source_cookie *)cookie)->sourcing_lnum ! : sourcing_lnum; } static char_u * --- 1490,1496 ---- { return fgetline == getsourceline ? ((struct source_cookie *)cookie)->sourcing_lnum ! : SOURCING_LNUM; } static char_u * *************** *** 1507,1513 **** // 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->dbg_tick = debug_tick; } # ifdef FEAT_PROFILE --- 1616,1622 ---- // 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->dbg_tick = debug_tick; } # ifdef FEAT_PROFILE *************** *** 1517,1523 **** #endif // Set the current sourcing line number. ! sourcing_lnum = sp->sourcing_lnum + 1; // Get current line. If there is a read-ahead line, use it, otherwise get // one now. --- 1626,1632 ---- #endif // Set the current sourcing line number. ! SOURCING_LNUM = sp->sourcing_lnum + 1; // Get current line. If there is a read-ahead line, use it, otherwise get // one now. *************** *** 1602,1612 **** #ifdef FEAT_EVAL // Did we encounter a breakpoint? ! if (sp->breakpoint != 0 && sp->breakpoint <= sourcing_lnum) { ! dbg_breakpoint(sp->fname, sourcing_lnum); // Find next breakpoint. ! sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, sourcing_lnum); sp->dbg_tick = debug_tick; } #endif --- 1711,1721 ---- #ifdef FEAT_EVAL // Did we encounter a breakpoint? ! if (sp->breakpoint != 0 && sp->breakpoint <= SOURCING_LNUM) { ! dbg_breakpoint(sp->fname, SOURCING_LNUM); // Find next breakpoint. ! sp->breakpoint = dbg_find_breakpoint(TRUE, sp->fname, SOURCING_LNUM); sp->dbg_tick = debug_tick; } #endif *** ../vim-8.2.0055/src/option.c 2019-12-05 20:11:19.000000000 +0100 --- src/option.c 2019-12-29 16:41:30.196427514 +0100 *************** *** 2435,2441 **** int indir = (int)options[opt_idx].indir; sctx_T new_script_ctx = script_ctx; ! 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. --- 2435,2441 ---- int indir = (int)options[opt_idx].indir; sctx_T new_script_ctx = script_ctx; ! 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. *** ../vim-8.2.0055/src/profiler.c 2019-09-18 22:00:33.000000000 +0200 --- src/profiler.c 2019-12-29 16:42:33.308158473 +0100 *************** *** 602,611 **** 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) { ! 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; --- 602,611 ---- 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) { ! 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,918 **** 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) { // 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; while (si->sn_prl_ga.ga_len <= si->sn_prl_idx && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) { --- 906,918 ---- 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) { // 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; while (si->sn_prl_ga.ga_len <= si->sn_prl_idx && si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) { *** ../vim-8.2.0055/src/spellfile.c 2019-12-05 21:20:39.000000000 +0100 --- src/spellfile.c 2019-12-29 16:33:07.918397631 +0100 *************** *** 349,356 **** 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; --- 349,354 ---- *************** *** 393,400 **** lp = old_lp; // Set sourcing_name, so that error messages mention the file name. ! sourcing_name = fname; ! sourcing_lnum = 0; /* *
: --- 391,397 ---- lp = old_lp; // Set sourcing_name, so that error messages mention the file name. ! estack_push(ETYPE_SPELL, fname, 0); /* *
: *************** *** 581,588 **** endOK: if (fd != NULL) fclose(fd); ! sourcing_name = save_sourcing_name; ! sourcing_lnum = save_sourcing_lnum; return lp; } --- 578,584 ---- endOK: if (fd != NULL) fclose(fd); ! estack_pop(); return lp; } *** ../vim-8.2.0055/src/term.c 2019-12-07 17:34:32.000000000 +0100 --- src/term.c 2019-12-29 16:34:24.690127317 +0100 *************** *** 2277,2283 **** } #endif ! if (sourcing_name == NULL) { #ifdef HAVE_TGETENT if (error_msg != NULL) --- 2277,2283 ---- } #endif ! if (SOURCING_NAME == NULL) { #ifdef HAVE_TGETENT if (error_msg != NULL) *** ../vim-8.2.0055/src/testing.c 2019-12-23 22:59:14.264820697 +0100 --- src/testing.c 2019-12-29 20:31:46.756611485 +0100 *************** *** 21,42 **** static void prepare_assert_error(garray_T *gap) { ! char buf[NUMBUFLEN]; ga_init2(gap, 1, 100); ! if (sourcing_name != NULL) { ! ga_concat(gap, sourcing_name); ! if (sourcing_lnum > 0) ga_concat(gap, (char_u *)" "); } ! if (sourcing_lnum > 0) { ! sprintf(buf, "line %ld", (long)sourcing_lnum); ga_concat(gap, (char_u *)buf); } ! if (sourcing_name != NULL || sourcing_lnum > 0) ga_concat(gap, (char_u *)": "); } /* --- 21,44 ---- static void prepare_assert_error(garray_T *gap) { ! char buf[NUMBUFLEN]; ! char_u *sname = estack_sfile(); ga_init2(gap, 1, 100); ! if (sname != NULL) { ! ga_concat(gap, sname); ! if (SOURCING_LNUM > 0) ga_concat(gap, (char_u *)" "); } ! if (SOURCING_LNUM > 0) { ! sprintf(buf, "line %ld", (long)SOURCING_LNUM); ga_concat(gap, (char_u *)buf); } ! if (sname != NULL || SOURCING_LNUM > 0) ga_concat(gap, (char_u *)": "); + vim_free(sname); } /* *** ../vim-8.2.0055/src/usercmd.c 2019-12-29 13:56:28.692861883 +0100 --- src/usercmd.c 2019-12-29 16:43:13.271990339 +0100 *************** *** 191,197 **** { xp->xp_arg = uc->uc_compl_arg; xp->xp_script_ctx = uc->uc_script_ctx; ! xp->xp_script_ctx.sc_lnum += sourcing_lnum; } # endif // Do not search for further abbreviations --- 191,197 ---- { xp->xp_arg = uc->uc_compl_arg; xp->xp_script_ctx = uc->uc_script_ctx; ! xp->xp_script_ctx.sc_lnum += SOURCING_LNUM; } # endif // Do not search for further abbreviations *************** *** 956,962 **** cmd->uc_compl = compl; #ifdef FEAT_EVAL cmd->uc_script_ctx = current_sctx; ! cmd->uc_script_ctx.sc_lnum += sourcing_lnum; cmd->uc_compl_arg = compl_arg; #endif cmd->uc_addr_type = addr_type; --- 956,962 ---- cmd->uc_compl = compl; #ifdef FEAT_EVAL cmd->uc_script_ctx = current_sctx; ! cmd->uc_script_ctx.sc_lnum += SOURCING_LNUM; cmd->uc_compl_arg = compl_arg; #endif cmd->uc_addr_type = addr_type; *** ../vim-8.2.0055/src/userfunc.c 2019-12-25 15:03:56.526592324 +0100 --- src/userfunc.c 2019-12-29 19:44:28.321252384 +0100 *************** *** 226,231 **** --- 226,247 ---- 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,315 **** vim_strncpy(p + 7, s, e - s); fp->uf_refcount = 1; ! STRCPY(fp->uf_name, name); hash_add(&func_hashtab, UF2HIKEY(fp)); fp->uf_args = newargs; ga_init(&fp->uf_def_args); --- 325,331 ---- vim_strncpy(p + 7, s, e - s); fp->uf_refcount = 1; ! set_ufunc_name(fp, name); hash_add(&func_hashtab, UF2HIKEY(fp)); fp->uf_args = newargs; ga_init(&fp->uf_def_args); *************** *** 333,339 **** 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; pt->pt_func = fp; pt->pt_refcount = 1; --- 349,355 ---- 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; pt->pt_func = fp; pt->pt_refcount = 1; *************** *** 759,766 **** 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; --- 775,780 ---- *************** *** 774,780 **** int islambda = FALSE; char_u numbuf[NUMBUFLEN]; char_u *name; - size_t len; #ifdef FEAT_PROFILE proftime_T wait_start; proftime_T call_start; --- 788,793 ---- *************** *** 948,956 **** // 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) { --- 961,966 ---- *************** *** 958,1022 **** ++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) ! { ! 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) ! { ! 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 { ! // 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) ! { ! 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; } } #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) --- 968,1018 ---- ++sandbox; } ! estack_push_ufunc(ETYPE_UFUNC, fp, 1); ! if (p_verbose >= 12) ! { ! ++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) ! { ! 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) { ! 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); } } } ! 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,1093 **** verbose_enter_scroll(); if (aborting()) ! smsg(_("%s aborted"), sourcing_name); else if (fc->rettv->v_type == VAR_NUMBER) ! smsg(_("%s returning #%ld"), sourcing_name, (long)fc->rettv->vval.v_number); else { --- 1081,1089 ---- verbose_enter_scroll(); if (aborting()) ! smsg(_("%s aborted"), SOURCING_NAME); else if (fc->rettv->v_type == VAR_NUMBER) ! smsg(_("%s returning #%ld"), SOURCING_NAME, (long)fc->rettv->vval.v_number); else { *************** *** 1109,1115 **** trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); s = buf; } ! smsg(_("%s returning %s"), sourcing_name, s); vim_free(tofree); } } --- 1105,1111 ---- trunc_string(s, buf, MSG_BUF_CLEN, MSG_BUF_LEN); s = buf; } ! smsg(_("%s returning %s"), SOURCING_NAME, s); vim_free(tofree); } } *************** *** 1119,1127 **** --no_wait_return; } ! vim_free(sourcing_name); ! sourcing_name = save_sourcing_name; ! sourcing_lnum = save_sourcing_lnum; current_sctx = save_current_sctx; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) --- 1115,1121 ---- --no_wait_return; } ! estack_pop(); current_sctx = save_current_sctx; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) *************** *** 1130,1141 **** if (using_sandbox) --sandbox; ! if (p_verbose >= 12 && sourcing_name != NULL) { ++no_wait_return; verbose_enter_scroll(); ! smsg(_("continuing in %s"), sourcing_name); msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); --- 1124,1135 ---- if (using_sandbox) --sandbox; ! if (p_verbose >= 12 && SOURCING_NAME != NULL) { ++no_wait_return; verbose_enter_scroll(); ! smsg(_("continuing in %s"), SOURCING_NAME); msg_puts("\n"); // don't overwrite this either verbose_leave_scroll(); *************** *** 1204,1216 **** ga_clear_strings(&(fp->uf_args)); ga_clear_strings(&(fp->uf_def_args)); ga_clear_strings(&(fp->uf_lines)); #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; #endif } --- 1198,1208 ---- 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_CLEAR(fp->uf_tml_count); ! VIM_CLEAR(fp->uf_tml_total); ! VIM_CLEAR(fp->uf_tml_self); #endif } *************** *** 1736,1746 **** 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); ! } else msg_puts((char *)fp->uf_name); msg_putchar('('); --- 1728,1735 ---- if (indent) msg_puts(" "); msg_puts("function "); ! if (fp->uf_name_exp != NULL) ! msg_puts((char *)fp->uf_name_exp); else msg_puts((char *)fp->uf_name); msg_putchar('('); *************** *** 2308,2314 **** } // Save the starting line number. ! sourcing_lnum_top = sourcing_lnum; indent = 2; nesting = 0; --- 2297,2303 ---- } // Save the starting line number. ! sourcing_lnum_top = SOURCING_LNUM; indent = 2; nesting = 0; *************** *** 2351,2360 **** goto erret; } ! // 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; else sourcing_lnum_off = 0; --- 2340,2349 ---- goto erret; } ! // 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; else sourcing_lnum_off = 0; *************** *** 2631,2646 **** // Check that the autoload name matches the script name. j = FAIL; ! if (sourcing_name != NULL) { scriptname = autoload_name(name); if (scriptname != NULL) { p = vim_strchr(scriptname, '/'); plen = (int)STRLEN(p); ! slen = (int)STRLEN(sourcing_name); if (slen > plen && fnamecmp(p, ! sourcing_name + slen - plen) == 0) j = OK; vim_free(scriptname); } --- 2620,2635 ---- // Check that the autoload name matches the script name. j = FAIL; ! if (SOURCING_NAME != NULL) { scriptname = autoload_name(name); if (scriptname != NULL) { p = vim_strchr(scriptname, '/'); plen = (int)STRLEN(p); ! slen = (int)STRLEN(SOURCING_NAME); if (slen > plen && fnamecmp(p, ! SOURCING_NAME + slen - plen) == 0) j = OK; vim_free(scriptname); } *************** *** 2685,2691 **** } // insert the new function in the function list ! STRCPY(fp->uf_name, name); if (overwrite) { hi = hash_find(&func_hashtab, name); --- 2674,2680 ---- } // insert the new function in the function list ! set_ufunc_name(fp, name); if (overwrite) { hi = hash_find(&func_hashtab, name); *************** *** 3353,3359 **** if (fcp->dbg_tick != debug_tick) { fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, ! sourcing_lnum); fcp->dbg_tick = debug_tick; } #ifdef FEAT_PROFILE --- 3342,3348 ---- if (fcp->dbg_tick != debug_tick) { fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, ! SOURCING_LNUM); fcp->dbg_tick = debug_tick; } #ifdef FEAT_PROFILE *************** *** 3376,3382 **** else { retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); ! sourcing_lnum = fcp->linenr; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) func_line_start(cookie); --- 3365,3371 ---- else { retval = vim_strsave(((char_u **)(gap->ga_data))[fcp->linenr++]); ! SOURCING_LNUM = fcp->linenr; #ifdef FEAT_PROFILE if (do_profiling == PROF_YES) func_line_start(cookie); *************** *** 3385,3396 **** } // Did we encounter a breakpoint? ! if (fcp->breakpoint != 0 && fcp->breakpoint <= sourcing_lnum) { ! dbg_breakpoint(fp->uf_name, sourcing_lnum); // Find next breakpoint. fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, ! sourcing_lnum); fcp->dbg_tick = debug_tick; } --- 3374,3385 ---- } // Did we encounter a breakpoint? ! if (fcp->breakpoint != 0 && fcp->breakpoint <= SOURCING_LNUM) { ! dbg_breakpoint(fp->uf_name, SOURCING_LNUM); // Find next breakpoint. fcp->breakpoint = dbg_find_breakpoint(FALSE, fp->uf_name, ! SOURCING_LNUM); fcp->dbg_tick = debug_tick; } *** ../vim-8.2.0055/src/kword_test.c 2019-12-04 21:41:40.000000000 +0100 --- src/kword_test.c 2019-12-29 16:50:21.846266344 +0100 *************** *** 76,81 **** --- 76,82 ---- int main(void) { + estack_init(); test_isword_funcs_utf8(); return 0; } *** ../vim-8.2.0055/src/testdir/test_debugger.vim 2019-08-07 22:51:41.000000000 +0200 --- src/testdir/test_debugger.vim 2019-12-29 21:00:41.864006715 +0100 *************** *** 14,20 **** " 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))}) let lnum += 1 endfor endif --- 14,20 ---- " 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))}, 200) let lnum += 1 endfor endif *** ../vim-8.2.0055/src/version.c 2019-12-29 15:19:00.470760367 +0100 --- src/version.c 2019-12-29 22:58:51.211858220 +0100 *************** *** 744,745 **** --- 744,747 ---- { /* Add new patch number below this line */ + /**/ + 56, /**/ -- ARTHUR: Shut up! Will you shut up! DENNIS: Ah, now we see the violence inherent in the system. ARTHUR: Shut up! DENNIS: Oh! Come and see the violence inherent in the system! HELP! HELP! I'm being repressed! The Quest for the Holy Grail (Monty Python) /// Bram Moolenaar -- Bram@Moolenaar.net -- http://www.Moolenaar.net \\\ /// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\ \\\ an exciting new programming language -- http://www.Zimbu.org /// \\\ help me help AIDS victims -- http://ICCF-Holland.org ///