Patch 8.2.4749

6 views
Skip to first unread message

Bram Moolenaar

unread,
Apr 14, 2022, 10:40:34 AM4/14/22
to vim...@googlegroups.com

Patch 8.2.4749
Problem: <script> is not expanded in autocmd context.
Solution: Add the context to the pattern struct. (closes #10144)
Rename AutoPatCmd to AutoPatCmd_T.
Files: src/autocmd.c, src/proto/autocmd.pro, src/scriptfile.c,
src/structs.h, src/testdir/test_expand.vim


*** ../vim-8.2.4748/src/autocmd.c 2022-04-09 18:17:30.060746546 +0100
--- src/autocmd.c 2022-04-14 15:35:58.641829848 +0100
***************
*** 55,61 ****
char once; // "One shot": removed after execution
char nested; // If autocommands nest here.
char last; // last command in list
! sctx_T script_ctx; // script context where defined
struct AutoCmd *next; // next AutoCmd in list
} AutoCmd;

--- 55,61 ----
char once; // "One shot": removed after execution
char nested; // If autocommands nest here.
char last; // last command in list
! sctx_T script_ctx; // script context where it is defined
struct AutoCmd *next; // next AutoCmd in list
} AutoCmd;

***************
*** 234,245 ****
char_u *sfname; // sfname to match with
char_u *tail; // tail of fname
event_T event; // current event
int arg_bufnr; // Initially equal to <abuf>, 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

// Macro to loop over all the patterns for an autocmd event
#define FOR_ALL_AUTOCMD_PATTERNS(event, ap) \
--- 234,246 ----
char_u *sfname; // sfname to match with
char_u *tail; // tail of fname
event_T event; // current event
+ sctx_T script_ctx; // script context where it is defined
int arg_bufnr; // Initially equal to <abuf>, set to zero when
// buf is deleted.
! AutoPatCmd_T *next; // chain of active apc-s for auto-invalidation
};

! static AutoPatCmd_T *active_apc_list = NULL; // stack of active autocommands

// Macro to loop over all the patterns for an autocmd event
#define FOR_ALL_AUTOCMD_PATTERNS(event, ap) \
***************
*** 264,270 ****
static int au_get_grouparg(char_u **argp);
static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group, int flags);
static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
! static void auto_next_pat(AutoPatCmd *apc, int stop_at_last);
static int au_find_group(char_u *name);

static event_T last_event;
--- 265,271 ----
static int au_get_grouparg(char_u **argp);
static int do_autocmd_event(event_T event, char_u *pat, int once, int nested, char_u *cmd, int forceit, int group, int flags);
static int apply_autocmds_group(event_T event, char_u *fname, char_u *fname_io, int force, int group, buf_T *buf, exarg_T *eap);
! static void auto_next_pat(AutoPatCmd_T *apc, int stop_at_last);
static int au_find_group(char_u *name);

