From 253b16a4abdad1df350b9ddd9a709520b063934c Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 6 Oct 2020 19:59:06 +0200 Subject: [PATCH 01/25] patch 8.2.1806: MS-Windows with Python: Vim freezes after import command Problem: MS-Windows with Python: Vim freezes after import command. Solution: Use either "NUL" or "CONIN$" when reopening stdin. (Yasuhiro Matsumoto, closes #7083) --- src/if_python3.c | 15 +++++++++------ src/version.c | 2 ++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/if_python3.c b/src/if_python3.c index 15c1d9973e..f6904c3801 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -917,6 +917,7 @@ reset_stdin(void) { FILE *(*py__acrt_iob_func)(unsigned) = NULL; FILE *(*pyfreopen)(const char *, const char *, FILE *) = NULL; + char *stdin_name = "NUL"; HINSTANCE hinst; # ifdef DYNAMIC_PYTHON3 @@ -933,16 +934,18 @@ reset_stdin(void) if (py__acrt_iob_func) { HINSTANCE hpystdiodll = find_imported_module_by_funcname(hinst, - "__acrt_iob_func"); + "__acrt_iob_func"); if (hpystdiodll) - pyfreopen = (void*)GetProcAddress(hpystdiodll, "freopen"); + pyfreopen = (void *)GetProcAddress(hpystdiodll, "freopen"); } + if (isatty(fileno(stdin))) + stdin_name = "CONIN$"; - // Reconnect stdin to NUL. - if (pyfreopen) - pyfreopen("NUL", "r", py__acrt_iob_func(0)); + // Reconnect stdin to NUL or CONIN$. + if (pyfreopen != NULL) + pyfreopen(stdin_name, "r", py__acrt_iob_func(0)); else - freopen("NUL", "r", stdin); + freopen(stdin_name, "r", stdin); } #else # define reset_stdin() diff --git a/src/version.c b/src/version.c index b8b9917d06..a410167beb 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1806, /**/ 1805, /**/ From 349f609f8990a3aca9a4b8faa0585d75e03116db Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Tue, 6 Oct 2020 20:46:49 +0200 Subject: [PATCH 02/25] patch 8.2.1807: can use :help in a terminal popup window Problem: Can use :help in a terminal popup window. Solution: Give an error. (closes #7088) --- src/help.c | 3 +++ src/testdir/test_popupwin.vim | 6 ++++++ src/version.c | 2 ++ 3 files changed, 11 insertions(+) diff --git a/src/help.c b/src/help.c index 4f2b6b69e0..4d59ab90e1 100644 --- a/src/help.c +++ b/src/help.c @@ -39,6 +39,9 @@ ex_help(exarg_T *eap) int old_KeyTyped = KeyTyped; #endif + if (ERROR_IF_ANY_POPUP_WINDOW) + return; + if (eap != NULL) { // A ":help" command ends at the first LF, or at a '|' that is diff --git a/src/testdir/test_popupwin.vim b/src/testdir/test_popupwin.vim index e991fc116f..187b4f13eb 100644 --- a/src/testdir/test_popupwin.vim +++ b/src/testdir/test_popupwin.vim @@ -2645,6 +2645,10 @@ func Test_popupwin_terminal_buffer() let g:test_is_flaky = 1 let origwin = win_getid() + + " open help window to test that :help below fails + help + let termbuf = term_start(&shell, #{hidden: 1}) let winid = popup_create(termbuf, #{minwidth: 40, minheight: 10}) " Wait for shell to start @@ -2666,6 +2670,7 @@ func Test_popupwin_terminal_buffer() " Cannot escape from terminal window call assert_fails('tab drop xxx', 'E863:') + call assert_fails('help', 'E994:') " Cannot open a second one. let termbuf2 = term_start(&shell, #{hidden: 1}) @@ -2677,6 +2682,7 @@ func Test_popupwin_terminal_buffer() " Wait for shell to exit call WaitForAssert({-> assert_equal("dead", job_status(term_getjob(termbuf)))}) + helpclose call feedkeys(":quit\", 'xt') call assert_equal(origwin, win_getid()) endfunc diff --git a/src/version.c b/src/version.c index a410167beb..daac37215c 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1807, /**/ 1806, /**/ From f12f0022e6698831681f0931a4e7e5298f6ef0d8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 7 Oct 2020 12:58:44 +0200 Subject: [PATCH 03/25] patch 8.2.1808: no test coverage for ":spelldump!" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Problem: No test coverage for ":spelldump!". Solution: Add a test. (Dominique Pellé, closes #7089) --- src/testdir/test_spell.vim | 38 ++++++++++++++++++++++++++++++++++++++ src/version.c | 2 ++ 2 files changed, 40 insertions(+) diff --git a/src/testdir/test_spell.vim b/src/testdir/test_spell.vim index dd68e0c090..a3a9621cb0 100644 --- a/src/testdir/test_spell.vim +++ b/src/testdir/test_spell.vim @@ -143,6 +143,44 @@ func Test_spell_file_missing() %bwipe! endfunc +func Test_spelldump() + set spell spelllang=en + spellrare! emacs + + spelldump + + " Check assumption about region: 1: us, 2: au, 3: ca, 4: gb, 5: nz. + call assert_equal('/regions=usaucagbnz', getline(1)) + call assert_notequal(0, search('^theater/1$')) " US English only. + call assert_notequal(0, search('^theatre/2345$')) " AU, CA, GB or NZ English. + + call assert_notequal(0, search('^emacs/?$')) " ? for a rare word. + call assert_notequal(0, search('^the the/!$')) " ! for a wrong word. + + bwipe + set spell& +endfunc + +func Test_spelldump_bang() + new + call setline(1, 'This is a sample sentence.') + redraw + set spell + redraw + spelldump! + + " :spelldump! includes the number of times a word was found while updating + " the screen. + " Common word count starts at 10, regular word count starts at 0. + call assert_notequal(0, search("^is\t11$")) " common word found once. + call assert_notequal(0, search("^the\t10$")) " common word never found. + call assert_notequal(0, search("^sample\t1$")) " regular word found once. + call assert_equal(0, search("^screen\t")) " regular word never found. + + %bwipe! + set spell& +endfunc + func Test_spelllang_inv_region() set spell spelllang=en_xx let messages = GetMessages() diff --git a/src/version.c b/src/version.c index daac37215c..6786727849 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1808, /**/ 1807, /**/ From 4e2114e988f5d8635f2ad748be3cafcc44289138 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 7 Oct 2020 16:12:37 +0200 Subject: [PATCH 04/25] patch 8.2.1809: mapping some keys with Ctrl does not work properly Problem: Mapping some keys with Ctrl does not work properly. Solution: For terminal, GTK and Motif handle "@", "^" and "_" codes. --- src/gui_gtk_x11.c | 7 +++---- src/gui_x11.c | 3 +++ src/misc2.c | 26 ++++++++++++++++++++++++++ src/proto/misc2.pro | 1 + src/term.c | 9 +++------ src/testdir/test_termcodes.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ 7 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index ecd2d887fc..2549aef779 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -1236,11 +1236,10 @@ key_press_event(GtkWidget *widget UNUSED, } else { - // and mean the same thing, always use "H" - if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) - key = TOUPPER_ASC(key); + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); - // May remove the shift modifier if it's included in the key. + // May remove the Shift modifier if it's included in the key. modifiers = may_remove_shift_modifier(modifiers, key); len = mb_char2bytes(key, string); diff --git a/src/gui_x11.c b/src/gui_x11.c index f1d9bf8e58..38f85d875e 100644 --- a/src/gui_x11.c +++ b/src/gui_x11.c @@ -956,6 +956,9 @@ gui_x11_key_hit_cb( { len = mb_char2bytes(key, string); + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); + // Remove the SHIFT modifier for keys where it's already included, // e.g., '(', '!' and '*'. modifiers = may_remove_shift_modifier(modifiers, key); diff --git a/src/misc2.c b/src/misc2.c index 3781dd85d2..b69714a8da 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2946,6 +2946,32 @@ find_special_key( } +/* + * Some keys are used with Ctrl without Shift and are still expected to be + * mapped as if Shift was pressed: + * CTRL-2 is CTRL-@ + * CTRL-6 is CTRL-^ + * CTRL-- is CTRL-_ + * Also, and mean the same thing, always use "H". + * Returns the possibly adjusted key. + */ + int +may_adjust_key_for_ctrl(int modifiers, int key) +{ + if (modifiers & MOD_MASK_CTRL) + { + if (ASCII_ISALPHA(key)) + return TOUPPER_ASC(key); + if (key == '2') + return '@'; + if (key == '6') + return '^'; + if (key == '-') + return '_'; + } + return key; +} + /* * Some keys already have Shift included, pass them as normal keys. * Not when Ctrl is also used, because and are different. diff --git a/src/proto/misc2.pro b/src/proto/misc2.pro index d55fc31c39..fc574038a9 100644 --- a/src/proto/misc2.pro +++ b/src/proto/misc2.pro @@ -72,6 +72,7 @@ char_u *get_special_key_name(int c, int modifiers); int trans_special(char_u **srcp, char_u *dst, int flags, int *did_simplify); int special_to_buf(int key, int modifiers, int keycode, char_u *dst); int find_special_key(char_u **srcp, int *modp, int flags, int *did_simplify); +int may_adjust_key_for_ctrl(int modifiers, int key); int may_remove_shift_modifier(int modifiers, int key); int extract_modifiers(int key, int *modp, int simplify, int *did_simplify); int find_special_key_in_table(int c); diff --git a/src/term.c b/src/term.c index 4d32c043a3..be6d531b97 100644 --- a/src/term.c +++ b/src/term.c @@ -4784,15 +4784,12 @@ handle_key_with_modifier( modifiers = decode_modifiers(arg[1]); + // Some keys need adjustment when the Ctrl modifier is used. + key = may_adjust_key_for_ctrl(modifiers, key); + // May remove the shift modifier if it's already included in the key. modifiers = may_remove_shift_modifier(modifiers, key); - // When used with Ctrl we always make a letter upper case, - // so that mapping and are the same. Typing - // also uses "H" but modifier is different. - if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) - key = TOUPPER_ASC(key); - // insert modifiers with KS_MODIFIER new_slen = modifiers2keycode(modifiers, &key, string); diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index 91ccda8ca9..7d7e2f0987 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -2103,6 +2103,24 @@ endfunc func Test_mapping_works_with_ctrl() call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C', 5) call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C', 5) + + new + set timeoutlen=10 + + " CTRL-@ actually produces the code for CTRL-2, which is converted + call RunTest_mapping_mods('', '2', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '2', function('GetEscCodeCSIu'), 5) + + " CTRL-^ actually produces the code for CTRL-6, which is converted + call RunTest_mapping_mods('', '6', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '6', function('GetEscCodeCSIu'), 5) + + " CTRL-_ actually produces the code for CTRL--, which is converted + call RunTest_mapping_mods('', '-', function('GetEscCodeCSI27'), 5) + call RunTest_mapping_mods('', '-', function('GetEscCodeCSIu'), 5) + + bwipe! + set timeoutlen& endfunc func Test_mapping_works_with_shift_ctrl() diff --git a/src/version.c b/src/version.c index 6786727849..9c4029fa7f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1809, /**/ 1808, /**/ From d7e5e9430ae192c76f1f03c3ac53fae823d94c33 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 7 Oct 2020 16:54:52 +0200 Subject: [PATCH 05/25] patch 8.2.1810: some code in normal.c not covered by tests Problem: Some code in normal.c not covered by tests. Solution: Add normal mode tests. (Yegappan Lakshmanan, closes #7086) --- src/testdir/test_charsearch.vim | 31 ++++++++++++++- src/testdir/test_normal.vim | 68 +++++++++++++++++++++++++++++++++ src/version.c | 2 + 3 files changed, 99 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_charsearch.vim b/src/testdir/test_charsearch.vim index 78e991d8cb..06b8ff6ce9 100644 --- a/src/testdir/test_charsearch.vim +++ b/src/testdir/test_charsearch.vim @@ -51,7 +51,7 @@ func Test_csearch_virtualedit() normal! tb call assert_equal([0, 1, 2, 6], getpos('.')) set virtualedit& - close! + bw! endfunc " Test for character search failure in latin1 encoding @@ -65,7 +65,34 @@ func Test_charsearch_latin1() call assert_beeps('normal $Fz') call assert_beeps('normal $Tx') let &encoding = save_enc - close! + bw! +endfunc + +" Test for using character search to find a multibyte character with composing +" characters. +func Test_charsearch_composing_char() + new + call setline(1, "one two thq\u0328\u0301r\u0328\u0301ree") + call feedkeys("fr\u0328\u0301", 'xt') + call assert_equal([0, 1, 16, 0, 12], getcurpos()) + + " use character search with a multi-byte character followed by a + " non-composing character + call setline(1, "abc deȉf ghi") + call feedkeys("ggcf\u0209\u0210", 'xt') + call assert_equal("\u0210f ghi", getline(1)) + bw! +endfunc + +" Test for character search with 'hkmap' +func Test_charsearch_hkmap() + new + set hkmap + call setline(1, "ùðáâ÷ëòéïçìêöî") + call feedkeys("fë", 'xt') + call assert_equal([0, 1, 11, 0, 6], getcurpos()) + set hkmap& + bw! endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim index bae5d8d0a2..d2f1fab573 100644 --- a/src/testdir/test_normal.vim +++ b/src/testdir/test_normal.vim @@ -118,6 +118,39 @@ func Test_normal01_keymodel() call feedkeys("Vkk\yy", 'tx') call assert_equal(['47', '48', '49', '50'], getreg(0, 0, 1)) + " Test for using special keys to start visual selection + %d + call setline(1, ['red fox tail', 'red fox tail', 'red fox tail']) + set keymodel=startsel + " Test for and + call cursor(1, 1) + call feedkeys("\y", 'xt') + call assert_equal([0, 1, 1, 0], getpos("'<")) + call assert_equal([0, 3, 1, 0], getpos("'>")) + call feedkeys("Gz\8|\y", 'xt') + call assert_equal([0, 2, 1, 0], getpos("'<")) + call assert_equal([0, 3, 8, 0], getpos("'>")) + " Test for and + call cursor(2, 12) + call feedkeys("\y", 'xt') + call assert_equal([0, 1, 1, 0], getpos("'<")) + call assert_equal([0, 2, 12, 0], getpos("'>")) + call cursor(1, 4) + call feedkeys("\y", 'xt') + call assert_equal([0, 1, 4, 0], getpos("'<")) + call assert_equal([0, 3, 13, 0], getpos("'>")) + " Test for and + call cursor(2, 5) + call feedkeys("\y", 'xt') + call assert_equal([0, 2, 5, 0], getpos("'<")) + call assert_equal([0, 2, 9, 0], getpos("'>")) + call cursor(2, 9) + call feedkeys("\y", 'xt') + call assert_equal([0, 2, 5, 0], getpos("'<")) + call assert_equal([0, 2, 9, 0], getpos("'>")) + + set keymodel& + " clean up bw! endfunc @@ -409,6 +442,14 @@ func Test_normal10_expand() call assert_equal(expected[i], expand(''), 'i == ' . i) endfor + " Test for in state.val and ptr->val + call setline(1, 'x = state.val;') + call cursor(1, 10) + call assert_equal('state.val', expand('')) + call setline(1, 'x = ptr->val;') + call cursor(1, 9) + call assert_equal('ptr->val', expand('')) + if executable('echo') " Test expand(`...`) i.e. backticks command expansion. call assert_equal('abcde', expand('`echo abcde`')) @@ -422,6 +463,19 @@ func Test_normal10_expand() bw! endfunc +" Test for expand() in latin1 encoding +func Test_normal_expand_latin1() + new + let save_enc = &encoding + set encoding=latin1 + call setline(1, 'val = item->color;') + call cursor(1, 11) + call assert_equal('color', expand("")) + call assert_equal('item->color', expand("")) + let &encoding = save_enc + bw! +endfunc + func Test_normal11_showcmd() " test for 'showcmd' 10new @@ -446,6 +500,13 @@ func Test_normal11_showcmd() redraw! call assert_match('1-3$', Screenline(&lines)) call feedkeys("v", 'xt') + " test for visually selecting the end of line + call setline(1, ["foobar"]) + call feedkeys("$vl", 'xt') + redraw! + call assert_match('2$', Screenline(&lines)) + call feedkeys("y", 'xt') + call assert_equal("r\n", @") bw! endfunc @@ -2021,6 +2082,13 @@ func Test_normal31_r_cmd() normal gglvjjrx call assert_equal(['axx', 'xxx', 'xxf'], getline(1, '$')) + " replace with a multibyte character (with multiple composing characters) + %d + new + call setline(1, 'aaa') + exe "normal $ra\u0328\u0301" + call assert_equal("aaa\u0328\u0301", getline(1)) + " clean up set noautoindent bw! diff --git a/src/version.c b/src/version.c index 9c4029fa7f..140b3c8e20 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1810, /**/ 1809, /**/ From 9a033d7b18651acbb7eda4b7f39a27c01748fb70 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 7 Oct 2020 17:29:48 +0200 Subject: [PATCH 06/25] patch 8.2.1811: mapping Ctrl-key does not work for '{', '}' and '|' Problem: Mapping Ctrl-key does not work for '{', '}' and '|'. Solution: Remove the shift modifier. (closes #6457) --- runtime/doc/map.txt | 11 +++++++++-- src/misc2.c | 8 +++++++- src/testdir/test_termcodes.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index df96bde941..cfd48b5a78 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -839,8 +839,15 @@ execute a shell command, e.g.: `!ls` Or put the lines in your |vimrc|. When modifyOtherKeys is enabled you can map and : > imap [[[ - imap {{{ -Without modifyOtherKeys and are indistinguishable from Esc. + imap {{{ +Without modifyOtherKeys and are indistinguishable from Esc. +Note that is used and not or . This works on most +keyboards. Similarly, is used instead of or and + instead of or . Note that '|' has a special meaning in a +mapping, see |map-bar|. + +WARNING: if you map you may very well break any key codes that start +with Esc. Make sure it comes AFTER other mappings. A known side effect is that in Insert mode the raw escape sequence is inserted after the CTRL-V key. This can be used to check whether modifyOtherKeys is diff --git a/src/misc2.c b/src/misc2.c index b69714a8da..6316b53df4 100644 --- a/src/misc2.c +++ b/src/misc2.c @@ -2974,7 +2974,8 @@ may_adjust_key_for_ctrl(int modifiers, int key) /* * Some keys already have Shift included, pass them as normal keys. - * Not when Ctrl is also used, because and are different. + * When Ctrl is also used and are different, but should + * be . Same for and . * Also for and . * This includes all printable ASCII characters except numbers and a-z. */ @@ -2989,6 +2990,11 @@ may_remove_shift_modifier(int modifiers, int key) || (key >= '[' && key <= '`') || (key >= '{' && key <= '~'))) return modifiers & ~MOD_MASK_SHIFT; + + if (modifiers == (MOD_MASK_SHIFT | MOD_MASK_CTRL) + && (key == '{' || key == '}' || key == '|')) + return modifiers & ~MOD_MASK_SHIFT; + return modifiers; } diff --git a/src/testdir/test_termcodes.vim b/src/testdir/test_termcodes.vim index 7d7e2f0987..424e285ef1 100644 --- a/src/testdir/test_termcodes.vim +++ b/src/testdir/test_termcodes.vim @@ -2126,6 +2126,24 @@ endfunc func Test_mapping_works_with_shift_ctrl() call RunTest_mapping_works_with_mods(function('GetEscCodeCSI27'), 'C-S', 6) call RunTest_mapping_works_with_mods(function('GetEscCodeCSIu'), 'C-S', 6) + + new + set timeoutlen=10 + + " Ctrl-Shift-[ actually produces CTRL-Shift-{ which is mapped as + call RunTest_mapping_mods('', '{', function('GetEscCodeCSI27'), 6) + call RunTest_mapping_mods('', '{', function('GetEscCodeCSIu'), 6) + + " Ctrl-Shift-] actually produces CTRL-Shift-} which is mapped as + call RunTest_mapping_mods('', '{', function('GetEscCodeCSI27'), 6) + call RunTest_mapping_mods('', '{', function('GetEscCodeCSIu'), 6) + + " Ctrl-Shift-\ actually produces CTRL-Shift-| which is mapped as + call RunTest_mapping_mods('', '|', function('GetEscCodeCSI27'), 6) + call RunTest_mapping_mods('', '|', function('GetEscCodeCSIu'), 6) + + bwipe! + set timeoutlen& endfunc " Below we also test the "u" code with Alt, This works, but libvterm would not diff --git a/src/version.c b/src/version.c index 140b3c8e20..a2929bc3f7 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1811, /**/ 1810, /**/ From 0876c78527469ddf50c23244566dd5bc35004307 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Wed, 7 Oct 2020 19:08:04 +0200 Subject: [PATCH 07/25] patch 8.2.1812: Vim9: nested closure throws an internal error Problem: Vim9: nested closure throws an internal error. Solution: Do not skip a local variable with a partial. (closes #7065) --- src/testdir/test_vim9_func.vim | 14 ++++++++++++++ src/version.c | 2 ++ src/vim9execute.c | 6 ++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index f3352453fe..c3687cf20a 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1388,6 +1388,20 @@ def Test_double_closure_fails() CheckScriptSuccess(lines) enddef +def Test_nested_closure_used() + var lines =<< trim END + vim9script + def Func() + var x = 'hello' + var Closure = {-> x} + g:Myclosure = {-> Closure()} + enddef + Func() + assert_equal('hello', g:Myclosure()) + END + CheckScriptSuccess(lines) +enddef + def Test_nested_closure_fails() var lines =<< trim END vim9script diff --git a/src/version.c b/src/version.c index a2929bc3f7..1c8629dd80 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1812, /**/ 1811, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 7afc5c27cd..2387ac9061 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -377,10 +377,11 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); // Do not copy a partial created for a local function. - // TODO: this won't work if the closure actually uses it. But when + // TODO: This won't work if the closure actually uses it. But when // keeping it it gets complicated: it will create a reference cycle // inside the partial, thus needs special handling for garbage // collection. + // For now, decide on the reference count. if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) { int i; @@ -389,7 +390,8 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) { partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len - closure_count + i]; - if (tv->vval.v_partial == pt) + + if (tv->vval.v_partial == pt && pt->pt_refcount < 2) break; } if (i < closure_count) From 10c65860f83589e0ca2498393d3cfef1115b7fe8 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 8 Oct 2020 21:16:42 +0200 Subject: [PATCH 08/25] patch 8.2.1813: Vim9: can assign wrong type to script dict Problem: Vim9: can assign wrong type to script dict. (Christian J. Robinson) Solution: Check the type if known. --- src/eval.c | 24 ++++++++++++ src/proto/evalvars.pro | 1 + src/proto/vim9script.pro | 1 + src/structs.h | 1 + src/testdir/test_vim9_script.vim | 9 +++++ src/version.c | 2 + src/vim9script.c | 64 +++++++++++++++++++------------- 7 files changed, 77 insertions(+), 25 deletions(-) diff --git a/src/eval.c b/src/eval.c index 285558df8f..f7657b4a84 100644 --- a/src/eval.c +++ b/src/eval.c @@ -887,6 +887,17 @@ get_lval( return NULL; } + if (in_vim9script() && lp->ll_valtype == NULL + && lp->ll_tv == &v->di_tv + && ht != NULL && ht == get_script_local_ht()) + { + svar_T *sv = find_typval_in_script(lp->ll_tv); + + // Vim9 script local variable: get the type + if (sv != NULL) + lp->ll_valtype = sv->sv_type; + } + len = -1; if (*p == '.') { @@ -1037,6 +1048,10 @@ get_lval( } } + if (lp->ll_valtype != NULL) + // use the type of the member + lp->ll_valtype = lp->ll_valtype->tt_member; + if (lp->ll_di == NULL) { // Can't add "v:" or "a:" variable. @@ -1148,6 +1163,10 @@ get_lval( return NULL; } + if (lp->ll_valtype != NULL) + // use the type of the member + lp->ll_valtype = lp->ll_valtype->tt_member; + /* * May need to find the item or absolute index for the second * index of a range. @@ -1383,6 +1402,11 @@ set_var_lval( emsg(_("E996: Cannot lock a list or dict")); return; } + + if (lp->ll_valtype != NULL + && check_typval_type(lp->ll_valtype, rettv, 0) == FAIL) + return; + if (lp->ll_newkey != NULL) { if (op != NULL && *op != '=') diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 69655089ea..520fedd5ef 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -58,6 +58,7 @@ int eval_variable(char_u *name, int len, typval_T *rettv, dictitem_T **dip, int void check_vars(char_u *name, int len); dictitem_T *find_var(char_u *name, hashtab_T **htp, int no_autoload); dictitem_T *find_var_in_ht(hashtab_T *ht, int htname, char_u *varname, int no_autoload); +hashtab_T *get_script_local_ht(void); void *lookup_scriptvar(char_u *name, size_t len, cctx_T *dummy); hashtab_T *find_var_ht(char_u *name, char_u **varname); char_u *get_var_value(char_u *name); diff --git a/src/proto/vim9script.pro b/src/proto/vim9script.pro index f8b12ee5de..a20b715bc3 100644 --- a/src/proto/vim9script.pro +++ b/src/proto/vim9script.pro @@ -8,5 +8,6 @@ void ex_import(exarg_T *eap); int find_exported(int sid, char_u *name, ufunc_T **ufunc, type_T **type); char_u *handle_import(char_u *arg_start, garray_T *gap, int import_sid, evalarg_T *evalarg, void *cctx); char_u *vim9_declare_scriptvar(exarg_T *eap, char_u *arg); +svar_T *find_typval_in_script(typval_T *dest); int check_script_var_type(typval_T *dest, typval_T *value, char_u *name); /* vim: set ft=c : */ diff --git a/src/structs.h b/src/structs.h index 86c6ef8992..e7b72de23c 100644 --- a/src/structs.h +++ b/src/structs.h @@ -4055,6 +4055,7 @@ typedef struct lval_S dict_T *ll_dict; // The Dictionary or NULL dictitem_T *ll_di; // The dictitem or NULL char_u *ll_newkey; // New key for Dict in alloc. mem or NULL. + type_T *ll_valtype; // type expected for the value or NULL blob_T *ll_blob; // The Blob or NULL } lval_T; diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 7fc522362d..02bc56b2fa 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -145,6 +145,15 @@ def Test_wrong_type() CheckDefFailure(['var Ref: string', 'var res = Ref()'], 'E1085:') enddef +def Test_script_wrong_type() + var lines =<< trim END + vim9script + var s:dict: dict + s:dict['a'] = ['x'] + END + CheckScriptFailure(lines, 'E1012: Type mismatch; expected string but got list', 3) +enddef + def Test_const() CheckDefFailure(['final name = 234', 'name = 99'], 'E1018:') CheckDefFailure(['final one = 234', 'var one = 99'], 'E1017:') diff --git a/src/version.c b/src/version.c index 1c8629dd80..7d62814d22 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1813, /**/ 1812, /**/ diff --git a/src/vim9script.c b/src/vim9script.c index 399c4a7b05..d9f103fbf5 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -565,18 +565,18 @@ vim9_declare_scriptvar(exarg_T *eap, char_u *arg) } /* - * Check if the type of script variable "dest" allows assigning "value". - * If needed convert "value" to a bool. + * Find the script-local variable that links to "dest". + * Returns NULL if not found. */ - int -check_script_var_type(typval_T *dest, typval_T *value, char_u *name) + svar_T * +find_typval_in_script(typval_T *dest) { scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); int idx; if (si->sn_version != SCRIPT_VERSION_VIM9) // legacy script doesn't store variable types - return OK; + return NULL; // Find the svar_T in sn_var_vals. for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) @@ -584,28 +584,42 @@ check_script_var_type(typval_T *dest, typval_T *value, char_u *name) svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; if (sv->sv_tv == dest) - { - int ret; - - if (sv->sv_const) - { - semsg(_(e_readonlyvar), name); - return FAIL; - } - ret = check_typval_type(sv->sv_type, value, 0); - if (ret == OK && need_convert_to_bool(sv->sv_type, value)) - { - int val = tv2bool(value); - - clear_tv(value); - value->v_type = VAR_BOOL; - value->v_lock = 0; - value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE; - } - return ret; - } + return sv; } iemsg("check_script_var_type(): not found"); + return NULL; +} + +/* + * Check if the type of script variable "dest" allows assigning "value". + * If needed convert "value" to a bool. + */ + int +check_script_var_type(typval_T *dest, typval_T *value, char_u *name) +{ + svar_T *sv = find_typval_in_script(dest); + int ret; + + if (sv != NULL) + { + if (sv->sv_const) + { + semsg(_(e_readonlyvar), name); + return FAIL; + } + ret = check_typval_type(sv->sv_type, value, 0); + if (ret == OK && need_convert_to_bool(sv->sv_type, value)) + { + int val = tv2bool(value); + + clear_tv(value); + value->v_type = VAR_BOOL; + value->v_lock = 0; + value->vval.v_number = val ? VVAL_TRUE : VVAL_FALSE; + } + return ret; + } + return OK; // not really } From 922acbda3d4e250c8683db223f444d0ec8c6fd03 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 8 Oct 2020 21:30:40 +0200 Subject: [PATCH 09/25] patch 8.2.1814: missing change to remove "static" Problem: Missing change to remove "static". Solution: Add the change. --- src/evalvars.c | 2 +- src/version.c | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/evalvars.c b/src/evalvars.c index fdc6f454a5..f7ee58d531 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -2653,7 +2653,7 @@ find_var_in_ht( /* * Get the script-local hashtab. NULL if not in a script context. */ - static hashtab_T * + hashtab_T * get_script_local_ht(void) { scid_T sid = current_sctx.sc_sid; diff --git a/src/version.c b/src/version.c index 7d62814d22..238113f67c 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1814, /**/ 1813, /**/ From 6a61421f646961b7d719432c02382f0a70702a80 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Thu, 8 Oct 2020 23:21:21 +0200 Subject: [PATCH 10/25] patch 8.2.1815: Vim9: memory leak when using function reference Problem: Vim9: memory leak when using function reference. Solution: Temporarily disable the test. --- src/testdir/test_vim9_disassemble.vim | 71 ++++++++++++++------------- src/version.c | 2 + 2 files changed, 38 insertions(+), 35 deletions(-) diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index ceeae0db51..f233f5b82e 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -436,41 +436,42 @@ def Test_disassemble_call() res) enddef -def s:CreateRefs() - var local = 'a' - def Append(arg: string) - local ..= arg - enddef - g:Append = Append - def Get(): string - return local - enddef - g:Get = Get -enddef - -def Test_disassemble_closure() - CreateRefs() - var res = execute('disass g:Append') - assert_match('\d\_s*' .. - 'local ..= arg\_s*' .. - '\d LOADOUTER $0\_s*' .. - '\d LOAD arg\[-1\]\_s*' .. - '\d CONCAT\_s*' .. - '\d STOREOUTER $0\_s*' .. - '\d PUSHNR 0\_s*' .. - '\d RETURN', - res) - - res = execute('disass g:Get') - assert_match('\d\_s*' .. - 'return local\_s*' .. - '\d LOADOUTER $0\_s*' .. - '\d RETURN', - res) - - unlet g:Append - unlet g:Get -enddef +" TODO: fix memory leak and enable again +"def s:CreateRefs() +" var local = 'a' +" def Append(arg: string) +" local ..= arg +" enddef +" g:Append = Append +" def Get(): string +" return local +" enddef +" g:Get = Get +"enddef +" +"def Test_disassemble_closure() +" CreateRefs() +" var res = execute('disass g:Append') +" assert_match('\d\_s*' .. +" 'local ..= arg\_s*' .. +" '\d LOADOUTER $0\_s*' .. +" '\d LOAD arg\[-1\]\_s*' .. +" '\d CONCAT\_s*' .. +" '\d STOREOUTER $0\_s*' .. +" '\d PUSHNR 0\_s*' .. +" '\d RETURN', +" res) +" +" res = execute('disass g:Get') +" assert_match('\d\_s*' .. +" 'return local\_s*' .. +" '\d LOADOUTER $0\_s*' .. +" '\d RETURN', +" res) +" +" unlet g:Append +" unlet g:Get +"enddef def EchoArg(arg: string): string diff --git a/src/version.c b/src/version.c index 238113f67c..ecc4e7dbe0 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1815, /**/ 1814, /**/ From 11416321ff45e2bf3d456f332dc9d1836a8d171a Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 9 Oct 2020 10:20:53 +0200 Subject: [PATCH 11/25] patch 8.2.1816: Vim9: another memory leak when using function reference Problem: Vim9: another memory leak when using function reference. Solution: Temporarily disable the tests. --- src/testdir/test_vim9_func.vim | 78 +++++++++++++++++----------------- src/version.c | 2 + 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index c3687cf20a..28e503de78 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1330,31 +1330,32 @@ def Test_closure_using_argument() unlet g:UseVararg enddef -def MakeGetAndAppendRefs() - var local = 'a' - - def Append(arg: string) - local ..= arg - enddef - g:Append = Append - - def Get(): string - return local - enddef - g:Get = Get -enddef - -def Test_closure_append_get() - MakeGetAndAppendRefs() - g:Get()->assert_equal('a') - g:Append('-b') - g:Get()->assert_equal('a-b') - g:Append('-c') - g:Get()->assert_equal('a-b-c') - - unlet g:Append - unlet g:Get -enddef +" TODO: reenable after fixing memory leak +"def MakeGetAndAppendRefs() +" var local = 'a' +" +" def Append(arg: string) +" local ..= arg +" enddef +" g:Append = Append +" +" def Get(): string +" return local +" enddef +" g:Get = Get +"enddef +" +"def Test_closure_append_get() +" MakeGetAndAppendRefs() +" g:Get()->assert_equal('a') +" g:Append('-b') +" g:Get()->assert_equal('a-b') +" g:Append('-c') +" g:Get()->assert_equal('a-b-c') +" +" unlet g:Append +" unlet g:Get +"enddef def Test_nested_closure() var local = 'text' @@ -1388,19 +1389,20 @@ def Test_double_closure_fails() CheckScriptSuccess(lines) enddef -def Test_nested_closure_used() - var lines =<< trim END - vim9script - def Func() - var x = 'hello' - var Closure = {-> x} - g:Myclosure = {-> Closure()} - enddef - Func() - assert_equal('hello', g:Myclosure()) - END - CheckScriptSuccess(lines) -enddef +" TODO: reenable after fixing memory leak +"def Test_nested_closure_used() +" var lines =<< trim END +" vim9script +" def Func() +" var x = 'hello' +" var Closure = {-> x} +" g:Myclosure = {-> Closure()} +" enddef +" Func() +" assert_equal('hello', g:Myclosure()) +" END +" CheckScriptSuccess(lines) +"enddef def Test_nested_closure_fails() var lines =<< trim END diff --git a/src/version.c b/src/version.c index ecc4e7dbe0..598222ae6a 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1816, /**/ 1815, /**/ From e8211a33dcb0ac6e29aad6699160fdc2e5fa2024 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 9 Oct 2020 22:04:29 +0200 Subject: [PATCH 12/25] patch 8.2.1817: Vim9: wrong instruction when reusing a local variable spot Problem: Vim9: wrong instruction when reusing a local variable spot. Solution: Clear a newly allocated local variable. (closes #7080) --- src/testdir/test_vim9_func.vim | 18 ++++++++++++++++++ src/version.c | 2 ++ src/vim9compile.c | 12 +++++++++--- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 28e503de78..6089402904 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -2032,5 +2032,23 @@ def Test_callstack_def() endtry enddef +" Re-using spot for variable used in block +def Test_block_scoped_var() + var lines =<< trim END + vim9script + def Func() + var x = ['a', 'b', 'c'] + if 1 + var y = 'x' + map(x, {-> y}) + endif + var z = x + assert_equal(['x', 'x', 'x'], z) + enddef + Func() + END + CheckScriptSuccess(lines) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/version.c b/src/version.c index 598222ae6a..5adfd96786 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1817, /**/ 1816, /**/ diff --git a/src/vim9compile.c b/src/vim9compile.c index a6bdcc3f3d..74be262a52 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -1690,7 +1690,12 @@ generate_EXECCONCAT(cctx_T *cctx, int count) * Return the variable or NULL if it failed. */ static lvar_T * -reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type) +reserve_local( + cctx_T *cctx, + char_u *name, + size_t len, + int isConst, + type_T *type) { lvar_T *lvar; @@ -1703,6 +1708,7 @@ reserve_local(cctx_T *cctx, char_u *name, size_t len, int isConst, type_T *type) if (ga_grow(&cctx->ctx_locals, 1) == FAIL) return NULL; lvar = ((lvar_T *)cctx->ctx_locals.ga_data) + cctx->ctx_locals.ga_len++; + CLEAR_POINTER(lvar); // Every local variable uses the next entry on the stack. We could re-use // the last ones when leaving a scope, but then variables used in a closure @@ -4438,7 +4444,6 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) char_u *name_start = eap->arg; char_u *name_end = to_name_end(eap->arg, TRUE); char_u *lambda_name; - lvar_T *lvar; ufunc_T *ufunc; int r; @@ -4487,8 +4492,9 @@ compile_nested_function(exarg_T *eap, cctx_T *cctx) else { // Define a local variable for the function reference. - lvar = reserve_local(cctx, name_start, name_end - name_start, + lvar_T *lvar = reserve_local(cctx, name_start, name_end - name_start, TRUE, ufunc->uf_func_type); + if (lvar == NULL) return NULL; if (generate_FUNCREF(cctx, ufunc) == FAIL) From 8956023920bb1b6f9c381739e59b9ddab4bf7798 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Fri, 9 Oct 2020 23:04:47 +0200 Subject: [PATCH 13/25] patch 8.2.1818: SE Linux: deprecation warning for security_context_t Problem: SE Linux: deprecation warning for security_context_t. Solution: Use "char *" instead. (James McCoy, closes #7093) --- src/os_unix.c | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/os_unix.c b/src/os_unix.c index 2afe1ba936..40df6b727c 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -2832,8 +2832,10 @@ mch_copy_sec(char_u *from_file, char_u *to_file) if (selinux_enabled > 0) { - security_context_t from_context = NULL; - security_context_t to_context = NULL; + // Use "char *" instead of "security_context_t" to avoid a deprecation + // warning. + char *from_context = NULL; + char *to_context = NULL; if (getfilecon((char *)from_file, &from_context) < 0) { diff --git a/src/version.c b/src/version.c index 5adfd96786..5fdfeeaf4a 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1818, /**/ 1817, /**/ From 85d5e2b723e6fc233e53252dd5c523944146fbc2 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 14:13:01 +0200 Subject: [PATCH 14/25] patch 8.2.1819: Vim9: Memory leak when using a closure Problem: Vim9: Memory leak when using a closure. Solution: Compute the mininal refcount in the funcstack. Reenable disabled tests. --- src/eval.c | 29 +++++----- src/proto/vim9execute.pro | 1 + src/structs.h | 3 ++ src/testdir/test_vim9_disassemble.vim | 72 ++++++++++++------------- src/testdir/test_vim9_func.vim | 78 +++++++++++++-------------- src/version.c | 2 + src/vim9execute.c | 68 ++++++++++++++++------- 7 files changed, 143 insertions(+), 110 deletions(-) diff --git a/src/eval.c b/src/eval.c index f7657b4a84..98d16c8262 100644 --- a/src/eval.c +++ b/src/eval.c @@ -3984,21 +3984,12 @@ partial_free(partial_T *pt) else func_ptr_unref(pt->pt_func); + // Decrease the reference count for the context of a closure. If down + // to the minimum it may be time to free it. if (pt->pt_funcstack != NULL) { - // Decrease the reference count for the context of a closure. If down - // to zero free it and clear the variables on the stack. - if (--pt->pt_funcstack->fs_refcount == 0) - { - garray_T *gap = &pt->pt_funcstack->fs_ga; - typval_T *stack = gap->ga_data; - - for (i = 0; i < gap->ga_len; ++i) - clear_tv(stack + i); - ga_clear(gap); - vim_free(pt->pt_funcstack); - } - pt->pt_funcstack = NULL; + --pt->pt_funcstack->fs_refcount; + funcstack_check_refcount(pt->pt_funcstack); } vim_free(pt); @@ -4011,8 +4002,16 @@ partial_free(partial_T *pt) void partial_unref(partial_T *pt) { - if (pt != NULL && --pt->pt_refcount <= 0) - partial_free(pt); + if (pt != NULL) + { + if (--pt->pt_refcount <= 0) + partial_free(pt); + + // If the reference count goes down to one, the funcstack may be the + // only reference and can be freed if no other partials reference it. + else if (pt->pt_refcount == 1 && pt->pt_funcstack != NULL) + funcstack_check_refcount(pt->pt_funcstack); + } } /* diff --git a/src/proto/vim9execute.pro b/src/proto/vim9execute.pro index 755b7ddd3d..2f0ef54543 100644 --- a/src/proto/vim9execute.pro +++ b/src/proto/vim9execute.pro @@ -1,5 +1,6 @@ /* vim9execute.c */ void to_string_error(vartype_T vartype); +void funcstack_check_refcount(funcstack_T *funcstack); int call_def_function(ufunc_T *ufunc, int argc_arg, typval_T *argv, partial_T *partial, typval_T *rettv); void ex_disassemble(exarg_T *eap); int tv2bool(typval_T *tv); diff --git a/src/structs.h b/src/structs.h index e7b72de23c..0a3d524e7b 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1869,8 +1869,11 @@ typedef struct funcstack_S // - arguments // - frame // - local variables + int fs_var_offset; // count of arguments + frame size == offset to + // local variables int fs_refcount; // nr of closures referencing this funcstack + int fs_min_refcount; // nr of closures on this funcstack int fs_copyID; // for garray_T collection } funcstack_T; diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim index f233f5b82e..53bc4bad70 100644 --- a/src/testdir/test_vim9_disassemble.vim +++ b/src/testdir/test_vim9_disassemble.vim @@ -436,42 +436,42 @@ def Test_disassemble_call() res) enddef -" TODO: fix memory leak and enable again -"def s:CreateRefs() -" var local = 'a' -" def Append(arg: string) -" local ..= arg -" enddef -" g:Append = Append -" def Get(): string -" return local -" enddef -" g:Get = Get -"enddef -" -"def Test_disassemble_closure() -" CreateRefs() -" var res = execute('disass g:Append') -" assert_match('\d\_s*' .. -" 'local ..= arg\_s*' .. -" '\d LOADOUTER $0\_s*' .. -" '\d LOAD arg\[-1\]\_s*' .. -" '\d CONCAT\_s*' .. -" '\d STOREOUTER $0\_s*' .. -" '\d PUSHNR 0\_s*' .. -" '\d RETURN', -" res) -" -" res = execute('disass g:Get') -" assert_match('\d\_s*' .. -" 'return local\_s*' .. -" '\d LOADOUTER $0\_s*' .. -" '\d RETURN', -" res) -" -" unlet g:Append -" unlet g:Get -"enddef + +def s:CreateRefs() + var local = 'a' + def Append(arg: string) + local ..= arg + enddef + g:Append = Append + def Get(): string + return local + enddef + g:Get = Get +enddef + +def Test_disassemble_closure() + CreateRefs() + var res = execute('disass g:Append') + assert_match('\d\_s*' .. + 'local ..= arg\_s*' .. + '\d LOADOUTER $0\_s*' .. + '\d LOAD arg\[-1\]\_s*' .. + '\d CONCAT\_s*' .. + '\d STOREOUTER $0\_s*' .. + '\d PUSHNR 0\_s*' .. + '\d RETURN', + res) + + res = execute('disass g:Get') + assert_match('\d\_s*' .. + 'return local\_s*' .. + '\d LOADOUTER $0\_s*' .. + '\d RETURN', + res) + + unlet g:Append + unlet g:Get +enddef def EchoArg(arg: string): string diff --git a/src/testdir/test_vim9_func.vim b/src/testdir/test_vim9_func.vim index 6089402904..371b9efbcb 100644 --- a/src/testdir/test_vim9_func.vim +++ b/src/testdir/test_vim9_func.vim @@ -1330,32 +1330,31 @@ def Test_closure_using_argument() unlet g:UseVararg enddef -" TODO: reenable after fixing memory leak -"def MakeGetAndAppendRefs() -" var local = 'a' -" -" def Append(arg: string) -" local ..= arg -" enddef -" g:Append = Append -" -" def Get(): string -" return local -" enddef -" g:Get = Get -"enddef -" -"def Test_closure_append_get() -" MakeGetAndAppendRefs() -" g:Get()->assert_equal('a') -" g:Append('-b') -" g:Get()->assert_equal('a-b') -" g:Append('-c') -" g:Get()->assert_equal('a-b-c') -" -" unlet g:Append -" unlet g:Get -"enddef +def MakeGetAndAppendRefs() + var local = 'a' + + def Append(arg: string) + local ..= arg + enddef + g:Append = Append + + def Get(): string + return local + enddef + g:Get = Get +enddef + +def Test_closure_append_get() + MakeGetAndAppendRefs() + g:Get()->assert_equal('a') + g:Append('-b') + g:Get()->assert_equal('a-b') + g:Append('-c') + g:Get()->assert_equal('a-b-c') + + unlet g:Append + unlet g:Get +enddef def Test_nested_closure() var local = 'text' @@ -1389,20 +1388,19 @@ def Test_double_closure_fails() CheckScriptSuccess(lines) enddef -" TODO: reenable after fixing memory leak -"def Test_nested_closure_used() -" var lines =<< trim END -" vim9script -" def Func() -" var x = 'hello' -" var Closure = {-> x} -" g:Myclosure = {-> Closure()} -" enddef -" Func() -" assert_equal('hello', g:Myclosure()) -" END -" CheckScriptSuccess(lines) -"enddef +def Test_nested_closure_used() + var lines =<< trim END + vim9script + def Func() + var x = 'hello' + var Closure = {-> x} + g:Myclosure = {-> Closure()} + enddef + Func() + assert_equal('hello', g:Myclosure()) + END + CheckScriptSuccess(lines) +enddef def Test_nested_closure_fails() var lines =<< trim END diff --git a/src/version.c b/src/version.c index 5fdfeeaf4a..a953c099b8 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1819, /**/ 1818, /**/ diff --git a/src/vim9execute.c b/src/vim9execute.c index 2387ac9061..015777e5e9 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -349,8 +349,8 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) // Move them to the called function. if (funcstack == NULL) return FAIL; - funcstack->fs_ga.ga_len = argcount + STACK_FRAME_SIZE - + dfunc->df_varcount; + funcstack->fs_var_offset = argcount + STACK_FRAME_SIZE; + funcstack->fs_ga.ga_len = funcstack->fs_var_offset + dfunc->df_varcount; stack = ALLOC_CLEAR_MULT(typval_T, funcstack->fs_ga.ga_len); funcstack->fs_ga.ga_data = stack; if (stack == NULL) @@ -376,29 +376,22 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) { tv = STACK_TV(ectx->ec_frame_idx + STACK_FRAME_SIZE + idx); - // Do not copy a partial created for a local function. - // TODO: This won't work if the closure actually uses it. But when - // keeping it it gets complicated: it will create a reference cycle - // inside the partial, thus needs special handling for garbage - // collection. - // For now, decide on the reference count. + // A partial created for a local function, that is also used as a + // local variable, has a reference count for the variable, thus + // will never go down to zero. When all these refcounts are one + // then the funcstack is unused. We need to count how many we have + // so we need when to check. if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL) { - int i; + int i; for (i = 0; i < closure_count; ++i) - { - partial_T *pt = ((partial_T **)gap->ga_data)[gap->ga_len - - closure_count + i]; - - if (tv->vval.v_partial == pt && pt->pt_refcount < 2) - break; - } - if (i < closure_count) - continue; + if (tv->vval.v_partial == ((partial_T **)gap->ga_data)[ + gap->ga_len - closure_count + i]) + ++funcstack->fs_min_refcount; } - *(stack + argcount + STACK_FRAME_SIZE + idx) = *tv; + *(stack + funcstack->fs_var_offset + idx) = *tv; tv->v_type = VAR_UNKNOWN; } @@ -426,6 +419,43 @@ handle_closure_in_use(ectx_T *ectx, int free_arguments) return OK; } +/* + * Called when a partial is freed or its reference count goes down to one. The + * funcstack may be the only reference to the partials in the local variables. + * Go over all of them, the funcref and can be freed if all partials + * referencing the funcstack have a reference count of one. + */ + void +funcstack_check_refcount(funcstack_T *funcstack) +{ + int i; + garray_T *gap = &funcstack->fs_ga; + int done = 0; + + if (funcstack->fs_refcount > funcstack->fs_min_refcount) + return; + for (i = funcstack->fs_var_offset; i < gap->ga_len; ++i) + { + typval_T *tv = ((typval_T *)gap->ga_data) + i; + + if (tv->v_type == VAR_PARTIAL && tv->vval.v_partial != NULL + && tv->vval.v_partial->pt_funcstack == funcstack + && tv->vval.v_partial->pt_refcount == 1) + ++done; + } + if (done == funcstack->fs_min_refcount) + { + typval_T *stack = gap->ga_data; + + // All partials referencing the funcstack have a reference count of + // one, thus the funcstack is no longer of use. + for (i = 0; i < gap->ga_len; ++i) + clear_tv(stack + i); + vim_free(stack); + vim_free(funcstack); + } +} + /* * Return from the current function. */ From 820d55a50bbc8c0ad0505b7e4302a734896b6bab Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 15:05:23 +0200 Subject: [PATCH 15/25] patch 8.2.1820: Vim9: crash when error happens in timer callback Problem: Vim9: crash when error happens in timer callback. Solution: Check that current_exception is not NULL. (closes #7100) --- src/ex_docmd.c | 4 ++++ src/version.c | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 05378fdcd7..310934ed71 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -1234,6 +1234,10 @@ do_cmdline( if (trylevel == 0) { + // Just in case did_throw got set but current_exception wasn't. + if (current_exception == NULL) + did_throw = FALSE; + /* * When an exception is being thrown out of the outermost try * conditional, discard the uncaught exception, disable the conversion diff --git a/src/version.c b/src/version.c index a953c099b8..8e2115e5d3 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1820, /**/ 1819, /**/ From 1a73923705744ab8297dd856d194e20297563456 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 15:37:58 +0200 Subject: [PATCH 16/25] patch 8.2.1821: Vim9: concatenating to a NULL list doesn't work Problem: Vim9: concatenating to a NULL list doesn't work. Solution: Handle a NULL list like an empty list. (closes #7064) --- src/list.c | 19 +++++++++++++------ src/testdir/test_vim9_assign.vim | 12 ++++++++++++ src/version.c | 2 ++ 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/list.c b/src/list.c index e86ec8686f..59c614ffbc 100644 --- a/src/list.c +++ b/src/list.c @@ -824,7 +824,7 @@ f_flatten(typval_T *argvars, typval_T *rettv) } /* - * Extend "l1" with "l2". + * Extend "l1" with "l2". "l1" must not be NULL. * If "bef" is NULL append at the end, otherwise insert before this item. * Returns FAIL when out of memory. */ @@ -832,8 +832,13 @@ f_flatten(typval_T *argvars, typval_T *rettv) list_extend(list_T *l1, list_T *l2, listitem_T *bef) { listitem_T *item; - int todo = l2->lv_len; + int todo; + // NULL list is equivalent to an empty list: nothing to do. + if (l2 == NULL || l2->lv_len == 0) + return OK; + + todo = l2->lv_len; CHECK_LIST_MATERIALIZE(l1); CHECK_LIST_MATERIALIZE(l2); @@ -854,15 +859,17 @@ list_concat(list_T *l1, list_T *l2, typval_T *tv) { list_T *l; - if (l1 == NULL || l2 == NULL) - return FAIL; - // make a copy of the first list. - l = list_copy(l1, FALSE, 0); + if (l1 == NULL) + l = list_alloc(); + else + l = list_copy(l1, FALSE, 0); if (l == NULL) return FAIL; tv->v_type = VAR_LIST; tv->vval.v_list = l; + if (l1 == NULL) + ++l->lv_refcount; // append all items from the second list return list_extend(l, l2, NULL); diff --git a/src/testdir/test_vim9_assign.vim b/src/testdir/test_vim9_assign.vim index 189ff4da01..1b56df54b5 100644 --- a/src/testdir/test_vim9_assign.vim +++ b/src/testdir/test_vim9_assign.vim @@ -236,6 +236,18 @@ def Test_extend_list() assert_equal(#{one: 1}, d) END CheckScriptSuccess(lines) + + # appending to NULL list from a function + lines =<< trim END + vim9script + var list: list + def Func() + list += ['a', 'b'] + enddef + Func() + assert_equal(['a', 'b'], list) + END + CheckScriptSuccess(lines) enddef def Test_single_letter_vars() diff --git a/src/version.c b/src/version.c index 8e2115e5d3..8dabd60597 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1821, /**/ 1820, /**/ From f57497276bc616d3856eeff9824c080941faa51b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 16:42:39 +0200 Subject: [PATCH 17/25] patch 8.2.1822: list test doesn't fail Problem: List test doesn't fail. Solution: Adjust the test for NULL list handling. --- src/testdir/test_listdict.vim | 6 ++++-- src/version.c | 2 ++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/testdir/test_listdict.vim b/src/testdir/test_listdict.vim index 54486ff49a..9085c6e006 100644 --- a/src/testdir/test_listdict.vim +++ b/src/testdir/test_listdict.vim @@ -1007,8 +1007,10 @@ func Test_null_list() call assert_equal('[]', string(l)) call assert_equal(0, sort(l)) call assert_equal(0, uniq(l)) - call assert_fails("let k = [] + l", 'E15:') - call assert_fails("let k = l + []", 'E15:') + let k = [] + l + call assert_equal([], k) + let k = l + [] + call assert_equal([], k) call assert_equal(0, len(copy(l))) call assert_equal(0, count(l, 5)) call assert_equal([], deepcopy(l)) diff --git a/src/version.c b/src/version.c index 8dabd60597..e0bcc90129 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1822, /**/ 1821, /**/ From 28f224b2c1bd2fcdee7b4fe2c64826e1cff08f39 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 16:45:25 +0200 Subject: [PATCH 18/25] patch 8.2.1823: "gN" does not select the matched string Problem: "gN" does not select the matched string. Solution: Move the cursor to the start of the match. --- src/search.c | 2 +- src/testdir/test_gn.vim | 11 ++++++++++- src/version.c | 2 ++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/search.c b/src/search.c index fd668383b7..45e4f9c1ab 100644 --- a/src/search.c +++ b/src/search.c @@ -3047,7 +3047,7 @@ current_search( curwin->w_cursor = end_pos; if (LT_POS(VIsual, end_pos) && forward) dec_cursor(); - else if (VIsual_active && LT_POS(curwin->w_cursor, VIsual)) + else if (VIsual_active && LT_POS(curwin->w_cursor, VIsual) && forward) curwin->w_cursor = pos; // put the cursor on the start of the match VIsual_active = TRUE; VIsual_mode = 'v'; diff --git a/src/testdir/test_gn.vim b/src/testdir/test_gn.vim index b90aa5f1d6..a2a7ac3f0f 100644 --- a/src/testdir/test_gn.vim +++ b/src/testdir/test_gn.vim @@ -172,7 +172,16 @@ func Test_gn_command() normal 0wgNy call assert_equal('one', @") set selection& -endfu +endfunc + +func Test_gN_repeat() + new + call setline(1, 'this list is a list with a list of a list.') + /list + normal $gNgNgNx + call assert_equal('list with a list of a list', @") + bwipe! +endfunc func Test_gn_multi_line() new diff --git a/src/version.c b/src/version.c index e0bcc90129..e30c02dd15 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1823, /**/ 1822, /**/ From fcdc5d83fbfd7ddce634769ea902e58c87f27f20 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 19:07:09 +0200 Subject: [PATCH 19/25] patch 8.2.1824: Vim9: variables at the script level escape their scope Problem: Vim9: variables at the script level escape their scope. Solution: When leaving a scope remove variables declared in it. --- src/evalvars.c | 3 +- src/ex_eval.c | 68 ++++++++++++++++++++++++++------ src/proto/evalvars.pro | 1 + src/structs.h | 2 + src/testdir/test_vim9_script.vim | 50 +++++++++++++++++++++++ src/version.c | 2 + 6 files changed, 112 insertions(+), 14 deletions(-) diff --git a/src/evalvars.c b/src/evalvars.c index f7ee58d531..2455046d93 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -174,7 +174,6 @@ static char_u *list_arg_vars(exarg_T *eap, char_u *arg, int *first); static char_u *ex_let_one(char_u *arg, typval_T *tv, int copy, int flags, char_u *endchars, char_u *op); static int do_unlet_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie); static int do_lock_var(lval_T *lp, char_u *name_end, exarg_T *eap, int deep, void *cookie); -static void delete_var(hashtab_T *ht, hashitem_T *hi); static void list_one_var(dictitem_T *v, char *prefix, int *first); static void list_one_var_a(char *prefix, char_u *name, int type, char_u *string, int *first); @@ -2890,7 +2889,7 @@ vars_clear_ext(hashtab_T *ht, int free_val) * Delete a variable from hashtab "ht" at item "hi". * Clear the variable value and free the dictitem. */ - static void + void delete_var(hashtab_T *ht, hashitem_T *hi) { dictitem_T *di = HI2DI(hi); diff --git a/src/ex_eval.c b/src/ex_eval.c index cbdf82e893..6a7087b683 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -905,6 +905,48 @@ ex_eval(exarg_T *eap) clear_evalarg(&evalarg, eap); } +/* + * Start a new scope/block. Caller should have checked that cs_idx is not + * exceeding CSTACK_LEN. + */ + static void +enter_block(cstack_T *cstack) +{ + ++cstack->cs_idx; + if (in_vim9script()) + cstack->cs_script_var_len[cstack->cs_idx] = + SCRIPT_ITEM(current_sctx.sc_sid)->sn_var_vals.ga_len; +} + + static void +leave_block(cstack_T *cstack) +{ + int i; + + if (in_vim9script()) + { + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + + for (i = cstack->cs_script_var_len[cstack->cs_idx]; + i < si->sn_var_vals.ga_len; ++i) + { + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; + hashtab_T *ht = get_script_local_ht(); + hashitem_T *hi; + + if (ht != NULL) + { + // Remove a variable declared inside the block, if it still + // exists. + hi = hash_find(ht, sv->sv_name); + if (!HASHITEM_EMPTY(hi)) + delete_var(ht, hi); + } + } + } + --cstack->cs_idx; +} + /* * ":if". */ @@ -920,12 +962,12 @@ ex_if(exarg_T *eap) eap->errmsg = _("E579: :if nesting too deep"); else { - ++cstack->cs_idx; + enter_block(cstack); cstack->cs_flags[cstack->cs_idx] = 0; /* - * Don't do something after an error, interrupt, or throw, or when there - * is a surrounding conditional and it was not active. + * Don't do something after an error, interrupt, or throw, or when + * there is a surrounding conditional and it was not active. */ skip = did_emsg || got_int || did_throw || (cstack->cs_idx > 0 && !(cstack->cs_flags[cstack->cs_idx - 1] & CSF_ACTIVE)); @@ -949,9 +991,11 @@ ex_if(exarg_T *eap) void ex_endif(exarg_T *eap) { + cstack_T *cstack = eap->cstack; + did_endif = TRUE; - if (eap->cstack->cs_idx < 0 - || (eap->cstack->cs_flags[eap->cstack->cs_idx] + if (cstack->cs_idx < 0 + || (cstack->cs_flags[cstack->cs_idx] & (CSF_WHILE | CSF_FOR | CSF_TRY))) eap->errmsg = _(e_endif_without_if); else @@ -965,11 +1009,11 @@ ex_endif(exarg_T *eap) * Doing this here prevents an exception for a parsing error being * discarded by throwing the interrupt exception later on. */ - if (!(eap->cstack->cs_flags[eap->cstack->cs_idx] & CSF_TRUE) + if (!(cstack->cs_flags[cstack->cs_idx] & CSF_TRUE) && dbg_check_skipped(eap)) - (void)do_intthrow(eap->cstack); + (void)do_intthrow(cstack); - --eap->cstack->cs_idx; + leave_block(cstack); } } @@ -1086,7 +1130,7 @@ ex_while(exarg_T *eap) */ if ((cstack->cs_lflags & CSL_HAD_LOOP) == 0) { - ++cstack->cs_idx; + enter_block(cstack); ++cstack->cs_looplevel; cstack->cs_line[cstack->cs_idx] = -1; } @@ -1450,7 +1494,7 @@ ex_try(exarg_T *eap) eap->errmsg = _("E601: :try nesting too deep"); else { - ++cstack->cs_idx; + enter_block(cstack); ++cstack->cs_trylevel; cstack->cs_flags[cstack->cs_idx] = CSF_TRY; cstack->cs_pending[cstack->cs_idx] = CSTP_NONE; @@ -1923,7 +1967,7 @@ ex_endtry(exarg_T *eap) */ (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, TRUE); - --cstack->cs_idx; + leave_block(cstack); --cstack->cs_trylevel; if (!skip) @@ -2303,7 +2347,7 @@ rewind_conditionals( --*cond_level; if (cstack->cs_flags[cstack->cs_idx] & CSF_FOR) free_for_info(cstack->cs_forinfo[cstack->cs_idx]); - --cstack->cs_idx; + leave_block(cstack); } } diff --git a/src/proto/evalvars.pro b/src/proto/evalvars.pro index 520fedd5ef..39ea33893a 100644 --- a/src/proto/evalvars.pro +++ b/src/proto/evalvars.pro @@ -67,6 +67,7 @@ void init_var_dict(dict_T *dict, dictitem_T *dict_var, int scope); void unref_var_dict(dict_T *dict); void vars_clear(hashtab_T *ht); void vars_clear_ext(hashtab_T *ht, int free_val); +void delete_var(hashtab_T *ht, hashitem_T *hi); void set_var(char_u *name, typval_T *tv, int copy); void set_var_const(char_u *name, type_T *type, typval_T *tv_arg, int copy, int flags); int var_check_ro(int flags, char_u *name, int use_gettext); diff --git a/src/structs.h b/src/structs.h index 0a3d524e7b..094b736ad2 100644 --- a/src/structs.h +++ b/src/structs.h @@ -889,6 +889,8 @@ typedef struct { } cs_pend; void *cs_forinfo[CSTACK_LEN]; // info used by ":for" int cs_line[CSTACK_LEN]; // line nr of ":while"/":for" line + int cs_script_var_len[CSTACK_LEN]; // value of sn_var_vals.ga_len + // when entering the block int cs_idx; // current entry, or -1 if none int cs_looplevel; // nr of nested ":while"s and ":for"s int cs_trylevel; // nr of nested ":try"s diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 02bc56b2fa..466b2d0788 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2685,6 +2685,56 @@ def Run_Test_define_func_at_command_line() delete('Xdidcmd') enddef +def Test_script_var_scope() + var lines =<< trim END + vim9script + if true + if true + var one = 'one' + echo one + endif + echo one + endif + END + CheckScriptFailure(lines, 'E121:', 7) + + lines =<< trim END + vim9script + if true + if false + var one = 'one' + echo one + else + var one = 'one' + echo one + endif + echo one + endif + END + CheckScriptFailure(lines, 'E121:', 10) + + lines =<< trim END + vim9script + while true + var one = 'one' + echo one + break + endwhile + echo one + END + CheckScriptFailure(lines, 'E121:', 7) + + lines =<< trim END + vim9script + for i in range(1) + var one = 'one' + echo one + endfor + echo one + END + CheckScriptFailure(lines, 'E121:', 6) +enddef + " Keep this last, it messes up highlighting. def Test_substitute_cmd() new diff --git a/src/version.c b/src/version.c index e30c02dd15..e7e863be16 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1824, /**/ 1823, /**/ From d747548c664815bb6e8520afa90b6108e1997591 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 20:31:37 +0200 Subject: [PATCH 20/25] patch 8.2.1825: Vim9: accessing freed memory Problem: Vim9: accessing freed memory. Solution: Clear sv_name when the variable is deleted. --- src/ex_eval.c | 32 +++++++++++++++++++------------- src/version.c | 2 ++ 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/src/ex_eval.c b/src/ex_eval.c index 6a7087b683..d205cafc47 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -925,22 +925,28 @@ leave_block(cstack_T *cstack) if (in_vim9script()) { - scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + scriptitem_T *si = SCRIPT_ITEM(current_sctx.sc_sid); + hashtab_T *ht = get_script_local_ht(); - for (i = cstack->cs_script_var_len[cstack->cs_idx]; - i < si->sn_var_vals.ga_len; ++i) + if (ht != NULL) { - svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; - hashtab_T *ht = get_script_local_ht(); - hashitem_T *hi; - - if (ht != NULL) + for (i = cstack->cs_script_var_len[cstack->cs_idx]; + i < si->sn_var_vals.ga_len; ++i) { - // Remove a variable declared inside the block, if it still - // exists. - hi = hash_find(ht, sv->sv_name); - if (!HASHITEM_EMPTY(hi)) - delete_var(ht, hi); + svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + i; + hashitem_T *hi; + + if (sv->sv_name != NULL) + { + // Remove a variable declared inside the block, if it still + // exists. + hi = hash_find(ht, sv->sv_name); + if (!HASHITEM_EMPTY(hi)) + { + delete_var(ht, hi); + sv->sv_name = NULL; + } + } } } } diff --git a/src/version.c b/src/version.c index e7e863be16..789e104938 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1825, /**/ 1824, /**/ From 9becdf2b98e56d5eb193f3413d706ea433269216 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 21:33:48 +0200 Subject: [PATCH 21/25] patch 8.2.1826: Vim9: cannot use a {} block at script level Problem: Vim9: cannot use a {} block at script level. Solution: Recognize a {} block. --- src/errors.h | 2 ++ src/ex_cmdidxs.h | 2 +- src/ex_cmds.h | 6 ++++++ src/ex_docmd.c | 10 +++++++-- src/ex_eval.c | 35 ++++++++++++++++++++++++++++++-- src/proto/ex_eval.pro | 2 ++ src/structs.h | 1 + src/testdir/test_vim9_script.vim | 21 +++++++++++++++++++ src/version.c | 2 ++ 9 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/errors.h b/src/errors.h index cddd6910fe..c2dc633f16 100644 --- a/src/errors.h +++ b/src/errors.h @@ -278,4 +278,6 @@ EXTERN char e_cannot_use_let_in_vim9_script[] INIT(= N_("E1126: Cannot use :let in Vim9 script")); EXTERN char e_missing_name_after_dot[] INIT(= N_("E1127: Missing name after dot")); +EXTERN char e_endblock_without_block[] + INIT(= N_("E1128: } without {")); #endif diff --git a/src/ex_cmdidxs.h b/src/ex_cmdidxs.h index 0f9eb39ff6..2e59d2c502 100644 --- a/src/ex_cmdidxs.h +++ b/src/ex_cmdidxs.h @@ -69,4 +69,4 @@ static const unsigned char cmdidxs2[26][26] = /* z */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; -static const int command_count = 571; +static const int command_count = 573; diff --git a/src/ex_cmds.h b/src/ex_cmds.h index 0c83f521f6..0b52c11ee0 100644 --- a/src/ex_cmds.h +++ b/src/ex_cmds.h @@ -1812,6 +1812,12 @@ EXCMD(CMD_rshift, ">", ex_operators, EXCMD(CMD_at, "@", ex_at, EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, ADDR_LINES), +EXCMD(CMD_block, "{{{{{{{{", ex_block, // not found normally + 0, + ADDR_NONE), +EXCMD(CMD_endblock, "}", ex_endblock, + EX_TRLBAR|EX_CMDWIN|EX_LOCK_OK, + ADDR_NONE), EXCMD(CMD_tilde, "~", ex_substitute, EX_RANGE|EX_WHOLEFOLD|EX_EXTRA|EX_CMDWIN|EX_LOCK_OK|EX_MODIFY, ADDR_LINES), diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 310934ed71..4a71989ddb 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3222,7 +3222,7 @@ find_ex_command( *p == '(' || (p == eap->cmd ? ( - // "{..." is an dict expression. + // "{..." is a dict expression or block start. *eap->cmd == '{' // "'string'->func()" is an expression. || *eap->cmd == '\'' @@ -3234,6 +3234,12 @@ find_ex_command( // "varname->func()" is an expression. : (*p == '-' && p[1] == '>'))) { + if (*eap->cmd == '{' && ends_excmd(*skipwhite(eap->cmd + 1))) + { + // "{" by itself is the start of a block. + eap->cmdidx = CMD_block; + return eap->cmd + 1; + } eap->cmdidx = CMD_eval; return eap->cmd; } @@ -3355,7 +3361,7 @@ find_ex_command( } // check for non-alpha command - if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#", *p) != NULL) + if (p == eap->cmd && vim_strchr((char_u *)"@*!=><&~#}", *p) != NULL) ++p; len = (int)(p - eap->cmd); if (*eap->cmd == 'd' && (p[-1] == 'l' || p[-1] == 'p')) diff --git a/src/ex_eval.c b/src/ex_eval.c index d205cafc47..57c6178727 100644 --- a/src/ex_eval.c +++ b/src/ex_eval.c @@ -1002,7 +1002,7 @@ ex_endif(exarg_T *eap) did_endif = TRUE; if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] - & (CSF_WHILE | CSF_FOR | CSF_TRY))) + & (CSF_WHILE | CSF_FOR | CSF_TRY | CSF_BLOCK))) eap->errmsg = _(e_endif_without_if); else { @@ -1043,7 +1043,7 @@ ex_else(exarg_T *eap) if (cstack->cs_idx < 0 || (cstack->cs_flags[cstack->cs_idx] - & (CSF_WHILE | CSF_FOR | CSF_TRY))) + & (CSF_WHILE | CSF_FOR | CSF_TRY | CSF_BLOCK))) { if (eap->cmdidx == CMD_else) { @@ -1375,6 +1375,37 @@ ex_endwhile(exarg_T *eap) } } +/* + * "{" start of a block in Vim9 script + */ + void +ex_block(exarg_T *eap) +{ + cstack_T *cstack = eap->cstack; + + if (cstack->cs_idx == CSTACK_LEN - 1) + eap->errmsg = _("E579: block nesting too deep"); + else + { + enter_block(cstack); + cstack->cs_flags[cstack->cs_idx] = CSF_BLOCK | CSF_ACTIVE | CSF_TRUE; + } +} + +/* + * "}" end of a block in Vim9 script + */ + void +ex_endblock(exarg_T *eap) +{ + cstack_T *cstack = eap->cstack; + + if (cstack->cs_idx < 0 + || (cstack->cs_flags[cstack->cs_idx] & CSF_BLOCK) == 0) + eap->errmsg = _(e_endblock_without_block); + else + leave_block(cstack); +} /* * ":throw expr" diff --git a/src/proto/ex_eval.pro b/src/proto/ex_eval.pro index 929f47987f..f1861612a5 100644 --- a/src/proto/ex_eval.pro +++ b/src/proto/ex_eval.pro @@ -20,6 +20,8 @@ void ex_while(exarg_T *eap); void ex_continue(exarg_T *eap); void ex_break(exarg_T *eap); void ex_endwhile(exarg_T *eap); +void ex_block(exarg_T *eap); +void ex_endblock(exarg_T *eap); void ex_throw(exarg_T *eap); void do_throw(cstack_T *cstack); void ex_try(exarg_T *eap); diff --git a/src/structs.h b/src/structs.h index 094b736ad2..103c70c5e8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -907,6 +907,7 @@ typedef struct { # define CSF_ELSE 0x0004 // ":else" has been passed # define CSF_WHILE 0x0008 // is a ":while" # define CSF_FOR 0x0010 // is a ":for" +# define CSF_BLOCK 0x0020 // is a "{" block # define CSF_TRY 0x0100 // is a ":try" # define CSF_FINALLY 0x0200 // ":finally" has been passed diff --git a/src/testdir/test_vim9_script.vim b/src/testdir/test_vim9_script.vim index 466b2d0788..1edc773cc1 100644 --- a/src/testdir/test_vim9_script.vim +++ b/src/testdir/test_vim9_script.vim @@ -2733,6 +2733,27 @@ def Test_script_var_scope() echo one END CheckScriptFailure(lines, 'E121:', 6) + + lines =<< trim END + vim9script + { + var one = 'one' + assert_equal('one', one) + } + assert_false(exists('one')) + assert_false(exists('s:one')) + END + CheckScriptSuccess(lines) + + lines =<< trim END + vim9script + { + var one = 'one' + echo one + } + echo one + END + CheckScriptFailure(lines, 'E121:', 6) enddef " Keep this last, it messes up highlighting. diff --git a/src/version.c b/src/version.c index 789e104938..6ff2aa08db 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1826, /**/ 1825, /**/ From 10a1a534d1ae1d798bb695f9a521052ebbf1e289 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 21:50:25 +0200 Subject: [PATCH 22/25] patch 8.2.1827: filetype detection does not test enough file names Problem: Filetype detection does not test enough file names. Solution: Test more file names. (Adam Stankiewicz, closes #7099) --- runtime/filetype.vim | 7 -- src/testdir/test_filetype.vim | 194 ++++++++++++++++++---------------- src/version.c | 2 + 3 files changed, 107 insertions(+), 96 deletions(-) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 2b134c22b6..b647e25a42 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -1342,13 +1342,6 @@ au BufNewFile,BufRead *.rego setf rego " Rexx au BufNewFile,BufRead *.rex,*.orx,*.rxo,*.rxj,*.jrexx,*.rexxj,*.rexx,*.testGroup,*.testUnit setf rexx -" R (Splus) -if has("fname_case") - au BufNewFile,BufRead *.s,*.S setf r -else - au BufNewFile,BufRead *.s setf r -endif - " R Help file if has("fname_case") au BufNewFile,BufRead *.rd,*.Rd setf rhelp diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index d871b49c3b..9d997cbcfc 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -45,7 +45,7 @@ endfunc " Filetypes detected just from matching the file name. let s:filename_checks = { \ '8th': ['file.8th'], - \ 'a2ps': ['/etc/a2ps.cfg', '/etc/a2ps/file.cfg', 'a2psrc', '.a2psrc'], + \ 'a2ps': ['/etc/a2ps.cfg', '/etc/a2ps/file.cfg', 'a2psrc', '.a2psrc', 'any/etc/a2ps.cfg', 'any/etc/a2ps/file.cfg'], \ 'a65': ['file.a65'], \ 'aap': ['file.aap'], \ 'abap': ['file.abap'], @@ -55,23 +55,24 @@ let s:filename_checks = { \ 'ada': ['file.adb', 'file.ads', 'file.ada', 'file.gpr'], \ 'ahdl': ['file.tdf'], \ 'aidl': ['file.aidl'], - \ 'alsaconf': ['.asoundrc', '/usr/share/alsa/alsa.conf', '/etc/asound.conf'], + \ 'alsaconf': ['.asoundrc', '/usr/share/alsa/alsa.conf', '/etc/asound.conf', 'any/etc/asound.conf', 'any/usr/share/alsa/alsa.conf'], \ 'aml': ['file.aml'], \ 'ampl': ['file.run'], \ 'ant': ['build.xml'], - \ 'apache': ['.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config'], - \ 'apachestyle': ['/etc/proftpd/file.config,/etc/proftpd/conf.file/file'], + \ 'apache': ['.htaccess', '/etc/httpd/file.conf', '/etc/apache2/sites-2/file.com', '/etc/apache2/some.config', '/etc/apache2/conf.file/conf', '/etc/apache2/mods-some/file', '/etc/apache2/sites-some/file', '/etc/httpd/conf.d/file.config', '/etc/apache2/conf.file/file', '/etc/apache2/file.conf', '/etc/apache2/file.conf-file', '/etc/apache2/mods-file/file', '/etc/apache2/sites-file/file', '/etc/apache2/sites-file/file.com', '/etc/httpd/conf.d/file.conf', '/etc/httpd/conf.d/file.conf-file', 'access.conf', 'access.conf-file', 'any/etc/apache2/conf.file/file', 'any/etc/apache2/file.conf', 'any/etc/apache2/file.conf-file', 'any/etc/apache2/mods-file/file', 'any/etc/apache2/sites-file/file', 'any/etc/apache2/sites-file/file.com', 'any/etc/httpd/conf.d/file.conf', 'any/etc/httpd/conf.d/file.conf-file', 'any/etc/httpd/file.conf', 'apache.conf', 'apache.conf-file', 'apache2.conf', 'apache2.conf-file', 'httpd.conf', 'httpd.conf-file', 'srm.conf', 'srm.conf-file'], + \ 'apachestyle': ['/etc/proftpd/file.config,/etc/proftpd/conf.file/file', '/etc/proftpd/conf.file/file', '/etc/proftpd/file.conf', '/etc/proftpd/file.conf-file', 'any/etc/proftpd/conf.file/file', 'any/etc/proftpd/file.conf', 'any/etc/proftpd/file.conf-file', 'proftpd.conf', 'proftpd.conf-file'], \ 'applescript': ['file.scpt'], - \ 'aptconf': ['apt.conf', '/.aptitude/config'], - \ 'arch': ['.arch-inventory'], + \ 'aptconf': ['apt.conf', '/.aptitude/config', 'any/.aptitude/config'], + \ 'arch': ['.arch-inventory', '=tagging-method'], \ 'arduino': ['file.ino', 'file.pde'], \ 'art': ['file.art'], \ 'asciidoc': ['file.asciidoc', 'file.adoc'], \ 'asn': ['file.asn', 'file.asn1'], + \ 'asterisk': ['asterisk/file.conf', 'asterisk/file.conf-file', 'some-asterisk/file.conf', 'some-asterisk/file.conf-file'], \ 'atlas': ['file.atl', 'file.as'], \ 'autohotkey': ['file.ahk'], \ 'autoit': ['file.au3'], - \ 'automake': ['GNUmakefile.am'], + \ 'automake': ['GNUmakefile.am', 'makefile.am', 'Makefile.am'], \ 'ave': ['file.ave'], \ 'awk': ['file.awk', 'file.gawk'], \ 'b': ['file.mch', 'file.ref', 'file.imp'], @@ -79,21 +80,21 @@ let s:filename_checks = { \ 'bc': ['file.bc'], \ 'bdf': ['file.bdf'], \ 'bib': ['file.bib'], - \ 'bindzone': ['named.root'], + \ 'bindzone': ['named.root', '/bind/db.file', '/named/db.file', 'any/bind/db.file', 'any/named/db.file'], \ 'blank': ['file.bl'], - \ 'bsdl': ['file.bsd', 'file.bsdl'], + \ 'bsdl': ['file.bsd', 'file.bsdl', 'bsd', 'some-bsd'], \ 'bst': ['file.bst'], - \ 'bzr': ['bzr_log.any'], - \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c'], + \ 'bzr': ['bzr_log.any', 'bzr_log.file'], + \ 'c': ['enlightenment/file.cfg', 'file.qc', 'file.c', 'some-enlightenment/file.cfg'], \ 'cabal': ['file.cabal'], - \ 'calendar': ['calendar'], - \ 'catalog': ['catalog', 'sgml.catalogfile'], + \ 'calendar': ['calendar', '/.calendar/file', '/share/calendar/any/calendar.file', '/share/calendar/calendar.file', 'any/share/calendar/any/calendar.file', 'any/share/calendar/calendar.file'], + \ 'catalog': ['catalog', 'sgml.catalogfile', 'sgml.catalog', 'sgml.catalog-file'], \ 'cdl': ['file.cdl'], - \ 'cdrdaoconf': ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao'], + \ 'cdrdaoconf': ['/etc/cdrdao.conf', '/etc/defaults/cdrdao', '/etc/default/cdrdao', '.cdrdao', 'any/etc/cdrdao.conf', 'any/etc/default/cdrdao', 'any/etc/defaults/cdrdao'], \ 'cdrtoc': ['file.toc'], \ 'cf': ['file.cfm', 'file.cfi', 'file.cfc'], \ 'cfengine': ['cfengine.conf'], - \ 'cfg': ['file.cfg', 'file.hgrc', 'filehgrc'], + \ 'cfg': ['file.cfg', 'file.hgrc', 'filehgrc', 'hgrc', 'some-hgrc'], \ 'ch': ['file.chf'], \ 'chaiscript': ['file.chai'], \ 'chaskell': ['file.chs'], @@ -103,15 +104,16 @@ let s:filename_checks = { \ 'clean': ['file.dcl', 'file.icl'], \ 'clojure': ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'], \ 'cmake': ['CMakeLists.txt', 'file.cmake', 'file.cmake.in'], - \ 'cmusrc': ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme'], + \ 'cmusrc': ['any/.cmus/autosave', 'any/.cmus/rc', 'any/.cmus/command-history', 'any/.cmus/file.theme', 'any/cmus/rc', 'any/cmus/file.theme', '/.cmus/autosave', '/.cmus/command-history', '/.cmus/file.theme', '/.cmus/rc', '/cmus/file.theme', '/cmus/rc'], \ 'cobol': ['file.cbl', 'file.cob', 'file.lib'], \ 'coco': ['file.atg'], \ 'conaryrecipe': ['file.recipe'], \ 'conf': ['auto.master'], - \ 'config': ['configure.in', 'configure.ac', 'Pipfile'], + \ 'config': ['configure.in', 'configure.ac', 'Pipfile', '/etc/hostname.file'], \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi'], \ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'], \ 'crm': ['file.crm'], + \ 'crontab': ['crontab', 'crontab.file', '/etc/cron.d/file', 'any/etc/cron.d/file'], \ 'cs': ['file.cs'], \ 'csc': ['file.csc'], \ 'csdl': ['file.csdl'], @@ -119,7 +121,7 @@ let s:filename_checks = { \ 'css': ['file.css'], \ 'cterm': ['file.con'], \ 'cucumber': ['file.feature'], - \ 'cuda': ['file.cu'], + \ 'cuda': ['file.cu', 'file.cuh'], \ 'cupl': ['file.pld'], \ 'cuplsim': ['file.si'], \ 'cvs': ['cvs123'], @@ -129,8 +131,9 @@ let s:filename_checks = { \ 'datascript': ['file.ds'], \ 'dcd': ['file.dcd'], \ 'debchangelog': ['changelog.Debian', 'changelog.dch', 'NEWS.Debian', 'NEWS.dch', '/debian/changelog'], - \ 'debcontrol': ['/debian/control'], - \ 'debsources': ['/etc/apt/sources.list', '/etc/apt/sources.list.d/file.list'], + \ 'debcontrol': ['/debian/control', 'any/debian/control'], + \ 'debcopyright': ['/debian/copyright', 'any/debian/copyright'], + \ 'debsources': ['/etc/apt/sources.list', '/etc/apt/sources.list.d/file.list', 'any/etc/apt/sources.list', 'any/etc/apt/sources.list.d/file.list'], \ 'def': ['file.def'], \ 'denyhosts': ['denyhosts.conf'], \ 'desc': ['file.desc'], @@ -138,13 +141,13 @@ let s:filename_checks = { \ 'dictconf': ['dict.conf', '.dictrc'], \ 'dictdconf': ['dictd.conf'], \ 'diff': ['file.diff', 'file.rej'], - \ 'dircolors': ['.dir_colors', '.dircolors', '/etc/DIR_COLORS'], - \ 'dnsmasq': ['/etc/dnsmasq.conf'], + \ 'dircolors': ['.dir_colors', '.dircolors', '/etc/DIR_COLORS', 'any/etc/DIR_COLORS'], + \ 'dnsmasq': ['/etc/dnsmasq.conf', '/etc/dnsmasq.d/file', 'any/etc/dnsmasq.conf', 'any/etc/dnsmasq.d/file'], \ 'dockerfile': ['Containerfile', 'Dockerfile', 'file.Dockerfile'], \ 'dosbatch': ['file.bat', 'file.sys'], - \ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5'], + \ 'dosini': ['.editorconfig', '/etc/pacman.conf', '/etc/yum.conf', 'file.ini', 'npmrc', '.npmrc', 'php.ini', 'php.ini-5', 'php.ini-file', '/etc/yum.repos.d/file', 'any/etc/pacman.conf', 'any/etc/yum.conf', 'any/etc/yum.repos.d/file'], \ 'dot': ['file.dot', 'file.gv'], - \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe'], + \ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'], \ 'dsl': ['file.dsl'], \ 'dtd': ['file.dtd'], \ 'dts': ['file.dts', 'file.dtsi'], @@ -158,10 +161,10 @@ let s:filename_checks = { \ 'elmfilt': ['filter-rules'], \ 'erlang': ['file.erl', 'file.hrl', 'file.yaws'], \ 'eruby': ['file.erb', 'file.rhtml'], - \ 'esmtprc': ['anyesmtprc'], + \ 'esmtprc': ['anyesmtprc', 'esmtprc', 'some-esmtprc'], \ 'esqlc': ['file.ec', 'file.EC'], \ 'esterel': ['file.strl'], - \ 'eterm': ['anyEterm/file.cfg'], + \ 'eterm': ['anyEterm/file.cfg', 'Eterm/file.cfg', 'some-Eterm/file.cfg'], \ 'exim': ['exim.conf'], \ 'expect': ['file.exp'], \ 'exports': ['exports'], @@ -176,12 +179,13 @@ let s:filename_checks = { \ 'framescript': ['file.fsl'], \ 'freebasic': ['file.fb', 'file.bi'], \ 'fstab': ['fstab', 'mtab'], + \ 'fvwm': ['/.fvwm/file', 'any/.fvwm/file'], \ 'gdb': ['.gdbinit'], \ 'gdmo': ['file.mo', 'file.gdmo'], - \ 'gedcom': ['file.ged', 'lltxxxxx.txt'], + \ 'gedcom': ['file.ged', 'lltxxxxx.txt', '/tmp/lltmp', '/tmp/lltmp-file', 'any/tmp/lltmp', 'any/tmp/lltmp-file'], \ 'gitcommit': ['COMMIT_EDITMSG', 'MERGE_MSG', 'TAG_EDITMSG'], - \ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig'], - \ 'gitolite': ['gitolite.conf'], + \ 'gitconfig': ['file.git/config', '.gitconfig', '.gitmodules', 'file.git/modules//config', '/.config/git/config', '/etc/gitconfig', '/etc/gitconfig.d/file', '/.gitconfig.d/file', 'any/.config/git/config', 'any/.gitconfig.d/file', 'some.git/config', 'some.git/modules/any/config'], + \ 'gitolite': ['gitolite.conf', '/gitolite-admin/conf/file', 'any/gitolite-admin/conf/file'], \ 'gitrebase': ['git-rebase-todo'], \ 'gitsendemail': ['.gitsendemail.msg.xxxxxx'], \ 'gkrellmrc': ['gkrellmrc', 'gkrellmrc_x'], @@ -189,14 +193,14 @@ let s:filename_checks = { \ 'gnuplot': ['file.gpi'], \ 'go': ['file.go'], \ 'gp': ['file.gp', '.gprc'], - \ 'gpg': ['/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel'], + \ 'gpg': ['/.gnupg/options', '/.gnupg/gpg.conf', '/usr/any/gnupg/options.skel', 'any/.gnupg/gpg.conf', 'any/.gnupg/options', 'any/usr/any/gnupg/options.skel'], \ 'grads': ['file.gs'], \ 'gretl': ['file.gretl'], \ 'groovy': ['file.gradle', 'file.groovy'], - \ 'group': ['any/etc/group', 'any/etc/group-', 'any/etc/group.edit', 'any/etc/gshadow', 'any/etc/gshadow-', 'any/etc/gshadow.edit', 'any/var/backups/group.bak', 'any/var/backups/gshadow.bak'], - \ 'grub': ['/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf'], + \ 'group': ['any/etc/group', 'any/etc/group-', 'any/etc/group.edit', 'any/etc/gshadow', 'any/etc/gshadow-', 'any/etc/gshadow.edit', 'any/var/backups/group.bak', 'any/var/backups/gshadow.bak', '/etc/group', '/etc/group-', '/etc/group.edit', '/etc/gshadow', '/etc/gshadow-', '/etc/gshadow.edit', '/var/backups/group.bak', '/var/backups/gshadow.bak'], + \ 'grub': ['/boot/grub/menu.lst', '/boot/grub/grub.conf', '/etc/grub.conf', 'any/boot/grub/grub.conf', 'any/boot/grub/menu.lst', 'any/etc/grub.conf'], \ 'gsp': ['file.gsp'], - \ 'gtkrc': ['.gtkrc', 'gtkrc'], + \ 'gtkrc': ['.gtkrc', 'gtkrc', '.gtkrc-file', 'gtkrc-file'], \ 'haml': ['file.haml'], \ 'hamster': ['file.hsc', 'file.hsm'], \ 'haskell': ['file.hs', 'file.hs-boot'], @@ -208,24 +212,35 @@ let s:filename_checks = { \ 'hgcommit': ['hg-editor-file.txt'], \ 'hog': ['file.hog', 'snort.conf', 'vision.conf'], \ 'hollywood': ['file.hws'], - \ 'hostconf': ['/etc/host.conf'], - \ 'hostsaccess': ['/etc/hosts.allow', '/etc/hosts.deny'], + \ 'hostconf': ['/etc/host.conf', 'any/etc/host.conf'], + \ 'hostsaccess': ['/etc/hosts.allow', '/etc/hosts.deny', 'any/etc/hosts.allow', 'any/etc/hosts.deny'], + \ 'logcheck': ['/etc/logcheck/file.d-some/file', '/etc/logcheck/file.d/file', 'any/etc/logcheck/file.d-some/file', 'any/etc/logcheck/file.d/file'], + \ 'modula3': ['file.m3', 'file.mg', 'file.i3', 'file.ig'], + \ 'natural': ['file.NSA', 'file.NSC', 'file.NSG', 'file.NSL', 'file.NSM', 'file.NSN', 'file.NSP', 'file.NSS'], + \ 'neomuttrc': ['Neomuttrc', '.neomuttrc', '.neomuttrc-file', '/.neomutt/neomuttrc', '/.neomutt/neomuttrc-file', 'Neomuttrc', 'Neomuttrc-file', 'any/.neomutt/neomuttrc', 'any/.neomutt/neomuttrc-file', 'neomuttrc', 'neomuttrc-file'], + \ 'opl': ['file.OPL', 'file.OPl', 'file.OpL', 'file.Opl', 'file.oPL', 'file.oPl', 'file.opL', 'file.opl'], + \ 'pcmk': ['file.pcmk'], + \ 'r': ['file.r'], + \ 'rhelp': ['file.rd'], + \ 'rmd': ['file.rmd', 'file.smd'], + \ 'rnoweb': ['file.rnw', 'file.snw'], + \ 'rrst': ['file.rrst', 'file.srst'], \ 'template': ['file.tmpl'], \ 'htmlm4': ['file.html.m4'], \ 'httest': ['file.htt', 'file.htb'], \ 'ibasic': ['file.iba', 'file.ibi'], - \ 'icemenu': ['/.icewm/menu'], + \ 'icemenu': ['/.icewm/menu', 'any/.icewm/menu'], \ 'icon': ['file.icn'], \ 'indent': ['.indent.pro', 'indentrc'], \ 'inform': ['file.inf', 'file.INF'], - \ 'initng': ['/etc/initng/any/file.i', 'file.ii'], + \ 'initng': ['/etc/initng/any/file.i', 'file.ii', 'any/etc/initng/any/file.i'], \ 'inittab': ['inittab'], \ 'ipfilter': ['ipf.conf', 'ipf6.conf', 'ipf.rules'], \ 'iss': ['file.iss'], \ 'ist': ['file.ist', 'file.mst'], \ 'j': ['file.ijs'], \ 'jal': ['file.jal', 'file.JAL'], - \ 'jam': ['file.jpl', 'file.jpr'], + \ 'jam': ['file.jpl', 'file.jpr', 'JAM-file.file', 'JAM.file', 'Prl-file.file', 'Prl.file'], \ 'java': ['file.java', 'file.jav'], \ 'javacc': ['file.jj', 'file.jjt'], \ 'javascript': ['file.js', 'file.javascript', 'file.es', 'file.mjs', 'file.cjs'], @@ -233,10 +248,10 @@ let s:filename_checks = { \ 'jess': ['file.clp'], \ 'jgraph': ['file.jgr'], \ 'jovial': ['file.jov', 'file.j73', 'file.jovial'], - \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx'], + \ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file'], \ 'json': ['file.json', 'file.jsonp', 'file.webmanifest', 'Pipfile.lock'], \ 'jsp': ['file.jsp'], - \ 'kconfig': ['Kconfig', 'Kconfig.debug'], + \ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'], \ 'kivy': ['file.kv'], \ 'kix': ['file.kix'], \ 'kotlin': ['file.kt', 'file.ktm', 'file.kts'], @@ -248,18 +263,18 @@ let s:filename_checks = { \ 'ldif': ['file.ldif'], \ 'less': ['file.less'], \ 'lex': ['file.lex', 'file.l', 'file.lxx', 'file.l++'], - \ 'lftp': ['lftp.conf', '.lftprc', 'anylftp/rc'], + \ 'lftp': ['lftp.conf', '.lftprc', 'anylftp/rc', 'lftp/rc', 'some-lftp/rc'], \ 'lhaskell': ['file.lhs'], - \ 'libao': ['/etc/libao.conf', '/.libao'], + \ 'libao': ['/etc/libao.conf', '/.libao', 'any/.libao', 'any/etc/libao.conf'], \ 'lifelines': ['file.ll'], - \ 'lilo': ['lilo.conf'], - \ 'limits': ['/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf'], + \ 'lilo': ['lilo.conf', 'lilo.conf-file'], + \ 'limits': ['/etc/limits', '/etc/anylimits.conf', '/etc/anylimits.d/file.conf', '/etc/limits.conf', '/etc/limits.d/file.conf', '/etc/some-limits.conf', '/etc/some-limits.d/file.conf', 'any/etc/limits', 'any/etc/limits.conf', 'any/etc/limits.d/file.conf', 'any/etc/some-limits.conf', 'any/etc/some-limits.d/file.conf'], \ 'liquid': ['file.liquid'], \ 'lisp': ['file.lsp', 'file.lisp', 'file.el', 'file.cl', '.emacs', '.sawfishrc', 'sbclrc', '.sbclrc'], \ 'lite': ['file.lite', 'file.lt'], - \ 'litestep': ['/LiteStep/any/file.rc'], - \ 'loginaccess': ['/etc/login.access'], - \ 'logindefs': ['/etc/login.defs'], + \ 'litestep': ['/LiteStep/any/file.rc', 'any/LiteStep/any/file.rc'], + \ 'loginaccess': ['/etc/login.access', 'any/etc/login.access'], + \ 'logindefs': ['/etc/login.defs', 'any/etc/login.defs'], \ 'logtalk': ['file.lgt'], \ 'lotos': ['file.lot', 'file.lotos'], \ 'lout': ['file.lou', 'file.lout'], @@ -269,13 +284,13 @@ let s:filename_checks = { \ 'lua': ['file.lua', 'file.rockspec', 'file.nse'], \ 'lynx': ['lynx.cfg'], \ 'm4': ['file.at'], - \ 'mail': ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml'], - \ 'mailaliases': ['/etc/mail/aliases', '/etc/aliases'], + \ 'mail': ['snd.123', '.letter', '.letter.123', '.followup', '.article', '.article.123', 'pico.123', 'mutt-xx-xxx', 'muttng-xx-xxx', 'ae123.txt', 'file.eml', 'reportbug-file'], + \ 'mailaliases': ['/etc/mail/aliases', '/etc/aliases', 'any/etc/aliases', 'any/etc/mail/aliases'], \ 'mailcap': ['.mailcap', 'mailcap'], - \ 'make': ['file.mk', 'file.mak', 'file.dsp'], + \ 'make': ['file.mk', 'file.mak', 'file.dsp', 'makefile', 'Makefile', 'makefile-file', 'Makefile-file', 'some-makefile', 'some-Makefile'], \ 'mallard': ['file.page'], \ 'man': ['file.man'], - \ 'manconf': ['/etc/man.conf', 'man.config'], + \ 'manconf': ['/etc/man.conf', 'man.config', 'any/etc/man.conf'], \ 'map': ['file.map'], \ 'maple': ['file.mv', 'file.mpl', 'file.mws'], \ 'markdown': ['file.markdown', 'file.mdown', 'file.mkd', 'file.mkdn', 'file.mdwn', 'file.md'], @@ -297,27 +312,27 @@ let s:filename_checks = { \ 'mix': ['file.mix', 'file.mixal'], \ 'mma': ['file.nb'], \ 'mmp': ['file.mmp'], - \ 'modconf': ['/etc/modules.conf', '/etc/modules', '/etc/conf.modules'], + \ 'modconf': ['/etc/modules.conf', '/etc/modules', '/etc/conf.modules', '/etc/modprobe.file', 'any/etc/conf.modules', 'any/etc/modprobe.file', 'any/etc/modules', 'any/etc/modules.conf'], \ 'modula2': ['file.m2', 'file.mi'], \ 'monk': ['file.isc', 'file.monk', 'file.ssc', 'file.tsc'], \ 'moo': ['file.moo'], \ 'mp': ['file.mp'], - \ 'mplayerconf': ['mplayer.conf', '/.mplayer/config'], + \ 'mplayerconf': ['mplayer.conf', '/.mplayer/config', 'any/.mplayer/config'], \ 'mrxvtrc': ['mrxvtrc', '.mrxvtrc'], \ 'msidl': ['file.odl', 'file.mof'], \ 'msql': ['file.msql'], \ 'mupad': ['file.mu'], \ 'mush': ['file.mush'], - \ 'muttrc': ['Muttngrc', 'Muttrc'], + \ 'muttrc': ['Muttngrc', 'Muttrc', '.muttngrc', '.muttngrc-file', '.muttrc', '.muttrc-file', '/.mutt/muttngrc', '/.mutt/muttngrc-file', '/.mutt/muttrc', '/.mutt/muttrc-file', '/.muttng/muttngrc', '/.muttng/muttngrc-file', '/.muttng/muttrc', '/.muttng/muttrc-file', '/etc/Muttrc.d/file', 'Muttngrc-file', 'Muttrc-file', 'any/.mutt/muttngrc', 'any/.mutt/muttngrc-file', 'any/.mutt/muttrc', 'any/.mutt/muttrc-file', 'any/.muttng/muttngrc', 'any/.muttng/muttngrc-file', 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', 'muttrc-file'], \ 'mysql': ['file.mysql'], \ 'n1ql': ['file.n1ql', 'file.nql'], - \ 'named': ['namedfile.conf', 'rndcfile.conf'], - \ 'nanorc': ['/etc/nanorc', 'file.nanorc'], + \ 'named': ['namedfile.conf', 'rndcfile.conf', 'named-file.conf', 'named.conf', 'rndc-file.conf', 'rndc-file.key', 'rndc.conf', 'rndc.key'], + \ 'nanorc': ['/etc/nanorc', 'file.nanorc', 'any/etc/nanorc'], \ 'ncf': ['file.ncf'], \ 'netrc': ['.netrc'], \ 'ninja': ['file.ninja'], \ 'nqc': ['file.nqc'], - \ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom'], + \ 'nroff': ['file.tr', 'file.nr', 'file.roff', 'file.tmac', 'file.mom', 'tmac.file'], \ 'nsis': ['file.nsi', 'file.nsh'], \ 'obj': ['file.obj'], \ 'ocaml': ['file.ml', 'file.mli', 'file.mll', 'file.mly', '.ocamlinit'], @@ -325,11 +340,11 @@ let s:filename_checks = { \ 'omnimark': ['file.xom', 'file.xin'], \ 'openroad': ['file.or'], \ 'ora': ['file.ora'], - \ 'pamconf': ['/etc/pam.conf'], - \ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment'], + \ 'pamconf': ['/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'], + \ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'], \ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'], \ 'pascal': ['file.pas', 'file.pp', 'file.dpr', 'file.lpr'], - \ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak'], + \ 'passwd': ['any/etc/passwd', 'any/etc/passwd-', 'any/etc/passwd.edit', 'any/etc/shadow', 'any/etc/shadow-', 'any/etc/shadow.edit', 'any/var/backups/passwd.bak', 'any/var/backups/shadow.bak', '/etc/passwd', '/etc/passwd-', '/etc/passwd.edit', '/etc/shadow', '/etc/shadow-', '/etc/shadow.edit', '/var/backups/passwd.bak', '/var/backups/shadow.bak'], \ 'pccts': ['file.g'], \ 'pdf': ['file.pdf'], \ 'perl': ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc'], @@ -342,7 +357,7 @@ let s:filename_checks = { \ 'cmod': ['file.cmod'], \ 'pilrc': ['file.rcp'], \ 'pine': ['.pinerc', 'pinerc', '.pinercex', 'pinercex'], - \ 'pinfo': ['/etc/pinforc', '/.pinforc'], + \ 'pinfo': ['/etc/pinforc', '/.pinforc', 'any/.pinforc', 'any/etc/pinforc'], \ 'pli': ['file.pli', 'file.pl1'], \ 'plm': ['file.plm', 'file.p36', 'file.pac'], \ 'plp': ['file.plp'], @@ -361,17 +376,17 @@ let s:filename_checks = { \ 'prolog': ['file.pdb'], \ 'promela': ['file.pml'], \ 'proto': ['file.proto'], - \ 'protocols': ['/etc/protocols'], + \ 'protocols': ['/etc/protocols', 'any/etc/protocols'], \ 'psf': ['file.psf'], \ 'pyrex': ['file.pyx', 'file.pxd'], \ 'python': ['file.py', 'file.pyw', '.pythonstartup', '.pythonrc', 'file.ptl', 'file.pyi', 'SConstruct'], - \ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg'], + \ 'quake': ['anybaseq2/file.cfg', 'anyid1/file.cfg', 'quake3/file.cfg', 'baseq2/file.cfg', 'id1/file.cfg', 'quake1/file.cfg', 'some-baseq2/file.cfg', 'some-id1/file.cfg', 'some-quake1/file.cfg'], \ 'radiance': ['file.rad', 'file.mat'], \ 'ratpoison': ['.ratpoisonrc', 'ratpoisonrc'], \ 'rc': ['file.rc', 'file.rch'], \ 'rcs': ['file,v'], \ 'readline': ['.inputrc', 'inputrc'], - \ 'remind': ['.reminders', 'file.remind', 'file.rem'], + \ 'remind': ['.reminders', 'file.remind', 'file.rem', '.reminders-file'], \ 'rego': ['file.rego'], \ 'resolv': ['resolv.conf'], \ 'reva': ['file.frt'], @@ -384,7 +399,7 @@ let s:filename_checks = { \ 'rpl': ['file.rpl'], \ 'rst': ['file.rst'], \ 'rtf': ['file.rtf'], - \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake'], + \ 'ruby': ['.irbrc', 'irbrc', 'file.rb', 'file.rbw', 'file.gemspec', 'file.ru', 'Gemfile', 'file.builder', 'file.rxml', 'file.rjs', 'file.rant', 'file.rake', 'rakefile', 'Rakefile', 'rantfile', 'Rantfile', 'rakefile-file', 'Rakefile-file'], \ 'rust': ['file.rs'], \ 'samba': ['smb.conf'], \ 'sas': ['file.sas'], @@ -400,10 +415,10 @@ let s:filename_checks = { \ 'sdc': ['file.sdc'], \ 'sdl': ['file.sdl', 'file.pr'], \ 'sed': ['file.sed'], - \ 'sensors': ['/etc/sensors.conf', '/etc/sensors3.conf'], - \ 'services': ['/etc/services'], - \ 'setserial': ['/etc/serial.conf'], - \ 'sh': ['/etc/udev/cdsymlinks.conf'], + \ 'sensors': ['/etc/sensors.conf', '/etc/sensors3.conf', 'any/etc/sensors.conf', 'any/etc/sensors3.conf'], + \ 'services': ['/etc/services', 'any/etc/services'], + \ 'setserial': ['/etc/serial.conf', 'any/etc/serial.conf'], + \ 'sh': ['/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf'], \ 'sieve': ['file.siv', 'file.sieve'], \ 'simula': ['file.sim'], \ 'sinda': ['file.sin', 'file.s85'], @@ -411,9 +426,9 @@ let s:filename_checks = { \ 'skill': ['file.il', 'file.ils', 'file.cdf'], \ 'slang': ['file.sl'], \ 'slice': ['file.ice'], - \ 'slpconf': ['/etc/slp.conf'], - \ 'slpreg': ['/etc/slp.reg'], - \ 'slpspi': ['/etc/slp.spi'], + \ 'slpconf': ['/etc/slp.conf', 'any/etc/slp.conf'], + \ 'slpreg': ['/etc/slp.reg', 'any/etc/slp.reg'], + \ 'slpspi': ['/etc/slp.spi', 'any/etc/slp.spi'], \ 'slrnrc': ['.slrnrc'], \ 'slrnsc': ['file.score'], \ 'sm': ['sendmail.cf'], @@ -431,19 +446,19 @@ let s:filename_checks = { \ 'sqr': ['file.sqr', 'file.sqi'], \ 'squid': ['squid.conf'], \ 'srec': ['file.s19', 'file.s28', 'file.s37', 'file.mot', 'file.srec'], - \ 'sshconfig': ['ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf'], + \ 'sshconfig': ['ssh_config', '/.ssh/config', '/etc/ssh/ssh_config.d/file.conf', 'any/etc/ssh/ssh_config.d/file.conf', 'any/.ssh/config'], \ 'sshdconfig': ['sshd_config', '/etc/ssh/sshd_config.d/file.conf', 'any/etc/ssh/sshd_config.d/file.conf'], \ 'st': ['file.st'], \ 'stata': ['file.ado', 'file.do', 'file.imata', 'file.mata'], \ 'stp': ['file.stp'], - \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp'], + \ 'sudoers': ['any/etc/sudoers', 'sudoers.tmp', '/etc/sudoers'], \ 'svg': ['file.svg'], - \ 'svn': ['svn-commitfile.tmp'], + \ 'svn': ['svn-commitfile.tmp', 'svn-commit-file.tmp', 'svn-commit.tmp'], \ 'swift': ['file.swift'], \ 'swiftgyb': ['file.swift.gyb'], \ 'sil': ['file.sil'], - \ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf'], - \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.dnssd', 'any/systemd/file.link', 'any/systemd/file.mount', 'any/systemd/file.netdev', 'any/systemd/file.network', 'any/systemd/file.nspawn', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.slice', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/some.conf.d/file.conf', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile'], + \ 'sysctl': ['/etc/sysctl.conf', '/etc/sysctl.d/file.conf', 'any/etc/sysctl.conf', 'any/etc/sysctl.d/file.conf'], + \ 'systemd': ['any/systemd/file.automount', 'any/systemd/file.dnssd', 'any/systemd/file.link', 'any/systemd/file.mount', 'any/systemd/file.netdev', 'any/systemd/file.network', 'any/systemd/file.nspawn', 'any/systemd/file.path', 'any/systemd/file.service', 'any/systemd/file.slice', 'any/systemd/file.socket', 'any/systemd/file.swap', 'any/systemd/file.target', 'any/systemd/file.timer', '/etc/systemd/some.conf.d/file.conf', '/etc/systemd/system/some.d/file.conf', '/etc/systemd/system/some.d/.#file', '/etc/systemd/system/.#otherfile', '/home/user/.config/systemd/user/some.d/mine.conf', '/home/user/.config/systemd/user/some.d/.#file', '/home/user/.config/systemd/user/.#otherfile', '/.config/systemd/user/.#', '/.config/systemd/user/.#-file', '/.config/systemd/user/file.d/.#', '/.config/systemd/user/file.d/.#-file', '/.config/systemd/user/file.d/file.conf', '/etc/systemd/file.conf.d/file.conf', '/etc/systemd/system/.#', '/etc/systemd/system/.#-file', '/etc/systemd/system/file.d/.#', '/etc/systemd/system/file.d/.#-file', '/etc/systemd/system/file.d/file.conf', '/systemd/file.automount', '/systemd/file.dnssd', '/systemd/file.link', '/systemd/file.mount', '/systemd/file.netdev', '/systemd/file.network', '/systemd/file.nspawn', '/systemd/file.path', '/systemd/file.service', '/systemd/file.slice', '/systemd/file.socket', '/systemd/file.swap', '/systemd/file.target', '/systemd/file.timer', 'any/.config/systemd/user/.#', 'any/.config/systemd/user/.#-file', 'any/.config/systemd/user/file.d/.#', 'any/.config/systemd/user/file.d/.#-file', 'any/.config/systemd/user/file.d/file.conf', 'any/etc/systemd/file.conf.d/file.conf', 'any/etc/systemd/system/.#', 'any/etc/systemd/system/.#-file', 'any/etc/systemd/system/file.d/.#', 'any/etc/systemd/system/file.d/.#-file', 'any/etc/systemd/system/file.d/file.conf'], \ 'systemverilog': ['file.sv', 'file.svh'], \ 'tags': ['tags'], \ 'tak': ['file.tak'], @@ -460,7 +475,7 @@ let s:filename_checks = { \ 'tidy': ['.tidyrc', 'tidyrc', 'tidy.conf'], \ 'tilde': ['file.t.html'], \ 'tli': ['file.tli'], - \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf'], + \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf'], \ 'tpp': ['file.tpp'], \ 'treetop': ['file.treetop'], \ 'trustees': ['trustees.conf'], @@ -472,12 +487,12 @@ let s:filename_checks = { \ 'typescript': ['file.ts'], \ 'typescriptreact': ['file.tsx'], \ 'uc': ['file.uc'], - \ 'udevconf': ['/etc/udev/udev.conf'], - \ 'udevperm': ['/etc/udev/permissions.d/file.permissions'], + \ 'udevconf': ['/etc/udev/udev.conf', 'any/etc/udev/udev.conf'], + \ 'udevperm': ['/etc/udev/permissions.d/file.permissions', 'any/etc/udev/permissions.d/file.permissions'], \ 'udevrules': ['/etc/udev/rules.d/file.rules', '/usr/lib/udev/rules.d/file.rules', '/lib/udev/rules.d/file.rules'], \ 'uil': ['file.uit', 'file.uil'], - \ 'updatedb': ['/etc/updatedb.conf'], - \ 'upstart': ['/usr/share/upstart/file.conf', '/usr/share/upstart/file.override', '/etc/init/file.conf', '/etc/init/file.override', '/.init/file.conf', '/.init/file.override', '/.config/upstart/file.conf', '/.config/upstart/file.override'], + \ 'updatedb': ['/etc/updatedb.conf', 'any/etc/updatedb.conf'], + \ 'upstart': ['/usr/share/upstart/file.conf', '/usr/share/upstart/file.override', '/etc/init/file.conf', '/etc/init/file.override', '/.init/file.conf', '/.init/file.override', '/.config/upstart/file.conf', '/.config/upstart/file.override', 'any/.config/upstart/file.conf', 'any/.config/upstart/file.override', 'any/.init/file.conf', 'any/.init/file.override', 'any/etc/init/file.conf', 'any/etc/init/file.override', 'any/usr/share/upstart/file.conf', 'any/usr/share/upstart/file.override'], \ 'upstreamdat': ['upstream.dat', 'UPSTREAM.DAT', 'upstream.file.dat', 'UPSTREAM.FILE.DAT', 'file.upstream.dat', 'FILE.UPSTREAM.DAT'], \ 'upstreaminstalllog': ['upstreaminstall.log', 'UPSTREAMINSTALL.LOG', 'upstreaminstall.file.log', 'UPSTREAMINSTALL.FILE.LOG', 'file.upstreaminstall.log', 'FILE.UPSTREAMINSTALL.LOG'], \ 'upstreamlog': ['fdrupstream.log', 'upstream.log', 'UPSTREAM.LOG', 'upstream.file.log', 'UPSTREAM.FILE.LOG', 'file.upstream.log', 'FILE.UPSTREAM.LOG', 'UPSTREAM-file.log', 'UPSTREAM-FILE.LOG'], @@ -488,8 +503,8 @@ let s:filename_checks = { \ 'verilog': ['file.v'], \ 'verilogams': ['file.va', 'file.vams'], \ 'vgrindefs': ['vgrindefs'], - \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho'], - \ 'vim': ['file.vim', 'file.vba', '.exrc', '_exrc'], + \ 'vhdl': ['file.hdl', 'file.vhd', 'file.vhdl', 'file.vbe', 'file.vst', 'file.vhdl_123', 'file.vho', 'some.vhdl_1', 'some.vhdl_1-file'], + \ 'vim': ['file.vim', 'file.vba', '.exrc', '_exrc', 'some-vimrc', 'some-vimrc-file', 'vimrc', 'vimrc-file'], \ 'viminfo': ['.viminfo', '_viminfo'], \ 'vmasm': ['file.mar'], \ 'voscm': ['file.cm'], @@ -501,14 +516,15 @@ let s:filename_checks = { \ 'wget': ['.wgetrc', 'wgetrc'], \ 'winbatch': ['file.wbt'], \ 'wml': ['file.wml'], + \ 'wsh': ['file.wsf', 'file.wsc'], \ 'wsml': ['file.wsml'], \ 'wvdial': ['wvdial.conf', '.wvdialrc'], - \ 'xdefaults': ['.Xdefaults', '.Xpdefaults', '.Xresources', 'xdm-config', 'file.ad'], + \ 'xdefaults': ['.Xdefaults', '.Xpdefaults', '.Xresources', 'xdm-config', 'file.ad', '/Xresources/file', '/app-defaults/file', 'Xresources', 'Xresources-file', 'any/Xresources/file', 'any/app-defaults/file'], \ 'xhtml': ['file.xhtml', 'file.xht'], - \ 'xinetd': ['/etc/xinetd.conf'], + \ 'xinetd': ['/etc/xinetd.conf', '/etc/xinetd.d/file', 'any/etc/xinetd.conf', 'any/etc/xinetd.d/file'], \ 'xmath': ['file.msc', 'file.msf'], - \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl'], - \ 'xmodmap': ['anyXmodmap'], + \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu'], + \ 'xmodmap': ['anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'], \ 'xf86conf': ['xorg.conf', 'xorg.conf-4'], \ 'xpm2': ['file.xpm2'], \ 'xquery': ['file.xq', 'file.xql', 'file.xqm', 'file.xquery', 'file.xqy'], @@ -521,7 +537,7 @@ let s:filename_checks = { \ 'z8a': ['file.z8a'], \ 'zimbu': ['file.zu'], \ 'zimbutempl': ['file.zut'], - \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh'], + \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'], \ \ 'help': [$VIMRUNTIME . '/doc/help.txt'], \ 'xpm': ['file.xpm'], diff --git a/src/version.c b/src/version.c index 6ff2aa08db..590de0b2f0 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1827, /**/ 1826, /**/ From 1b1e9df78b9ff98cc5ccff359bead37ce5c54d6b Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 22:26:52 +0200 Subject: [PATCH 23/25] patch 8.2.1828: build failure without the +eval feature Problem: Build failure without the +eval feature. Solution: Add dummys for ex_block and ex_endblock. --- src/ex_docmd.c | 2 ++ src/version.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 4a71989ddb..112cb9eab9 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -263,6 +263,7 @@ static void ex_psearch(exarg_T *eap); static void ex_tag(exarg_T *eap); static void ex_tag_cmd(exarg_T *eap, char_u *name); #ifndef FEAT_EVAL +# define ex_block ex_ni # define ex_break ex_ni # define ex_breakadd ex_ni # define ex_breakdel ex_ni @@ -280,6 +281,7 @@ static void ex_tag_cmd(exarg_T *eap, char_u *name); # define ex_echo ex_ni # define ex_echohl ex_ni # define ex_else ex_ni +# define ex_endblock ex_ni # define ex_endfunction ex_ni # define ex_endif ex_ni # define ex_endtry ex_ni diff --git a/src/version.c b/src/version.c index 590de0b2f0..abec6fbc0e 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1828, /**/ 1827, /**/ From bd6428b9e79ed85b54ea7eaa11871fa09d63ab6f Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 22:34:36 +0200 Subject: [PATCH 24/25] patch 8.2.1829: warnings when executing Github actions Problem: Warnings when executing Github actions. Solution: Use another method to set environment variables. (Ken Takata, closes #7107) --- .github/workflows/ci-windows.yaml | 4 ++-- src/version.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-windows.yaml b/.github/workflows/ci-windows.yaml index 6a5501f249..917783019d 100644 --- a/.github/workflows/ci-windows.yaml +++ b/.github/workflows/ci-windows.yaml @@ -74,8 +74,8 @@ jobs: git config --global core.autocrlf input python_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON_VER_DOT}/InstallPath/@") python3_dir=$(cat "/proc/${{ matrix.cygreg }}/HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${PYTHON3_VER_DOT}${{ matrix.pyreg }}/InstallPath/@") - echo "::set-env name=PYTHON_DIR::$python_dir" - echo "::set-env name=PYTHON3_DIR::$python3_dir" + echo "PYTHON_DIR=$python_dir" >> $GITHUB_ENV + echo "PYTHON3_DIR=$python3_dir" >> $GITHUB_ENV - uses: msys2/setup-msys2@v2 if: matrix.toolchain == 'mingw' diff --git a/src/version.c b/src/version.c index abec6fbc0e..388932fd5f 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1829, /**/ 1828, /**/ From c6ed254d9fda0ff54cdedce5597ff3e0d0218d18 Mon Sep 17 00:00:00 2001 From: Bram Moolenaar Date: Sat, 10 Oct 2020 23:26:28 +0200 Subject: [PATCH 25/25] patch 8.2.1830: MS-Windows: Python3 issue with stdin Problem: MS-Windows: Python3 issue with stdin. Solution: Check if stdin is readable. (Ken Takata, closes #7106) --- src/if_python3.c | 34 +++++++++++++++++++++++++--------- src/version.c | 2 ++ 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/if_python3.c b/src/if_python3.c index f6904c3801..e148e53bb7 100644 --- a/src/if_python3.c +++ b/src/if_python3.c @@ -908,8 +908,27 @@ python3_loaded(void) static wchar_t *py_home_buf = NULL; #if defined(MSWIN) && (PY_VERSION_HEX >= 0x030500f0) -// Python 3.5 or later will abort inside Py_Initialize() when stdin is -// redirected. Reconnect stdin to NUL. +/* + * Return TRUE if stdin is readable from Python 3. + */ + static BOOL +is_stdin_readable(void) +{ + DWORD mode, eventnum; + struct _stat st; + int fd = fileno(stdin); + HANDLE hstdin = (HANDLE)_get_osfhandle(fd); + + // Check if stdin is connected to the console. + if (GetConsoleMode(hstdin, &mode)) + // Check if it is opened as input. + return GetNumberOfConsoleInputEvents(hstdin, &eventnum); + + return _fstat(fd, &st) == 0; +} + +// Python 3.5 or later will abort inside Py_Initialize() when stdin has +// been closed (i.e. executed by "vim -"). Reconnect stdin to CONIN$. // Note that the python DLL is linked to its own stdio DLL which can be // differ from Vim's stdio. static void @@ -917,7 +936,6 @@ reset_stdin(void) { FILE *(*py__acrt_iob_func)(unsigned) = NULL; FILE *(*pyfreopen)(const char *, const char *, FILE *) = NULL; - char *stdin_name = "NUL"; HINSTANCE hinst; # ifdef DYNAMIC_PYTHON3 @@ -925,7 +943,7 @@ reset_stdin(void) # else hinst = GetModuleHandle(PYTHON3_DLL); # endif - if (hinst == NULL) + if (hinst == NULL || is_stdin_readable()) return; // Get "freopen" and "stdin" which are used in the python DLL. @@ -938,14 +956,12 @@ reset_stdin(void) if (hpystdiodll) pyfreopen = (void *)GetProcAddress(hpystdiodll, "freopen"); } - if (isatty(fileno(stdin))) - stdin_name = "CONIN$"; - // Reconnect stdin to NUL or CONIN$. + // Reconnect stdin to CONIN$. if (pyfreopen != NULL) - pyfreopen(stdin_name, "r", py__acrt_iob_func(0)); + pyfreopen("CONIN$", "r", py__acrt_iob_func(0)); else - freopen(stdin_name, "r", stdin); + freopen("CONIN$", "r", stdin); } #else # define reset_stdin() diff --git a/src/version.c b/src/version.c index 388932fd5f..2577c142c3 100644 --- a/src/version.c +++ b/src/version.c @@ -750,6 +750,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1830, /**/ 1829, /**/