# HG changeset patch # User Bram Moolenaar # Date 1610400606 -3600 # Node ID dc3b7a31c29f76ea57265d0cc4862cf5908e957c # Parent 4569ede6f294a5e881d013024f9d5637c9b5c3a2 patch 8.2.2332: Vim9: missing :endif not reported when using :windo Commit: https://github.com/vim/vim/commit/9567efa1b4a41baca9b2266f5903d5dda7ad1e88 Author: Bram Moolenaar Date: Mon Jan 11 22:16:30 2021 +0100 patch 8.2.2332: Vim9: missing :endif not reported when using :windo Problem: Vim9: missing :endif not reported when using :windo. Solution: Pass a getline function to do_cmdline(). (closes https://github.com/vim/vim/issues/7650) diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1019,30 +1019,6 @@ ex_options( /* * ":source" and associated commands. */ -/* - * Structure used to store info for each sourced file. - * It is shared between do_source() and getsourceline(). - * This is required, because it needs to be handed to do_cmdline() and - * sourcing can be done recursively. - */ -struct source_cookie -{ - FILE *fp; // opened file for sourcing - char_u *nextline; // if not NULL: line that was read ahead - linenr_T sourcing_lnum; // line number of the source file - int finished; // ":finish" used -#ifdef USE_CRNL - int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS - int error; // TRUE if LF found after CR-LF -#endif -#ifdef FEAT_EVAL - linenr_T breakpoint; // next line with breakpoint or zero - char_u *fname; // name of sourced file - int dbg_tick; // debug_tick when breakpoint was set - int level; // top nesting level of sourced file -#endif - vimconv_T conv; // type of conversion -}; #ifdef FEAT_EVAL /* @@ -1051,7 +1027,7 @@ struct source_cookie linenr_T * source_breakpoint(void *cookie) { - return &((struct source_cookie *)cookie)->breakpoint; + return &((source_cookie_T *)cookie)->breakpoint; } /* @@ -1060,7 +1036,7 @@ source_breakpoint(void *cookie) int * source_dbg_tick(void *cookie) { - return &((struct source_cookie *)cookie)->dbg_tick; + return &((source_cookie_T *)cookie)->dbg_tick; } /* @@ -1069,7 +1045,7 @@ source_dbg_tick(void *cookie) int source_level(void *cookie) { - return ((struct source_cookie *)cookie)->level; + return ((source_cookie_T *)cookie)->level; } /* @@ -1079,7 +1055,7 @@ source_level(void *cookie) char_u * source_nextline(void *cookie) { - return ((struct source_cookie *)cookie)->nextline; + return ((source_cookie_T *)cookie)->nextline; } #endif @@ -1130,7 +1106,7 @@ do_source( int is_vimrc, // DOSO_ value int *ret_sid UNUSED) { - struct source_cookie cookie; + source_cookie_T cookie; char_u *p; char_u *fname_exp; char_u *firstline = NULL; @@ -1613,12 +1589,12 @@ get_sourced_lnum( void *cookie) { return fgetline == getsourceline - ? ((struct source_cookie *)cookie)->sourcing_lnum + ? ((source_cookie_T *)cookie)->sourcing_lnum : SOURCING_LNUM; } static char_u * -get_one_sourceline(struct source_cookie *sp) +get_one_sourceline(source_cookie_T *sp) { garray_T ga; int len; @@ -1736,7 +1712,7 @@ getsourceline( int indent UNUSED, getline_opt_T options) { - struct source_cookie *sp = (struct source_cookie *)cookie; + source_cookie_T *sp = (source_cookie_T *)cookie; char_u *line; char_u *p; int do_vim9_all = in_vim9script() @@ -1761,8 +1737,8 @@ getsourceline( SOURCING_LNUM = sp->sourcing_lnum + 1; // Get current line. If there is a read-ahead line, use it, otherwise get - // one now. - if (sp->finished) + // one now. "fp" is NULL if actually using a string. + if (sp->finished || sp->fp == NULL) line = NULL; else if (sp->nextline == NULL) line = get_one_sourceline(sp); @@ -1880,8 +1856,8 @@ getsourceline( void ex_scriptencoding(exarg_T *eap) { - struct source_cookie *sp; - char_u *name; + source_cookie_T *sp; + char_u *name; if (!getline_equal(eap->getline, eap->cookie, getsourceline)) { @@ -1899,7 +1875,7 @@ ex_scriptencoding(exarg_T *eap) name = eap->arg; // Setup for conversion from the specified encoding to 'encoding'. - sp = (struct source_cookie *)getline_cookie(eap->getline, eap->cookie); + sp = (source_cookie_T *)getline_cookie(eap->getline, eap->cookie); convert_setup(&sp->conv, name, p_enc); if (name != eap->arg) @@ -1963,7 +1939,7 @@ do_finish(exarg_T *eap, int reanimate) int idx; if (reanimate) - ((struct source_cookie *)getline_cookie(eap->getline, + ((source_cookie_T *)getline_cookie(eap->getline, eap->cookie))->finished = FALSE; // Cleanup (and inactivate) conditionals, but stop when a try conditional @@ -1977,7 +1953,7 @@ do_finish(exarg_T *eap, int reanimate) report_make_pending(CSTP_FINISH, NULL); } else - ((struct source_cookie *)getline_cookie(eap->getline, + ((source_cookie_T *)getline_cookie(eap->getline, eap->cookie))->finished = TRUE; } @@ -1993,7 +1969,7 @@ source_finished( void *cookie) { return (getline_equal(fgetline, cookie, getsourceline) - && ((struct source_cookie *)getline_cookie( + && ((source_cookie_T *)getline_cookie( fgetline, cookie))->finished); } diff --git a/src/structs.h b/src/structs.h --- a/src/structs.h +++ b/src/structs.h @@ -4300,6 +4300,32 @@ typedef struct int sa_wrapped; // search wrapped around } searchit_arg_T; +/* + * Cookie used by getsourceline(). + */ +/* + * Cookie used to store info for each sourced file. + * It is shared between do_source() and getsourceline(). + * This is passed to do_cmdline(). + */ +typedef struct { + FILE *fp; // opened file for sourcing + char_u *nextline; // if not NULL: line that was read ahead + linenr_T sourcing_lnum; // line number of the source file + int finished; // ":finish" used +#ifdef USE_CRNL + int fileformat; // EOL_UNKNOWN, EOL_UNIX or EOL_DOS + int error; // TRUE if LF found after CR-LF +#endif +#ifdef FEAT_EVAL + linenr_T breakpoint; // next line with breakpoint or zero + char_u *fname; // name of sourced file + int dbg_tick; // debug_tick when breakpoint was set + int level; // top nesting level of sourced file +#endif + vimconv_T conv; // type of conversion +} source_cookie_T; + #define WRITEBUFSIZE 8192 // size of normal write buffer diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -921,4 +921,11 @@ def Test_wincmd() close enddef +def Test_windo_missing_endif() + var lines =<< trim END + windo if 1 + END + CheckDefExecFailure(lines, 'E171:', 1) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2332, +/**/ 2331, /**/ 2330, diff --git a/src/vim9execute.c b/src/vim9execute.c --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1382,9 +1382,18 @@ call_def_function( // execute Ex command line case ISN_EXEC: { + source_cookie_T cookie; + SOURCING_LNUM = iptr->isn_lnum; - do_cmdline_cmd(iptr->isn_arg.string); - if (did_emsg) + // Pass getsourceline to get an error for a missing ":end" + // command. + CLEAR_FIELD(cookie); + cookie.sourcing_lnum = iptr->isn_lnum - 1; + if (do_cmdline(iptr->isn_arg.string, + getsourceline, &cookie, + DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED) + == FAIL + || did_emsg) goto on_error; } break;