static event_T last_event;
***************
*** 453,461 ****
void
aubuflocal_remove(buf_T *buf)
{
! AutoPat *ap;
! event_T event;
! AutoPatCmd *apc;

// invalidate currently executing autocommands
for (apc = active_apc_list; apc; apc = apc->next)
--- 454,462 ----
void
aubuflocal_remove(buf_T *buf)
{
! AutoPat *ap;
! event_T event;
! AutoPatCmd_T *apc;

// invalidate currently executing autocommands
for (apc = active_apc_list; apc; apc = apc->next)
***************
*** 1914,1920 ****
int save_autocmd_busy;
int save_autocmd_nested;
static int nesting = 0;
! AutoPatCmd patcmd;
AutoPat *ap;
sctx_T save_current_sctx;
#ifdef FEAT_EVAL
--- 1915,1921 ----
int save_autocmd_busy;
int save_autocmd_nested;
static int nesting = 0;
! AutoPatCmd_T patcmd;
AutoPat *ap;
sctx_T save_current_sctx;
#ifdef FEAT_EVAL
***************
*** 2173,2187 ****
tail = gettail(fname);

// Find first autocommand that matches
patcmd.curpat = first_autopat[(int)event];
- patcmd.nextcmd = NULL;
patcmd.group = group;
patcmd.fname = fname;
patcmd.sfname = sfname;
patcmd.tail = tail;
patcmd.event = event;
patcmd.arg_bufnr = autocmd_bufnr;
- patcmd.next = NULL;
auto_next_pat(&patcmd, FALSE);

// found one, start executing the autocommands
--- 2174,2187 ----
tail = gettail(fname);

// Find first autocommand that matches
+ CLEAR_FIELD(patcmd);
patcmd.curpat = first_autopat[(int)event];
patcmd.group = group;
patcmd.fname = fname;
patcmd.sfname = sfname;
patcmd.tail = tail;
patcmd.event = event;
patcmd.arg_bufnr = autocmd_bufnr;
auto_next_pat(&patcmd, FALSE);

// found one, start executing the autocommands
***************
*** 2363,2378 ****
*/
static void
auto_next_pat(
! AutoPatCmd *apc,
int stop_at_last) // stop when 'last' flag is set
{
AutoPat *ap;
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)
{
--- 2363,2383 ----
*/
static void
auto_next_pat(
! AutoPatCmd_T *apc,
int stop_at_last) // stop when 'last' flag is set
{
AutoPat *ap;
AutoCmd *cp;
char_u *name;
char *s;
! estack_T *entry;
! char_u *namep;
!
! entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;

! // Clear the exestack entry for this ETYPE_AUCMD entry.
! VIM_CLEAR(entry->es_name);
! entry->es_info.aucmd = NULL;

for (ap = apc->curpat; ap != NULL && !got_int; ap = ap->next)
{
***************
*** 2392,2411 ****
{
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();
}
}

apc->curpat = ap;
apc->nextcmd = ap->cmds;
// mark last command
--- 2397,2418 ----
{
name = event_nr2name(apc->event);
s = _("%s Autocommands for \"%s\"");
! namep = alloc(STRLEN(s) + STRLEN(name) + ap->patlen + 1);
! if (namep != NULL)
{
! sprintf((char *)namep, s, (char *)name, (char *)ap->pat);
if (p_verbose >= 8)
{
verbose_enter();
! smsg(_("Executing %s"), namep);
verbose_leave();
}
}

+ // Update the exestack entry for this autocmd.
+ entry->es_name = namep;
+ entry->es_info.aucmd = apc;
+
apc->curpat = ap;
apc->nextcmd = ap->cmds;
// mark last command
***************
*** 2423,2428 ****
--- 2430,2444 ----
}

/*
+ * Get the script context where autocommand "acp" is defined.
+ */
+ sctx_T *
+ acp_script_ctx(AutoPatCmd_T *acp)
+ {
+ return &acp->script_ctx;
+ }
+
+ /*
* Get next autocommand command.
* Called by do_cmdline() to get the next line for ":if".
* Returns allocated string, or NULL for end of autocommands.
***************
*** 2434,2440 ****
int indent UNUSED,
getline_opt_T options UNUSED)
{
! AutoPatCmd *acp = (AutoPatCmd *)cookie;
char_u *retval;
AutoCmd *ac;

--- 2450,2456 ----
int indent UNUSED,
getline_opt_T options UNUSED)
{
! AutoPatCmd_T *acp = (AutoPatCmd_T *)cookie;
char_u *retval;
AutoCmd *ac;

***************
*** 2481,2486 ****
--- 2497,2503 ----
au_del_cmd(ac);
autocmd_nested = ac->nested;
current_sctx = ac->script_ctx;
+ acp->script_ctx = current_sctx;
if (ac->last)
acp->nextcmd = NULL;
else
*** ../vim-8.2.4748/src/proto/autocmd.pro 2022-04-08 15:17:53.067952553 +0100
--- src/proto/autocmd.pro 2022-04-14 15:36:36.865820601 +0100
***************
*** 7,13 ****
char_u *au_event_disable(char *what);
void au_event_restore(char_u *old_ei);
void do_autocmd(exarg_T *eap, char_u *arg_in, int forceit);
! int do_doautocmd(char_u *arg, int do_msg, int *did_something);
void ex_doautoall(exarg_T *eap);
int check_nomodeline(char_u **argp);
void aucmd_prepbuf(aco_save_T *aco, buf_T *buf);
--- 7,13 ----
char_u *au_event_disable(char *what);
void au_event_restore(char_u *old_ei);
void do_autocmd(exarg_T *eap, char_u *arg_in, int forceit);
! int do_doautocmd(char_u *arg_start, int do_msg, int *did_something);
void ex_doautoall(exarg_T *eap);
int check_nomodeline(char_u **argp);
void aucmd_prepbuf(aco_save_T *aco, buf_T *buf);
***************
*** 16,21 ****
--- 16,22 ----
int apply_autocmds_exarg(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, exarg_T *eap);
int apply_autocmds_retval(event_T event, char_u *fname, char_u *fname_io, int force, buf_T *buf, int *retval);
int trigger_cursorhold(void);
+ int has_winscrolled(void);
int has_cursormoved(void);
int has_cursormovedI(void);
int has_textchanged(void);
***************
*** 26,35 ****
int has_textyankpost(void);
int has_completechanged(void);
int has_modechanged(void);
- int has_winscrolled(void);
void block_autocmds(void);
void unblock_autocmds(void);
int is_autocmd_blocked(void);
char_u *getnextac(int c, void *cookie, int indent, getline_opt_T options);
int has_autocmd(event_T event, char_u *sfname, buf_T *buf);
char_u *get_augroup_name(expand_T *xp, int idx);
--- 27,36 ----
int has_textyankpost(void);
int has_completechanged(void);
int has_modechanged(void);
void block_autocmds(void);
void unblock_autocmds(void);
int is_autocmd_blocked(void);
+ sctx_T *acp_script_ctx(AutoPatCmd_T *acp);
char_u *getnextac(int c, void *cookie, int indent, getline_opt_T options);
int has_autocmd(event_T event, char_u *sfname, buf_T *buf);
char_u *get_augroup_name(expand_T *xp, int idx);
*** ../vim-8.2.4748/src/scriptfile.c 2022-04-14 12:58:19.604895030 +0100
--- src/scriptfile.c 2022-04-14 15:29:19.265779919 +0100
***************
*** 157,183 ****
return NULL;
}

! // If evaluated in a function return the path of the script where the
! // function is defined, at script level the current script path is returned
// instead.
if (which == ESTACK_SCRIPT)
{
! if (entry->es_type == ETYPE_UFUNC)
{
! sctx_T *def_ctx = &entry->es_info.ufunc->uf_script_ctx;

! if (def_ctx->sc_sid > 0)
! return vim_strsave(SCRIPT_ITEM(def_ctx->sc_sid)->sn_name);
! }
! else if (exestack.ga_len > 0)
! {
! // Walk the stack backwards, starting from the current frame.
! for (idx = exestack.ga_len - 1; idx; --idx)
{
! entry = ((estack_T *)exestack.ga_data) + idx;

! if (entry->es_type == ETYPE_SCRIPT)
! return vim_strsave(entry->es_name);
}
}
return NULL;
--- 157,192 ----
return NULL;
}

! // If evaluated in a function or autocommand, return the path of the script
! // where it is defined, at script level the current script path is returned
// instead.
if (which == ESTACK_SCRIPT)
{
! entry = ((estack_T *)exestack.ga_data) + exestack.ga_len - 1;
! // Walk the stack backwards, starting from the current frame.
! for (idx = exestack.ga_len - 1; idx >= 0; --idx, --entry)
{
! if (entry->es_type == ETYPE_UFUNC)
! {
! sctx_T *def_ctx = &entry->es_info.ufunc->uf_script_ctx;

! if (def_ctx->sc_sid > 0)
! return vim_strsave(SCRIPT_ITEM(def_ctx->sc_sid)->sn_name);
! else
! return NULL;
! }
! else if (entry->es_type == ETYPE_AUCMD)
{
! sctx_T *def_ctx = acp_script_ctx(entry->es_info.aucmd);

! if (def_ctx->sc_sid > 0)
! return vim_strsave(SCRIPT_ITEM(def_ctx->sc_sid)->sn_name);
! else
! return NULL;
! }
! else if (entry->es_type == ETYPE_SCRIPT)
! {
! return vim_strsave(entry->es_name);
}
}
return NULL;
*** ../vim-8.2.4748/src/structs.h 2022-04-12 14:22:46.890838165 +0100
--- src/structs.h 2022-04-14 15:36:19.653824975 +0100
***************
*** 2073,2079 ****
dict_T *pt_dict; // dict for "self"
};

! typedef struct AutoPatCmd_S AutoPatCmd;

/*
* Entry in the execution stack "exestack".
--- 2073,2079 ----
dict_T *pt_dict; // dict for "self"
};

! typedef struct AutoPatCmd_S AutoPatCmd_T;

/*
* Entry in the execution stack "exestack".
***************
*** 2100,2106 ****
#if defined(FEAT_EVAL)
ufunc_T *ufunc; // function info
#endif
! AutoPatCmd *aucmd; // autocommand info
except_T *except; // exception info
} es_info;
#if defined(FEAT_EVAL)
--- 2100,2106 ----
#if defined(FEAT_EVAL)
ufunc_T *ufunc; // function info
#endif
! AutoPatCmd_T *aucmd; // autocommand info
except_T *except; // exception info
} es_info;
#if defined(FEAT_EVAL)
*** ../vim-8.2.4748/src/testdir/test_expand.vim 2022-04-12 12:54:06.917010952 +0100
--- src/testdir/test_expand.vim 2022-04-14 15:29:19.265779919 +0100
***************
*** 169,211 ****

func Test_expand_script_source()
let lines0 =<< trim [SCRIPT]
! let g:script_level[0] = expand('<script>:t')
so Xscript1
func F0()
! let g:func_level[0] = expand('<script>:t')
endfunc
[SCRIPT]

let lines1 =<< trim [SCRIPT]
! let g:script_level[1] = expand('<script>:t')
so Xscript2
func F1()
! let g:func_level[1] = expand('<script>:t')
endfunc
[SCRIPT]

let lines2 =<< trim [SCRIPT]
! let g:script_level[2] = expand('<script>:t')
func F2()
! let g:func_level[2] = expand('<script>:t')
endfunc
[SCRIPT]

call writefile(lines0, 'Xscript0')
call writefile(lines1, 'Xscript1')
call writefile(lines2, 'Xscript2')

! " Check the expansion of <script> at script and function level.
! let g:script_level = ['', '', '']
! let g:func_level = ['', '', '']

so Xscript0
call F0()
call F1()
call F2()

call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:script_level)
call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:func_level)

unlet g:script_level g:func_level
delfunc F0
--- 169,220 ----

func Test_expand_script_source()
let lines0 =<< trim [SCRIPT]
! call extend(g:script_level, [expand('<script>:t')])
so Xscript1
func F0()
! call extend(g:func_level, [expand('<script>:t')])
endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
[SCRIPT]

let lines1 =<< trim [SCRIPT]
! call extend(g:script_level, [expand('<script>:t')])
so Xscript2
func F1()
! call extend(g:func_level, [expand('<script>:t')])
endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
[SCRIPT]

let lines2 =<< trim [SCRIPT]
! call extend(g:script_level, [expand('<script>:t')])
func F2()
! call extend(g:func_level, [expand('<script>:t')])
endfunc
+
+ au User * call extend(g:au_level, [expand('<script>:t')])
[SCRIPT]

call writefile(lines0, 'Xscript0')
call writefile(lines1, 'Xscript1')
call writefile(lines2, 'Xscript2')

! " Check the expansion of <script> at different levels.
! let g:script_level = []
! let g:func_level = []
! let g:au_level = []

so Xscript0
call F0()
call F1()
call F2()
+ doautocmd User

call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:script_level)
call assert_equal(['Xscript0', 'Xscript1', 'Xscript2'], g:func_level)
+ call assert_equal(['Xscript2', 'Xscript1', 'Xscript0'], g:au_level)

unlet g:script_level g:func_level
delfunc F0
*** ../vim-8.2.4748/src/version.c 2022-04-14 12:58:19.608895029 +0100
--- src/version.c 2022-04-14 15:30:35.345815517 +0100
***************
*** 748,749 ****
--- 748,751 ----
{ /* Add new patch number below this line */
+ /**/
+ 4749,
/**/

--
If the Universe is constantly expanding, why can't I ever find a parking space?

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
Reply all
Reply to author
Forward
0 new messages