Skip to content

Commit 1a47ae3

Browse files
committed
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.
1 parent 257a396 commit 1a47ae3

23 files changed

+385
-240
lines changed

src/autocmd.c

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ static AutoPat *last_autopat[NUM_EVENTS] =
218218
/*
219219
* struct used to keep status while executing autocommands for an event.
220220
*/
221-
typedef struct AutoPatCmd
221+
struct AutoPatCmd_S
222222
{
223223
AutoPat *curpat; // next AutoPat to examine
224224
AutoCmd *nextcmd; // next AutoCmd to execute
@@ -229,8 +229,8 @@ typedef struct AutoPatCmd
229229
event_T event; // current event
230230
int arg_bufnr; // Initially equal to <abuf>, set to zero when
231231
// buf is deleted.
232-
struct AutoPatCmd *next; // chain of active apc-s for auto-invalidation
233-
} AutoPatCmd;
232+
AutoPatCmd *next; // chain of active apc-s for auto-invalidation
233+
};
234234

235235
static AutoPatCmd *active_apc_list = NULL; // stack of active autocommands
236236

@@ -1242,7 +1242,7 @@ do_autocmd_event(
12421242
ac->cmd = vim_strsave(cmd);
12431243
#ifdef FEAT_EVAL
12441244
ac->script_ctx = current_sctx;
1245-
ac->script_ctx.sc_lnum += sourcing_lnum;
1245+
ac->script_ctx.sc_lnum += SOURCING_LNUM;
12461246
#endif
12471247
if (ac->cmd == NULL)
12481248
{
@@ -1805,8 +1805,6 @@ apply_autocmds_group(
18051805
int save_changed;
18061806
buf_T *old_curbuf;
18071807
int retval = FALSE;
1808-
char_u *save_sourcing_name;
1809-
linenr_T save_sourcing_lnum;
18101808
char_u *save_autocmd_fname;
18111809
int save_autocmd_fname_full;
18121810
int save_autocmd_bufnr;
@@ -2020,10 +2018,9 @@ apply_autocmds_group(
20202018

20212019
// Don't redraw while doing autocommands.
20222020
++RedrawingDisabled;
2023-
save_sourcing_name = sourcing_name;
2024-
sourcing_name = NULL; // don't free this one
2025-
save_sourcing_lnum = sourcing_lnum;
2026-
sourcing_lnum = 0; // no line number here
2021+
2022+
// name and lnum are filled in later
2023+
estack_push(ETYPE_AUCMD, NULL, 0);
20272024

20282025
#ifdef FEAT_EVAL
20292026
save_current_sctx = current_sctx;
@@ -2126,9 +2123,8 @@ apply_autocmds_group(
21262123
autocmd_busy = save_autocmd_busy;
21272124
filechangeshell_busy = FALSE;
21282125
autocmd_nested = save_autocmd_nested;
2129-
vim_free(sourcing_name);
2130-
sourcing_name = save_sourcing_name;
2131-
sourcing_lnum = save_sourcing_lnum;
2126+
vim_free(SOURCING_NAME);
2127+
estack_pop();
21322128
vim_free(autocmd_fname);
21332129
autocmd_fname = save_autocmd_fname;
21342130
autocmd_fname_full = save_autocmd_fname_full;
@@ -2256,8 +2252,9 @@ auto_next_pat(
22562252
AutoCmd *cp;
22572253
char_u *name;
22582254
char *s;
2255+
char_u **sourcing_namep = &SOURCING_NAME;
22592256

2260-
VIM_CLEAR(sourcing_name);
2257+
VIM_CLEAR(*sourcing_namep);
22612258

22622259
for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
22632260
{
@@ -2277,16 +2274,16 @@ auto_next_pat(
22772274
{
22782275
name = event_nr2name(apc->event);
22792276
s = _("%s Autocommands for \"%s\"");
2280-
sourcing_name = alloc(STRLEN(s)
2277+
*sourcing_namep = alloc(STRLEN(s)
22812278
+ STRLEN(name) + ap->patlen + 1);
2282-
if (sourcing_name != NULL)
2279+
if (*sourcing_namep != NULL)
22832280
{
2284-
sprintf((char *)sourcing_name, s,
2281+
sprintf((char *)*sourcing_namep, s,
22852282
(char *)name, (char *)ap->pat);
22862283
if (p_verbose >= 8)
22872284
{
22882285
verbose_enter();
2289-
smsg(_("Executing %s"), sourcing_name);
2286+
smsg(_("Executing %s"), *sourcing_namep);
22902287
verbose_leave();
22912288
}
22922289
}

src/buffer.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5279,8 +5279,6 @@ chk_modeline(
52795279
int vers;
52805280
int end;
52815281
int retval = OK;
5282-
char_u *save_sourcing_name;
5283-
linenr_T save_sourcing_lnum;
52845282
#ifdef FEAT_EVAL
52855283
sctx_T save_current_sctx;
52865284
#endif
@@ -5325,10 +5323,8 @@ chk_modeline(
53255323
if (linecopy == NULL)
53265324
return FAIL;
53275325

5328-
save_sourcing_lnum = sourcing_lnum;
5329-
save_sourcing_name = sourcing_name;
5330-
sourcing_lnum = lnum; // prepare for emsg()
5331-
sourcing_name = (char_u *)"modelines";
5326+
// prepare for emsg()
5327+
estack_push(ETYPE_MODELINE, (char_u *)"modelines", lnum);
53325328

53335329
end = FALSE;
53345330
while (end == FALSE)
@@ -5371,7 +5367,7 @@ chk_modeline(
53715367
save_current_sctx = current_sctx;
53725368
current_sctx.sc_sid = SID_MODELINE;
53735369
current_sctx.sc_seq = 0;
5374-
current_sctx.sc_lnum = 0;
5370+
current_sctx.sc_lnum = lnum;
53755371
current_sctx.sc_version = 1;
53765372
#endif
53775373
// Make sure no risky things are executed as a side effect.
@@ -5389,9 +5385,7 @@ chk_modeline(
53895385
s = e + 1; // advance to next part
53905386
}
53915387

5392-
sourcing_lnum = save_sourcing_lnum;
5393-
sourcing_name = save_sourcing_name;
5394-
5388+
estack_pop();
53955389
vim_free(linecopy);
53965390
}
53975391
return retval;

src/debugger.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ do_debug(char_u *cmd)
5151
int n;
5252
char_u *cmdline = NULL;
5353
char_u *p;
54+
char_u *sname;
5455
char *tail = NULL;
5556
static int last_cmd = 0;
5657
#define CMD_CONT 1
@@ -104,10 +105,12 @@ do_debug(char_u *cmd)
104105
vim_free(debug_newval);
105106
debug_newval = NULL;
106107
}
107-
if (sourcing_name != NULL)
108-
msg((char *)sourcing_name);
109-
if (sourcing_lnum != 0)
110-
smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd);
108+
sname = estack_sfile();
109+
if (sname != NULL)
110+
msg((char *)sname);
111+
vim_free(sname);
112+
if (SOURCING_LNUM != 0)
113+
smsg(_("line %ld: %s"), SOURCING_LNUM, cmd);
111114
else
112115
smsg(_("cmd: %s"), cmd);
113116

@@ -300,14 +303,14 @@ do_debug(char_u *cmd)
300303
}
301304

302305
static int
303-
get_maxbacktrace_level(void)
306+
get_maxbacktrace_level(char_u *sname)
304307
{
305308
char *p, *q;
306309
int maxbacktrace = 0;
307310

308-
if (sourcing_name != NULL)
311+
if (sname != NULL)
309312
{
310-
p = (char *)sourcing_name;
313+
p = (char *)sname;
311314
while ((q = strstr(p, "..")) != NULL)
312315
{
313316
p = q + 2;
@@ -341,27 +344,32 @@ do_checkbacktracelevel(void)
341344
}
342345
else
343346
{
344-
int max = get_maxbacktrace_level();
347+
char_u *sname = estack_sfile();
348+
int max = get_maxbacktrace_level(sname);
345349

346350
if (debug_backtrace_level > max)
347351
{
348352
debug_backtrace_level = max;
349353
smsg(_("frame at highest level: %d"), max);
350354
}
355+
vim_free(sname);
351356
}
352357
}
353358

354359
static void
355360
do_showbacktrace(char_u *cmd)
356361
{
362+
char_u *sname;
357363
char *cur;
358364
char *next;
359365
int i = 0;
360-
int max = get_maxbacktrace_level();
366+
int max;
361367

362-
if (sourcing_name != NULL)
368+
sname = estack_sfile();
369+
max = get_maxbacktrace_level(sname);
370+
if (sname != NULL)
363371
{
364-
cur = (char *)sourcing_name;
372+
cur = (char *)sname;
365373
while (!got_int)
366374
{
367375
next = strstr(cur, "..");
@@ -377,9 +385,11 @@ do_showbacktrace(char_u *cmd)
377385
*next = '.';
378386
cur = next + 2;
379387
}
388+
vim_free(sname);
380389
}
381-
if (sourcing_lnum != 0)
382-
smsg(_("line %ld: %s"), (long)sourcing_lnum, cmd);
390+
391+
if (SOURCING_LNUM != 0)
392+
smsg(_("line %ld: %s"), (long)SOURCING_LNUM, cmd);
383393
else
384394
smsg(_("cmd: %s"), cmd);
385395
}

src/ex_docmd.c

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ do_cmdline(
703703
}
704704
else if (getline_equal(fgetline, cookie, getsourceline))
705705
{
706-
fname = sourcing_name;
706+
fname = SOURCING_NAME;
707707
breakpoint = source_breakpoint(real_cookie);
708708
dbg_tick = source_dbg_tick(real_cookie);
709709
}
@@ -819,22 +819,22 @@ do_cmdline(
819819
{
820820
*breakpoint = dbg_find_breakpoint(
821821
getline_equal(fgetline, cookie, getsourceline),
822-
fname, sourcing_lnum);
822+
fname, SOURCING_LNUM);
823823
*dbg_tick = debug_tick;
824824
}
825825

826826
next_cmdline = ((wcmd_T *)(lines_ga.ga_data))[current_line].line;
827-
sourcing_lnum = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
827+
SOURCING_LNUM = ((wcmd_T *)(lines_ga.ga_data))[current_line].lnum;
828828

829829
// Did we encounter a breakpoint?
830830
if (breakpoint != NULL && *breakpoint != 0
831-
&& *breakpoint <= sourcing_lnum)
831+
&& *breakpoint <= SOURCING_LNUM)
832832
{
833-
dbg_breakpoint(fname, sourcing_lnum);
833+
dbg_breakpoint(fname, SOURCING_LNUM);
834834
// Find next breakpoint.
835835
*breakpoint = dbg_find_breakpoint(
836836
getline_equal(fgetline, cookie, getsourceline),
837-
fname, sourcing_lnum);
837+
fname, SOURCING_LNUM);
838838
*dbg_tick = debug_tick;
839839
}
840840
# ifdef FEAT_PROFILE
@@ -963,8 +963,8 @@ do_cmdline(
963963
}
964964
}
965965

966-
if (p_verbose >= 15 && sourcing_name != NULL)
967-
msg_verbose_cmd(sourcing_lnum, cmdline_copy);
966+
if (p_verbose >= 15 && SOURCING_NAME != NULL)
967+
msg_verbose_cmd(SOURCING_LNUM, cmdline_copy);
968968

969969
/*
970970
* 2. Execute one '|' separated command.
@@ -1081,7 +1081,7 @@ do_cmdline(
10811081
// Check for the next breakpoint after a watchexpression
10821082
if (breakpoint != NULL && has_watchexpr())
10831083
{
1084-
*breakpoint = dbg_find_breakpoint(FALSE, fname, sourcing_lnum);
1084+
*breakpoint = dbg_find_breakpoint(FALSE, fname, SOURCING_LNUM);
10851085
*dbg_tick = debug_tick;
10861086
}
10871087

@@ -1092,7 +1092,7 @@ do_cmdline(
10921092
{
10931093
if (lines_ga.ga_len > 0)
10941094
{
1095-
sourcing_lnum =
1095+
SOURCING_LNUM =
10961096
((wcmd_T *)lines_ga.ga_data)[lines_ga.ga_len - 1].lnum;
10971097
free_cmdlines(&lines_ga);
10981098
}
@@ -1234,8 +1234,6 @@ do_cmdline(
12341234
if (did_throw)
12351235
{
12361236
void *p = NULL;
1237-
char_u *saved_sourcing_name;
1238-
int saved_sourcing_lnum;
12391237
struct msglist *messages = NULL, *next;
12401238

12411239
/*
@@ -1260,10 +1258,8 @@ do_cmdline(
12601258
break;
12611259
}
12621260

1263-
saved_sourcing_name = sourcing_name;
1264-
saved_sourcing_lnum = sourcing_lnum;
1265-
sourcing_name = current_exception->throw_name;
1266-
sourcing_lnum = current_exception->throw_lnum;
1261+
estack_push(ETYPE_EXCEPT, current_exception->throw_name,
1262+
current_exception->throw_lnum);
12671263
current_exception->throw_name = NULL;
12681264

12691265
discard_current_exception(); // uses IObuff if 'verbose'
@@ -1287,9 +1283,8 @@ do_cmdline(
12871283
emsg(p);
12881284
vim_free(p);
12891285
}
1290-
vim_free(sourcing_name);
1291-
sourcing_name = saved_sourcing_name;
1292-
sourcing_lnum = saved_sourcing_lnum;
1286+
vim_free(SOURCING_NAME);
1287+
estack_pop();
12931288
}
12941289

12951290
/*
@@ -1428,7 +1423,7 @@ get_loop_line(int c, void *cookie, int indent, int do_concat)
14281423
KeyTyped = FALSE;
14291424
++cp->current_line;
14301425
wp = (wcmd_T *)(cp->lines_gap->ga_data) + cp->current_line;
1431-
sourcing_lnum = wp->lnum;
1426+
SOURCING_LNUM = wp->lnum;
14321427
return vim_strsave(wp->line);
14331428
}
14341429

@@ -1441,7 +1436,7 @@ store_loop_line(garray_T *gap, char_u *line)
14411436
if (ga_grow(gap, 1) == FAIL)
14421437
return FAIL;
14431438
((wcmd_T *)(gap->ga_data))[gap->ga_len].line = vim_strsave(line);
1444-
((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = sourcing_lnum;
1439+
((wcmd_T *)(gap->ga_data))[gap->ga_len].lnum = SOURCING_LNUM;
14451440
++gap->ga_len;
14461441
return OK;
14471442
}
@@ -8171,33 +8166,34 @@ eval_vars(
81718166
break;
81728167

81738168
case SPEC_SFILE: // file name for ":so" command
8174-
result = sourcing_name;
8169+
result = estack_sfile();
81758170
if (result == NULL)
81768171
{
81778172
*errormsg = _("E498: no :source file name to substitute for \"<sfile>\"");
81788173
return NULL;
81798174
}
8175+
resultbuf = result; // remember allocated string
81808176
break;
81818177

81828178
case SPEC_SLNUM: // line in file for ":so" command
8183-
if (sourcing_name == NULL || sourcing_lnum == 0)
8179+
if (SOURCING_NAME == NULL || SOURCING_LNUM == 0)
81848180
{
81858181
*errormsg = _("E842: no line number to use for \"<slnum>\"");
81868182
return NULL;
81878183
}
8188-
sprintf((char *)strbuf, "%ld", (long)sourcing_lnum);
8184+
sprintf((char *)strbuf, "%ld", SOURCING_LNUM);
81898185
result = strbuf;
81908186
break;
81918187

81928188
#ifdef FEAT_EVAL
81938189
case SPEC_SFLNUM: // line in script file
8194-
if (current_sctx.sc_lnum + sourcing_lnum == 0)
8190+
if (current_sctx.sc_lnum + SOURCING_LNUM == 0)
81958191
{
81968192
*errormsg = _("E961: no line number to use for \"<sflnum>\"");
81978193
return NULL;
81988194
}
81998195
sprintf((char *)strbuf, "%ld",
8200-
(long)(current_sctx.sc_lnum + sourcing_lnum));
8196+
(long)(current_sctx.sc_lnum + SOURCING_LNUM));
82018197
result = strbuf;
82028198
break;
82038199
#endif

0 commit comments

Comments
 (0)