From 9ef371fd545034519e4259da001a52e9f7838ffe Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 13 Dec 2016 14:15:10 -0500 Subject: test: quickfix: Move upstream vim quickfix test to src/nvim/testdir Massaging the upstream patches for this test into the lua tests are too cumbersome and slow down patching. --- src/nvim/testdir/Makefile | 5 +- src/nvim/testdir/test_quickfix.vim | 681 +++++++++++++++++++++++++++++++++++++ 2 files changed, 684 insertions(+), 2 deletions(-) create mode 100644 src/nvim/testdir/test_quickfix.vim (limited to 'src') diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 0118597eb8..7cd1921ce1 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -30,15 +30,16 @@ SCRIPTS := \ # Tests using runtest.vim.vim. # Keep test_alot*.res as the last one, sort the others. NEW_TESTS = \ + test_cmdline.res \ test_cscope.res \ - test_cmdline.res \ test_diffmode.res \ test_hardcopy.res \ test_help_tagjump.res \ test_history.res \ test_langmap.res \ - test_match.res \ + test_match.res \ test_matchadd_conceal.res \ + test_quickfix.res \ test_syntax.res \ test_usercommands.res \ test_timers.res \ diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim new file mode 100644 index 0000000000..9dbd00b001 --- /dev/null +++ b/src/nvim/testdir/test_quickfix.vim @@ -0,0 +1,681 @@ +" Test for the quickfix commands. + +if !has('quickfix') + finish +endif + +set encoding=utf-8 + +" Tests for the :clist and :llist commands +function XlistTests(cchar) + let Xlist = a:cchar . 'list' + let Xgetexpr = a:cchar . 'getexpr' + + " With an empty list, command should return error + exe Xgetexpr . ' []' + exe 'silent! ' . Xlist + call assert_true(v:errmsg ==# 'E42: No Errors') + + " Populate the list and then try + exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', + \ 'non-error 2', 'Xtestfile2:2:2:Line2', + \ 'non-error 3', 'Xtestfile3:3:1:Line3']" + + " List only valid entries + redir => result + exe Xlist + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List all the entries + redir => result + exe Xlist . "!" + redir END + let l = split(result, "\n") + call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2', + \ ' 5: non-error 3', ' 6 Xtestfile3:3 col 1: Line3'], l) + + " List a range of errors + redir => result + exe Xlist . " 3,6" + redir END + let l = split(result, "\n") + call assert_equal([' 4 Xtestfile2:2 col 2: Line2', + \ ' 6 Xtestfile3:3 col 1: Line3'], l) + + redir => result + exe Xlist . "! 3,4" + redir END + let l = split(result, "\n") + call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) + + redir => result + exe Xlist . " -6,-4" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) + + redir => result + exe Xlist . "! -5,-3" + redir END + let l = split(result, "\n") + call assert_equal([' 2 Xtestfile1:1 col 3: Line1', + \ ' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) +endfunction + +function Test_clist() + call XlistTests('c') + call XlistTests('l') +endfunction + +" Tests for the :colder, :cnewer, :lolder and :lnewer commands +" Note that this test assumes that a quickfix/location list is +" already set by the caller. +function XageTests(cchar) + let Xolder = a:cchar . 'older' + let Xnewer = a:cchar . 'newer' + let Xgetexpr = a:cchar . 'getexpr' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + " Jumping to a non existent list should return error + exe 'silent! ' . Xolder . ' 99' + call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') + + exe 'silent! ' . Xnewer . ' 99' + call assert_true(v:errmsg ==# 'E381: At top of quickfix stack') + + " Add three quickfix/location lists + exe Xgetexpr . " ['Xtestfile1:1:3:Line1']" + exe Xgetexpr . " ['Xtestfile2:2:2:Line2']" + exe Xgetexpr . " ['Xtestfile3:3:1:Line3']" + + " Go back two lists + exe Xolder + exe 'let l = ' . Xgetlist + call assert_equal('Line2', l[0].text) + + " Go forward two lists + exe Xnewer + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) + + " Test for the optional count argument + exe Xolder . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line1', l[0].text) + + exe Xnewer . ' 2' + exe 'let l = ' . Xgetlist + call assert_equal('Line3', l[0].text) +endfunction + +function Test_cage() + let list = [{'bufnr': 1, 'lnum': 1}] + call setqflist(list) + call XageTests('c') + + call setloclist(0, list) + call XageTests('l') +endfunction + +" Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen +" commands +function XwindowTests(cchar) + let Xwindow = a:cchar . 'window' + let Xclose = a:cchar . 'close' + let Xopen = a:cchar . 'open' + let Xgetexpr = a:cchar . 'getexpr' + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Quickfix/Location window should not open with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) + + " Create a list with valid entries + exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', + \ 'Xtestfile3:3:1:Line3']" + + " Open the window + exe Xwindow + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') + + " Close the window + exe Xclose + call assert_true(winnr('$') == 1) + + " Create a list with no valid entries + exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + + " Open the window + exe Xopen . ' 5' + call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1' + \ && winheight('.') == 5) + + " Opening the window again, should move the cursor to that window + wincmd t + exe Xopen . ' 7' + call assert_true(winnr('$') == 2 && winnr() == 2 && + \ winheight('.') == 7 && + \ getline('.') ==# '|| non-error 1') + + + " Calling cwindow should close the quickfix window with no valid errors + exe Xwindow + call assert_true(winnr('$') == 1) +endfunction + +function Test_cwindow() + call XwindowTests('c') + call XwindowTests('l') +endfunction + +" Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile +" commands. +function XfileTests(cchar) + let Xfile = a:cchar . 'file' + let Xgetfile = a:cchar . 'getfile' + let Xaddfile = a:cchar . 'addfile' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + call writefile(['Xtestfile1:700:10:Line 700', + \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1') + + enew! + exe Xfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + " Run cfile/lfile from a modified buffer + enew! + silent! put ='Quickfix' + exe 'silent! ' . Xfile . ' Xqftestfile1' + call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)') + + call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') + exe Xaddfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 3 && + \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') + + call writefile(['Xtestfile1:222:77:Line 222', + \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1') + + enew! + exe Xgetfile . ' Xqftestfile1' + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && + \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') + + call delete('Xqftestfile1') +endfunction + +function Test_cfile() + call XfileTests('c') + call XfileTests('l') +endfunction + +" Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and +" :lgetbuffer commands. +function XbufferTests(cchar) + let Xbuffer = a:cchar . 'buffer' + let Xgetbuffer = a:cchar . 'getbuffer' + let Xaddbuffer = a:cchar . 'addbuffer' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + + enew! + silent! call setline(1, ['Xtestfile7:700:10:Line 700', + \ 'Xtestfile8:800:15:Line 800']) + exe Xbuffer . "!" + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && + \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + + enew! + silent! call setline(1, ['Xtestfile9:900:55:Line 900', + \ 'Xtestfile10:950:66:Line 950']) + exe Xgetbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 2 && + \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') + + enew! + silent! call setline(1, ['Xtestfile11:700:20:Line 700', + \ 'Xtestfile12:750:25:Line 750']) + exe Xaddbuffer + exe 'let l = ' . Xgetlist + call assert_true(len(l) == 4 && + \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && + \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && + \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') + +endfunction + +function Test_cbuffer() + call XbufferTests('c') + call XbufferTests('l') +endfunction + +function Test_helpgrep() + helpgrep quickfix + copen + " This wipes out the buffer, make sure that doesn't cause trouble. + cclose +endfunc + +func Test_errortitle() + augroup QfBufWinEnter + au! + au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE') + augroup END + copen + let a=[{'lnum': 308, 'bufnr': bufnr(''), 'col': 58, 'valid': 1, 'vcol': 0, 'nr': 0, 'type': '', 'pattern': '', 'text': ' au BufWinEnter * :let g:a=get(w:, ''quickfix_title'', ''NONE'')'}] + call setqflist(a) + call assert_equal(':setqflist()', g:a) + augroup QfBufWinEnter + au! + augroup END + augroup! QfBufWinEnter +endfunc + +func Test_vimgreptitle() + augroup QfBufWinEnter + au! + au BufWinEnter * :let g:a=get(w:, 'quickfix_title', 'NONE') + augroup END + try + vimgrep /pattern/j file + catch /E480/ + endtry + copen + call assert_equal(': vimgrep /pattern/j file', g:a) + augroup QfBufWinEnter + au! + augroup END + augroup! QfBufWinEnter +endfunc + +function XqfTitleTests(cchar) + let Xgetexpr = a:cchar . 'getexpr' + if a:cchar == 'c' + let Xgetlist = 'getqflist()' + else + let Xgetlist = 'getloclist(0)' + endif + let Xopen = a:cchar . 'open' + let Xclose = a:cchar . 'close' + + exe Xgetexpr . " ['file:1:1:message']" + exe 'let l = ' . Xgetlist + if a:cchar == 'c' + call setqflist(l, 'r') + else + call setloclist(0, l, 'r') + endif + + exe Xopen + if a:cchar == 'c' + let title = ':setqflist()' + else + let title = ':setloclist()' + endif + call assert_equal(title, w:quickfix_title) + exe Xclose +endfunction + +" Tests for quickfix window's title +function Test_qf_title() + call XqfTitleTests('c') + call XqfTitleTests('l') +endfunction + +" Tests for 'errorformat' +function Test_efm() + let save_efm = &efm + set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%# + cgetexpr ['WWWW', 'EEEE', 'CCCC'] + let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) + call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l) + cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC'] + let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) + call assert_equal("[['W', 1], ['E^@CCCC', 1]]", l) + cgetexpr ['WWWW', 'GGGG', 'ZZZZ', 'EEEE', 'CCCC', 'YYYY'] + let l = strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]'))) + call assert_equal("[['W', 1], ['ZZZZ', 0], ['E^@CCCC', 1], ['YYYY', 0]]", l) + let &efm = save_efm +endfunction + +" This will test for problems in quickfix: +" A. incorrectly copying location lists which caused the location list to show +" a different name than the file that was actually being displayed. +" B. not reusing the window for which the location list window is opened but +" instead creating new windows. +" C. make sure that the location list window is not reused instead of the +" window it belongs to. +" +" Set up the test environment: +function! ReadTestProtocol(name) + let base = substitute(a:name, '\v^test://(.*)%(\.[^.]+)?', '\1', '') + let word = substitute(base, '\v(.*)\..*', '\1', '') + + setl modifiable + setl noreadonly + setl noswapfile + setl bufhidden=delete + %del _ + " For problem 2: + " 'buftype' has to be set to reproduce the constant opening of new windows + setl buftype=nofile + + call setline(1, word) + + setl nomodified + setl nomodifiable + setl readonly + exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '') +endfunction + +function Test_locationlist() + enew + + augroup testgroup + au! + autocmd BufReadCmd test://* call ReadTestProtocol(expand("")) + augroup END + + let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ] + + let qflist = [] + for word in words + call add(qflist, {'filename': 'test://' . word . '.txt', 'text': 'file ' . word . '.txt', }) + " NOTE: problem 1: + " intentionally not setting 'lnum' so that the quickfix entries are not + " valid + call setloclist(0, qflist, ' ') + endfor + + " Test A + lrewind + enew + lopen + lnext + lnext + lnext + lnext + vert split + wincmd L + lopen + wincmd p + lnext + let fileName = expand("%") + wincmd p + let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '') + let fileName = substitute(fileName, '\\', '/', 'g') + let locationListFileName = substitute(locationListFileName, '\\', '/', 'g') + call assert_equal("test://bar.txt", fileName) + call assert_equal("test://bar.txt", locationListFileName) + + wincmd n | only + + " Test B: + lrewind + lopen + 2 + exe "normal \" + wincmd p + 3 + exe "normal \" + wincmd p + 4 + exe "normal \" + call assert_equal(2, winnr('$')) + wincmd n | only + + " Test C: + lrewind + lopen + " Let's move the location list window to the top to check whether it (the + " first window found) will be reused when we try to open new windows: + wincmd K + 2 + exe "normal \" + wincmd p + 3 + exe "normal \" + wincmd p + 4 + exe "normal \" + 1wincmd w + call assert_equal('quickfix', &buftype) + 2wincmd w + let bufferName = expand("%") + let bufferName = substitute(bufferName, '\\', '/', 'g') + call assert_equal('test://quux.txt', bufferName) + + wincmd n | only + + augroup! testgroup +endfunction + +function Test_locationlist_curwin_was_closed() + augroup testgroup + au! + autocmd BufReadCmd t call R(expand("")) + augroup END + + function! R(n) + quit + endfunc + + new + let q = [] + call add(q, {'filename': 't' }) + call setloclist(0, q) + call assert_fails('lrewind', 'E924:') + + augroup! testgroup +endfunction + +" More tests for 'errorformat' +function! Test_efm1() + if !has('unix') + " The 'errorformat' setting is different on non-Unix systems. + " This test works only on Unix-like systems. + return + endif + + let l = [ + \ '"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.', + \ '"Xtestfile", line 6 col 19; this is an error', + \ 'gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c', + \ 'Xtestfile:9: parse error before `asd''', + \ 'make: *** [vim] Error 1', + \ 'in file "Xtestfile" linenr 10: there is an error', + \ '', + \ '2 returned', + \ '"Xtestfile", line 11 col 1; this is an error', + \ '"Xtestfile", line 12 col 2; this is another error', + \ '"Xtestfile", line 14:10; this is an error in column 10', + \ '=Xtestfile=, line 15:10; this is another error, but in vcol 10 this time', + \ '"Xtestfile", linenr 16: yet another problem', + \ 'Error in "Xtestfile" at line 17:', + \ 'x should be a dot', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17', + \ ' ^', + \ 'Error in "Xtestfile" at line 18:', + \ 'x should be a dot', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18', + \ '.............^', + \ 'Error in "Xtestfile" at line 19:', + \ 'x should be a dot', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19', + \ '--------------^', + \ 'Error in "Xtestfile" at line 20:', + \ 'x should be a dot', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20', + \ ' ^', + \ '', + \ 'Does anyone know what is the problem and how to correction it?', + \ '"Xtestfile", line 21 col 9: What is the title of the quickfix window?', + \ '"Xtestfile", line 22 col 9: What is the title of the quickfix window?' + \ ] + + call writefile(l, 'Xerrorfile1') + call writefile(l[:-2], 'Xerrorfile2') + + let m = [ + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 2', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 3', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 4', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 5', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 6', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 7', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 8', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 9', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 10', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 11', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 12', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 13', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 14', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 15', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 16', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 17', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 18', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 19', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 20', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 21', + \ ' xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx line 22' + \ ] + call writefile(m, 'Xtestfile') + + let save_efm = &efm + set efm+==%f=\\,\ line\ %l%*\\D%v%*[^\ ]\ %m + set efm^=%AError\ in\ \"%f\"\ at\ line\ %l:,%Z%p^,%C%m + + exe 'cf Xerrorfile2' + clast + copen + call assert_equal(':cf Xerrorfile2', w:quickfix_title) + wincmd p + + exe 'cf Xerrorfile1' + call assert_equal([4, 12], [line('.'), col('.')]) + cn + call assert_equal([6, 19], [line('.'), col('.')]) + cn + call assert_equal([9, 2], [line('.'), col('.')]) + cn + call assert_equal([10, 2], [line('.'), col('.')]) + cn + call assert_equal([11, 1], [line('.'), col('.')]) + cn + call assert_equal([12, 2], [line('.'), col('.')]) + cn + call assert_equal([14, 10], [line('.'), col('.')]) + cn + call assert_equal([15, 3, 10], [line('.'), col('.'), virtcol('.')]) + cn + call assert_equal([16, 2], [line('.'), col('.')]) + cn + call assert_equal([17, 6], [line('.'), col('.')]) + cn + call assert_equal([18, 7], [line('.'), col('.')]) + cn + call assert_equal([19, 8], [line('.'), col('.')]) + cn + call assert_equal([20, 9], [line('.'), col('.')]) + clast + cprev + cprev + wincmd w + call assert_equal(':cf Xerrorfile1', w:quickfix_title) + wincmd p + + let &efm = save_efm + call delete('Xerrorfile1') + call delete('Xerrorfile2') + call delete('Xtestfile') +endfunction + +function XquickfixChangedByAutocmd(cchar) + let Xolder = a:cchar . 'older' + let Xgetexpr = a:cchar . 'getexpr' + let Xrewind = a:cchar . 'rewind' + if a:cchar == 'c' + let Xsetlist = 'setqflist(' + let ErrorNr = 'E925' + function! ReadFunc() + colder + cgetexpr [] + endfunc + else + let Xsetlist = 'setloclist(0,' + let ErrorNr = 'E926' + function! ReadFunc() + lolder + lgetexpr [] + endfunc + endif + + augroup testgroup + au! + autocmd BufReadCmd t call ReadFunc() + augroup END + + bwipe! + let words = [ "a", "b" ] + let qflist = [] + for word in words + call add(qflist, {'filename': 't'}) + exec "call " . Xsetlist . "qflist, '')" + endfor + exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" + + augroup! testgroup +endfunc + +function Test_quickfix_was_changed_by_autocmd() + call XquickfixChangedByAutocmd('c') + call XquickfixChangedByAutocmd('l') +endfunction + +func Test_caddbuffer_to_empty() + helpgr quickfix + call setqflist([], 'r') + cad + try + cn + catch + " number of matches is unknown + call assert_true(v:exception =~ 'E553:') + endtry + quit! +endfunc + +func Test_cgetexpr_works() + " this must not crash Vim + cgetexpr [$x] +endfunc -- cgit From e89efe75f9fd872e2c7323ea525b35af90e8afa0 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 10:56:00 -0500 Subject: vim-patch:7.4.1752 Problem: When adding to the quickfix list the current position is reset. Solution: Do not reset the position when not needed. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/c1808d5822ed9534ef7f0fe509b15bee92a5cc28 --- src/nvim/quickfix.c | 26 ++++++++++++--------- src/nvim/testdir/test_quickfix.vim | 48 ++++++++++++++++++++++++++++++++++++++ src/nvim/version.c | 2 +- 3 files changed, 64 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index f0d77f9e2b..b97530b700 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -786,7 +786,7 @@ qf_init_end: xfree(pattern); xfree(fmtstr); - qf_update_buffer(qi); + qf_update_buffer(qi, true); return retval; } @@ -1927,7 +1927,7 @@ static void qf_msg(qf_info_T *qi) smsg(_("error list %d of %d; %d errors"), qi->qf_curlist + 1, qi->qf_listcount, qi->qf_lists[qi->qf_curlist].qf_count); - qf_update_buffer(qi); + qf_update_buffer(qi, true); } /* @@ -2314,7 +2314,7 @@ static buf_T *qf_find_buf(qf_info_T *qi) /* * Find the quickfix buffer. If it exists, update the contents. */ -static void qf_update_buffer(qf_info_T *qi) +static void qf_update_buffer(qf_info_T *qi, bool update_cursor) { buf_T *buf; win_T *win; @@ -2337,8 +2337,9 @@ static void qf_update_buffer(qf_info_T *qi) /* restore curwin/curbuf and a few other things */ aucmd_restbuf(&aco); - - (void)qf_win_pos_update(qi, 0); + if (update_cursor) { + (void)qf_win_pos_update(qi, 0); + } } } @@ -3240,7 +3241,7 @@ void ex_vimgrep(exarg_T *eap) qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; qi->qf_lists[qi->qf_curlist].qf_index = 1; - qf_update_buffer(qi); + qf_update_buffer(qi, true); if (au_name != NULL) apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, @@ -3624,12 +3625,15 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) qi->qf_lists[qi->qf_curlist].qf_nonevalid = TRUE; else qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; - qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; - if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { - qi->qf_lists[qi->qf_curlist].qf_index = 1; + if (action != 'a') { + qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; + if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { + qi->qf_lists[qi->qf_curlist].qf_index = 1; + } } - qf_update_buffer(qi); + // Don't update the cursor in quickfix window when appending entries + qf_update_buffer(qi, (action != 'a')); return retval; } @@ -3885,7 +3889,7 @@ void ex_helpgrep(exarg_T *eap) /* Darn, some plugin changed the value. */ free_string_option(save_cpo); - qf_update_buffer(qi); + qf_update_buffer(qi, true); if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 9dbd00b001..9955b4f775 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -679,3 +679,51 @@ func Test_cgetexpr_works() " this must not crash Vim cgetexpr [$x] endfunc + +" Tests for the setqflist() and setloclist() functions +function SetXlistTests(cchar, bnum) + if a:cchar == 'c' + let Xsetlist = function('setqflist') + let Xgetlist = function('getqflist') + let Xnext = 'cnext' + else + let Xsetlist = function('setloclist', [0]) + let Xgetlist = function('getloclist', [0]) + let Xnext = 'lnext' + endif + + call Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, + \ {'bufnr': a:bnum, 'lnum': 2}]) + let l = Xgetlist() + call assert_equal(2, len(l)) + call assert_equal(2, l[1].lnum) + + exe Xnext + call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a') + let l = Xgetlist() + call assert_equal(3, len(l)) + exe Xnext + call assert_equal(3, line('.')) + + call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, + \ {'bufnr': a:bnum, 'lnum': 4}, + \ {'bufnr': a:bnum, 'lnum': 5}], 'r') + let l = Xgetlist() + call assert_equal(3, len(l)) + call assert_equal(5, l[2].lnum) + + call Xsetlist([]) + let l = Xgetlist() + call assert_equal(0, len(l)) +endfunction + +function Test_setqflist() + new Xtestfile | only + let bnum = bufnr('%') + call setline(1, range(1,5)) + + call SetXlistTests('c', bnum) + call SetXlistTests('l', bnum) + + call delete('Xtestfile') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index ed1d7448ea..d10d5cf75b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -689,7 +689,7 @@ static int included_patches[] = { 1754, 1753, // 1753, - // 1752, + 1752, 1751, // 1750 NA // 1749 NA -- cgit From 29d7a597115b692a7e2e39d213b87ac566444a5c Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 11:33:51 -0500 Subject: vim-patch:7.4.1768 Problem: Arguments of setqflist() are not checked properly. Solution: Add better checks, add a test. (Nikolai Pavlov, Hirohito Higashi, closes vim/vim#661) https://github.com/vim/vim/commit/d106e5ba7f10f0d2a14eaefe5d78405044416cb9 --- src/nvim/eval.c | 11 ++-- src/nvim/po/uk.po | 4 +- src/nvim/testdir/test_quickfix.vim | 102 ++++++++++++++++++++++++++++++++++--- src/nvim/version.c | 2 +- 4 files changed, 105 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 39e121eb53..45364a1666 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -158,7 +158,7 @@ static char *e_listdictarg = N_( static char *e_emptykey = N_("E713: Cannot use empty key for Dictionary"); static char *e_listreq = N_("E714: List required"); static char *e_dictreq = N_("E715: Dictionary required"); -static char *e_strreq = N_("E114: String required"); +static char *e_stringreq = N_("E928: String required"); static char *e_toomanyarg = N_("E118: Too many arguments for function: %s"); static char *e_dictkey = N_("E716: Key not present in Dictionary: %s"); static char *e_funcexts = N_( @@ -14996,6 +14996,7 @@ static void f_setline(typval_T *argvars, typval_T *rettv, FunPtr fptr) static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) FUNC_ATTR_NONNULL_ARG(2, 3) { + static char *e_invact = N_("E927: Invalid action: '%s'"); char_u *title = NULL; int action = ' '; rettv->vval.v_number = -1; @@ -15011,13 +15012,17 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) // Option argument was not given. goto skip_args; } else if (action_arg->v_type != VAR_STRING) { - EMSG(_(e_strreq)); + EMSG(_(e_stringreq)); return; } char_u *act = get_tv_string_chk(action_arg); - if (*act == 'a' || *act == 'r') { + if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) { action = *act; } + else { + EMSG2(_(e_invact), act); + return; + } typval_T *title_arg = &args[2]; if (title_arg->v_type == VAR_UNKNOWN) { diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po index bbbb462292..3145931bfe 100644 --- a/src/nvim/po/uk.po +++ b/src/nvim/po/uk.po @@ -564,8 +564,8 @@ msgstr "E714: Потрібен список" msgid "E715: Dictionary required" msgstr "E715: Потрібен словник" -msgid "E114: String required" -msgstr "E114: Потрібен String" +msgid "E928: String required" +msgstr "E928: Потрібен String" #, c-format msgid "E118: Too many arguments for function: %s" diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 9955b4f775..2c6f3c922a 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -483,7 +483,7 @@ endfunction function Test_locationlist_curwin_was_closed() augroup testgroup au! - autocmd BufReadCmd t call R(expand("")) + autocmd BufReadCmd test_curwin.txt call R(expand("")) augroup END function! R(n) @@ -492,7 +492,7 @@ function Test_locationlist_curwin_was_closed() new let q = [] - call add(q, {'filename': 't' }) + call add(q, {'filename': 'test_curwin.txt' }) call setloclist(0, q) call assert_fails('lrewind', 'E924:') @@ -625,14 +625,14 @@ function XquickfixChangedByAutocmd(cchar) let Xgetexpr = a:cchar . 'getexpr' let Xrewind = a:cchar . 'rewind' if a:cchar == 'c' - let Xsetlist = 'setqflist(' + let Xsetlist = function('setqflist') let ErrorNr = 'E925' function! ReadFunc() colder cgetexpr [] endfunc else - let Xsetlist = 'setloclist(0,' + let Xsetlist = function('setloclist', [0]) let ErrorNr = 'E926' function! ReadFunc() lolder @@ -642,15 +642,15 @@ function XquickfixChangedByAutocmd(cchar) augroup testgroup au! - autocmd BufReadCmd t call ReadFunc() + autocmd BufReadCmd test_changed.txt call ReadFunc() augroup END - bwipe! + new | only let words = [ "a", "b" ] let qflist = [] for word in words - call add(qflist, {'filename': 't'}) - exec "call " . Xsetlist . "qflist, '')" + call add(qflist, {'filename': 'test_changed.txt'}) + call Xsetlist(qflist, ' ') endfor exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" @@ -727,3 +727,89 @@ function Test_setqflist() call delete('Xtestfile') endfunction + +function! XquickfixSetListWithAct(cchar) + let Xolder = a:cchar . 'older' + let Xnewer = a:cchar . 'newer' + if a:cchar == 'c' + let Xsetlist = function('setqflist') + let Xgetlist = function('getqflist') + else + let Xsetlist = function('setloclist', [0]) + let Xgetlist = function('getloclist', [0]) + endif + let list1 = [{'filename': 'fnameA', 'text': 'A'}, + \ {'filename': 'fnameB', 'text': 'B'}] + let list2 = [{'filename': 'fnameC', 'text': 'C'}, + \ {'filename': 'fnameD', 'text': 'D'}, + \ {'filename': 'fnameE', 'text': 'E'}] + + " {action} is unspecified. Same as specifing ' '. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2) + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + exec "silent! " . Xolder + let li = Xgetlist() + call assert_equal(2, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + + " {action} is specified ' '. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, ' ') + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + exec "silent! " . Xolder + let li = Xgetlist() + call assert_equal(2, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + + " {action} is specified 'a'. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, 'a') + let li = Xgetlist() + call assert_equal(5, len(li)) + call assert_equal('A', li[0]['text']) + call assert_equal('B', li[1]['text']) + call assert_equal('C', li[2]['text']) + call assert_equal('D', li[3]['text']) + call assert_equal('E', li[4]['text']) + + " {action} is specified 'r'. + new | only + exec "silent! " . Xnewer . "99" + call Xsetlist(list1) + call Xsetlist(list2, 'r') + let li = Xgetlist() + call assert_equal(3, len(li)) + call assert_equal('C', li[0]['text']) + call assert_equal('D', li[1]['text']) + call assert_equal('E', li[2]['text']) + + " Test for wrong value. + new | only + call assert_fails("call Xsetlist(0)", 'E714:') + call assert_fails("call Xsetlist(list1, '')", 'E927:') + call assert_fails("call Xsetlist(list1, 'aa')", 'E927:') + call assert_fails("call Xsetlist(list1, ' a')", 'E927:') + call assert_fails("call Xsetlist(list1, 0)", 'E928:') +endfunc + +function Test_quickfix_set_list_with_act() + call XquickfixSetListWithAct('c') + call XquickfixSetListWithAct('l') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index d10d5cf75b..a5addaf819 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -672,7 +672,7 @@ static int included_patches[] = { // 1771 NA // 1770 NA // 1769, - // 1768, + 1768, // 1767 NA // 1766 NA 1765, -- cgit From 39faa56bce66796f731ec339301acc3d303c08e9 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:04:44 -0500 Subject: vim-patch:7.4.1802 Problem: Quickfix doesn't handle long lines well, they are split. Solution: Drop characters after a limit. (Anton Lindqvist) https://github.com/vim/vim/commit/6be8c8e165204b8aa4eeb8a52be87a58d8b41b9e --- src/nvim/quickfix.c | 210 ++++++++++++++++++++++++++++------ src/nvim/testdir/samples/quickfix.txt | 3 + src/nvim/testdir/test_quickfix.vim | 37 ++++++ src/nvim/version.c | 2 +- 4 files changed, 216 insertions(+), 36 deletions(-) create mode 100644 src/nvim/testdir/samples/quickfix.txt (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index b97530b700..3c59fcef03 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -168,6 +168,9 @@ qf_init ( qf_title); } +// Maximum number of bytes allowed per line while reading an errorfile. +static const size_t LINE_MAXLEN = 4096; + /* * Read the errorfile "efile" into memory, line by line, building the error * list. @@ -192,8 +195,15 @@ qf_init_ext ( { char_u *namebuf; char_u *errmsg; + size_t errmsglen; char_u *pattern; char_u *fmtstr = NULL; + char_u *growbuf = NULL; + size_t growbuflen; + size_t growbufsiz; + char_u *linebuf; + size_t linelen; + bool discard; int col = 0; bool use_viscol = false; char_u type = 0; @@ -210,7 +220,7 @@ qf_init_ext ( char_u *efm; char_u *ptr; char_u *srcptr; - int len; + size_t len; int i; int round; int idx = 0; @@ -221,6 +231,7 @@ qf_init_ext ( char_u *directory = NULL; char_u *currfile = NULL; char_u *tail = NULL; + char_u *p_buf = NULL; char_u *p_str = NULL; listitem_T *p_li = NULL; struct dir_stack_T *file_stack = NULL; @@ -243,7 +254,8 @@ qf_init_ext ( }; namebuf = xmalloc(CMDBUFFSIZE + 1); - errmsg = xmalloc(CMDBUFFSIZE + 1); + errmsglen = CMDBUFFSIZE + 1; + errmsg = xmalloc(errmsglen); pattern = xmalloc(CMDBUFFSIZE + 1); if (efile != NULL && (fd = mch_fopen((char *)efile, "r")) == NULL) { @@ -466,36 +478,66 @@ qf_init_ext ( /* Get the next line from the supplied string */ char_u *p; - if (!*p_str) /* Reached the end of the string */ + if (*p_str == NUL) // Reached the end of the string break; p = vim_strchr(p_str, '\n'); - if (p) - len = (int)(p - p_str + 1); - else - len = (int)STRLEN(p_str); - - if (len > CMDBUFFSIZE - 2) - STRLCPY(IObuff, p_str, CMDBUFFSIZE - 1); + if (p != NULL) + len = (size_t)(p - p_str) + 1; else - STRLCPY(IObuff, p_str, len + 1); + len = STRLEN(p_str); + + if (len > IOSIZE - 2) { + // If the line exceeds LINE_MAXLEN exclude the last byte since it's + // not a NL character. + linelen = len > LINE_MAXLEN ? LINE_MAXLEN - 1 : len; + if (growbuf == NULL) { + growbuf = xmalloc(linelen); + } else if (linelen > growbufsiz) { + growbuf = xrealloc(growbuf, linelen); + } + growbufsiz = linelen; + linebuf = growbuf; + } else { + linebuf = IObuff; + linelen = len; + } + STRLCPY(linebuf, p_str, linelen + 1); + // Increment using len in order to discard the rest of the line if it + // exceeds LINE_MAXLEN. p_str += len; } else if (tv->v_type == VAR_LIST) { // Get the next line from the supplied list - while (p_li && (p_li->li_tv.v_type != VAR_STRING - || p_li->li_tv.vval.v_string == NULL)) { + while (p_li != NULL + && (p_li->li_tv.v_type != VAR_STRING + || p_li->li_tv.vval.v_string == NULL)) { p_li = p_li->li_next; // Skip non-string items } - if (!p_li) /* End of the list */ + if (p_li == NULL) // End of the list break; - len = (int)STRLEN(p_li->li_tv.vval.v_string); - if (len > CMDBUFFSIZE - 2) - len = CMDBUFFSIZE - 2; + len = STRLEN(p_li->li_tv.vval.v_string); + if (len > IOSIZE - 2) { + linelen = len; + if (linelen > LINE_MAXLEN) { + linelen = LINE_MAXLEN - 1; + } + if (growbuf == NULL) { + growbuf = xmalloc(linelen); + growbufsiz = linelen; + } else if (linelen > growbufsiz) { + growbuf = xrealloc(growbuf, linelen); + growbufsiz = linelen; + } + linebuf = growbuf; + } else { + linebuf = IObuff; + linelen = len; + } - STRLCPY(IObuff, p_li->li_tv.vval.v_string, len + 1); + STRLCPY(linebuf, p_li->li_tv.vval.v_string, linelen + 1); p_li = p_li->li_next; /* next item */ } @@ -503,21 +545,103 @@ qf_init_ext ( /* Get the next line from the supplied buffer */ if (buflnum > lnumlast) break; - STRLCPY(IObuff, ml_get_buf(buf, buflnum++, FALSE), - CMDBUFFSIZE - 1); + p_buf = ml_get_buf(buf, buflnum++, false); + linelen = STRLEN(p_buf); + if (linelen > IOSIZE - 2) { + if (growbuf == NULL) { + growbuf = xmalloc(linelen); + growbufsiz = linelen; + } else if (linelen > growbufsiz) { + if (linelen > LINE_MAXLEN) { + linelen = LINE_MAXLEN - 1; + } + growbuf = xrealloc(growbuf, linelen); + growbufsiz = linelen; + } + linebuf = growbuf; + } else { + linebuf = IObuff; + } + STRLCPY(linebuf, p_buf, linelen + 1); } - } else if (fgets((char *)IObuff, CMDBUFFSIZE - 2, fd) == NULL) - break; + } else { + if (fgets((char *)IObuff, IOSIZE, fd) == NULL) { + break; + } + + discard = false; + linelen = STRLEN(IObuff); + if (linelen == IOSIZE - 1 && (IObuff[linelen - 1] != '\n' +#ifdef USE_CRNL + || IObuff[linelen - 1] != '\r' +#endif + )) { + // The current line exceeds IObuff, continue reading using growbuf + // until EOL or LINE_MAXLEN bytes is read. + if (growbuf == NULL) { + growbufsiz = 2 * (IOSIZE - 1); + growbuf = xmalloc(growbufsiz); + } + + // Copy the read part of the line, excluding null-terminator + memcpy(growbuf, IObuff, IOSIZE - 1); + growbuflen = linelen; + + for (;;) { + if (fgets((char*)growbuf + growbuflen, + (int)(growbufsiz - growbuflen), fd) == NULL) { + break; + } + linelen = STRLEN(growbuf + growbuflen); + growbuflen += linelen; + if (growbuf[growbuflen - 1] == '\n' +#ifdef USE_CRNL + || growbuf[growbuflen - 1] == '\r' +#endif + ) { + break; + } + if (growbufsiz == LINE_MAXLEN) { + discard = true; + break; + } - IObuff[CMDBUFFSIZE - 2] = NUL; /* for very long lines */ - remove_bom(IObuff); + growbufsiz = (2 * growbufsiz < LINE_MAXLEN) + ? 2 * growbufsiz : LINE_MAXLEN; + growbuf = xrealloc(growbuf, 2 * growbufsiz); + } - if ((efmp = vim_strrchr(IObuff, '\n')) != NULL) - *efmp = NUL; + while (discard) { + // The current line is longer than LINE_MAXLEN, continue reading but + // discard everything until EOL or EOF is reached. + if (fgets((char *)IObuff, IOSIZE, fd) == NULL + || STRLEN(IObuff) < IOSIZE - 1 + || IObuff[IOSIZE - 1] == '\n' #ifdef USE_CRNL - if ((efmp = vim_strrchr(IObuff, '\r')) != NULL) - *efmp = NUL; + || IObuff[IOSIZE - 1] == '\r' #endif + ) { + break; + } + } + + linebuf = growbuf; + linelen = growbuflen; + } else { + linebuf = IObuff; + } + } + + if (linelen > 0 && linebuf[linelen - 1] == '\n') { + linebuf[linelen - 1] = NUL; + } +#ifdef USE_CRNL + if (linelen > 0 && linebuf[linelen - 1] == '\r') { + linebuf[linelen - 1] = NUL; + } +#endif + + remove_bom(linebuf); /* If there was no %> item start at the first pattern */ if (fmt_start == NULL) @@ -547,7 +671,7 @@ restofline: tail = NULL; regmatch.regprog = fmt_ptr->prog; - int r = vim_regexec(®match, IObuff, (colnr_T)0); + int r = vim_regexec(®match, linebuf, (colnr_T)0); fmt_ptr->prog = regmatch.regprog; if (r) { if ((idx == 'C' || idx == 'Z') && !multiline) { @@ -596,12 +720,22 @@ restofline: continue; type = *regmatch.startp[i]; } - if (fmt_ptr->flags == '+' && !multiscan) /* %+ */ - STRCPY(errmsg, IObuff); - else if ((i = (int)fmt_ptr->addr[5]) > 0) { /* %m */ + if (fmt_ptr->flags == '+' && !multiscan) { // %+ + if (linelen > errmsglen) { + // linelen + null terminator + errmsg = xrealloc(errmsg, linelen + 1); + errmsglen = linelen + 1; + } + STRLCPY(errmsg, linebuf, linelen + 1); + } else if ((i = (int)fmt_ptr->addr[5]) > 0) { /* %m */ if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) continue; - len = (int)(regmatch.endp[i] - regmatch.startp[i]); + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); + if (len > errmsglen) { + // len + null terminator + errmsg = xrealloc(errmsg, len + 1); + errmsglen = len + 1; + } STRLCPY(errmsg, regmatch.startp[i], len + 1); } if ((i = (int)fmt_ptr->addr[6]) > 0) { /* %r */ @@ -635,7 +769,7 @@ restofline: if ((i = (int)fmt_ptr->addr[9]) > 0) { /* %s */ if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) continue; - len = (int)(regmatch.endp[i] - regmatch.startp[i]); + len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); if (len > CMDBUFFSIZE - 5) len = CMDBUFFSIZE - 5; STRCPY(pattern, "^\\V"); @@ -664,7 +798,12 @@ restofline: namebuf[0] = NUL; // no match found, remove file name lnum = 0; // don't jump to this line valid = false; - STRCPY(errmsg, IObuff); // copy whole line to error message + if (linelen > errmsglen) { + // linelen + null terminator + errmsg = xrealloc(errmsg, linelen + 1); + } + // copy whole line to error message + STRLCPY(errmsg, linebuf, linelen + 1); if (fmt_ptr == NULL) { multiline = multiignore = false; } @@ -785,6 +924,7 @@ qf_init_end: xfree(errmsg); xfree(pattern); xfree(fmtstr); + xfree(growbuf); qf_update_buffer(qi, true); diff --git a/src/nvim/testdir/samples/quickfix.txt b/src/nvim/testdir/samples/quickfix.txt new file mode 100644 index 0000000000..38c8f49149 --- /dev/null +++ b/src/nvim/testdir/samples/quickfix.txt @@ -0,0 +1,3 @@ +samples/quickfix.txt:1:1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +samples/quickfix.txt:2:1:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb +samples/quickfix.txt:3:1:cccccccccc diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 2c6f3c922a..d43ab1e6db 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -813,3 +813,40 @@ function Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('c') call XquickfixSetListWithAct('l') endfunction + +func XLongLinesTests() + let l = getqflist() + + call assert_equal(3, len(l)) + call assert_equal(1, l[0].lnum) + call assert_equal(1, l[0].col) + call assert_equal(4070, len(l[0].text)) + call assert_equal(2, l[1].lnum) + call assert_equal(1, l[1].col) + call assert_equal(4070, len(l[1].text)) + call assert_equal(3, l[2].lnum) + call assert_equal(1, l[2].col) + call assert_equal(10, len(l[2].text)) + + call setqflist([], 'r') +endfunc + +func Test_long_lines() + let testfile = 'samples/quickfix.txt' + + " file + exe 'cgetfile' testfile + call XLongLinesTests() + + " list + cexpr readfile(testfile) + call XLongLinesTests() + + " string + cexpr join(readfile(testfile), "\n") + call XLongLinesTests() + + " buffer + e testfile + exe 'cbuffer' bufnr('%') +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index a5addaf819..897daf359c 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -637,7 +637,7 @@ static int included_patches[] = { // 1805 NA // 1804 NA // 1803 NA - // 1802, + 1802, // 1801 NA // 1800 NA 1799, -- cgit From 48b5d0f1ba1ad75411f6510ed79d322116ba6809 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:04:52 -0500 Subject: vim-patch:7.4.1813 Problem: Memory access error when running test_quickfix. Solution: Allocate one more byte. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/9b4ebc692d77ca8ef90d72517347f74c2474dd3d --- src/nvim/quickfix.c | 12 ++++++------ src/nvim/version.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 3c59fcef03..b4f8750c4c 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -492,9 +492,9 @@ qf_init_ext ( // not a NL character. linelen = len > LINE_MAXLEN ? LINE_MAXLEN - 1 : len; if (growbuf == NULL) { - growbuf = xmalloc(linelen); + growbuf = xmalloc(linelen + 1); } else if (linelen > growbufsiz) { - growbuf = xrealloc(growbuf, linelen); + growbuf = xrealloc(growbuf, linelen + 1); } growbufsiz = linelen; linebuf = growbuf; @@ -525,10 +525,10 @@ qf_init_ext ( linelen = LINE_MAXLEN - 1; } if (growbuf == NULL) { - growbuf = xmalloc(linelen); + growbuf = xmalloc(linelen + 1); growbufsiz = linelen; } else if (linelen > growbufsiz) { - growbuf = xrealloc(growbuf, linelen); + growbuf = xrealloc(growbuf, linelen + 1); growbufsiz = linelen; } linebuf = growbuf; @@ -549,13 +549,13 @@ qf_init_ext ( linelen = STRLEN(p_buf); if (linelen > IOSIZE - 2) { if (growbuf == NULL) { - growbuf = xmalloc(linelen); + growbuf = xmalloc(linelen + 1); growbufsiz = linelen; } else if (linelen > growbufsiz) { if (linelen > LINE_MAXLEN) { linelen = LINE_MAXLEN - 1; } - growbuf = xrealloc(growbuf, linelen); + growbuf = xrealloc(growbuf, linelen + 1); growbufsiz = linelen; } linebuf = growbuf; diff --git a/src/nvim/version.c b/src/nvim/version.c index 897daf359c..5edced3f0d 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -626,7 +626,7 @@ static int included_patches[] = { 1816, // 1815, // 1814 NA - // 1813, + 1813, // 1812, // 1811 NA // 1810 NA -- cgit From b9c5ca21e6a666dfcd3324720ca59ed52ce34883 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:04:57 -0500 Subject: vim-patch:7.4.1815 Problem: Compiler warnings for unused variables. (Ajit Thakkar) Solution: Add a dummy initialization. (Yasuhiro Matsumoto) https://github.com/vim/vim/commit/9a3b3311d26c990208150255ad65472bb4eefaa4 --- src/nvim/quickfix.c | 6 +++--- src/nvim/version.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index b4f8750c4c..1188ed7fd4 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -200,9 +200,9 @@ qf_init_ext ( char_u *fmtstr = NULL; char_u *growbuf = NULL; size_t growbuflen; - size_t growbufsiz; - char_u *linebuf; - size_t linelen; + size_t growbufsiz = 0; + char_u *linebuf = NULL; + size_t linelen = 0; bool discard; int col = 0; bool use_viscol = false; diff --git a/src/nvim/version.c b/src/nvim/version.c index 5edced3f0d..e8f639fcd4 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -624,7 +624,7 @@ static int included_patches[] = { 1818, // 1817 NA 1816, - // 1815, + 1815, // 1814 NA 1813, // 1812, -- cgit From e2b081ed0c9aa43e891e5b33c1f3f077bc579356 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Tue, 13 Dec 2016 11:03:28 -0500 Subject: vim-patch:7.4.1823 Problem: Warning from 64 bit compiler. Solution: Add type cast. (Mike Williams) https://github.com/vim/vim/commit/d9db8b448c214eb583e84c598bca0688b9202ba7 Already silenced in earlier commits by using size_t. --- src/nvim/version.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/version.c b/src/nvim/version.c index e8f639fcd4..c8eae8b588 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -616,7 +616,7 @@ static int included_patches[] = { // 1826 NA // 1825 NA // 1824 NA - // 1823, + 1823, // 1822 NA 1821, 1820, -- cgit From 9df9cf4ecc4143ce23b5ab85b2ad1ef413a249bd Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:01 -0500 Subject: vim-patch:7.4.1841 Problem: The code to reallocate the buffer used for quickfix is repeated. Solution: Move the code to a function. (Yegappan Lakshmanan, closes vim/vim#831) https://github.com/vim/vim/commit/2b2b8ae5ab37b04584633c469265d85825166905 --- src/nvim/quickfix.c | 52 ++++++++++++++------------------------ src/nvim/testdir/test_quickfix.vim | 13 ++++++++-- src/nvim/version.c | 2 +- 3 files changed, 31 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1188ed7fd4..a68c4eca2e 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -171,6 +171,22 @@ qf_init ( // Maximum number of bytes allowed per line while reading an errorfile. static const size_t LINE_MAXLEN = 4096; +static char_u *qf_grow_linebuf(char_u **growbuf, size_t *growbufsiz, + size_t newsz, size_t *allocsz) +{ + // If the line exceeds LINE_MAXLEN exclude the last + // byte since it's not a NL character. + *allocsz = newsz > LINE_MAXLEN ? LINE_MAXLEN - 1 : newsz; + if (*growbuf == NULL) { + *growbuf = xmalloc(*allocsz + 1); + *growbufsiz = *allocsz; + } else if (*allocsz > *growbufsiz) { + *growbuf = xrealloc(*growbuf, *allocsz + 1); + *growbufsiz = *allocsz; + } + return *growbuf; +} + /* * Read the errorfile "efile" into memory, line by line, building the error * list. @@ -488,16 +504,7 @@ qf_init_ext ( len = STRLEN(p_str); if (len > IOSIZE - 2) { - // If the line exceeds LINE_MAXLEN exclude the last byte since it's - // not a NL character. - linelen = len > LINE_MAXLEN ? LINE_MAXLEN - 1 : len; - if (growbuf == NULL) { - growbuf = xmalloc(linelen + 1); - } else if (linelen > growbufsiz) { - growbuf = xrealloc(growbuf, linelen + 1); - } - growbufsiz = linelen; - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); } else { linebuf = IObuff; linelen = len; @@ -520,18 +527,7 @@ qf_init_ext ( len = STRLEN(p_li->li_tv.vval.v_string); if (len > IOSIZE - 2) { - linelen = len; - if (linelen > LINE_MAXLEN) { - linelen = LINE_MAXLEN - 1; - } - if (growbuf == NULL) { - growbuf = xmalloc(linelen + 1); - growbufsiz = linelen; - } else if (linelen > growbufsiz) { - growbuf = xrealloc(growbuf, linelen + 1); - growbufsiz = linelen; - } - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); } else { linebuf = IObuff; linelen = len; @@ -548,17 +544,7 @@ qf_init_ext ( p_buf = ml_get_buf(buf, buflnum++, false); linelen = STRLEN(p_buf); if (linelen > IOSIZE - 2) { - if (growbuf == NULL) { - growbuf = xmalloc(linelen + 1); - growbufsiz = linelen; - } else if (linelen > growbufsiz) { - if (linelen > LINE_MAXLEN) { - linelen = LINE_MAXLEN - 1; - } - growbuf = xrealloc(growbuf, linelen + 1); - growbufsiz = linelen; - } - linebuf = growbuf; + linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); } else { linebuf = IObuff; } diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index d43ab1e6db..73ee240c77 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -682,14 +682,14 @@ endfunc " Tests for the setqflist() and setloclist() functions function SetXlistTests(cchar, bnum) + let Xwindow = a:cchar . 'window' + let Xnext = a:cchar . 'next' if a:cchar == 'c' let Xsetlist = function('setqflist') let Xgetlist = function('getqflist') - let Xnext = 'cnext' else let Xsetlist = function('setloclist', [0]) let Xgetlist = function('getloclist', [0]) - let Xnext = 'lnext' endif call Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, @@ -705,6 +705,15 @@ function SetXlistTests(cchar, bnum) exe Xnext call assert_equal(3, line('.')) + " Appending entries to the list should not change the cursor position + " in the quickfix window + exe Xwindow + 1 + call Xsetlist([{'bufnr': a:bnum, 'lnum': 4}, + \ {'bufnr': a:bnum, 'lnum': 5}], 'a') + call assert_equal(1, line('.')) + close + call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, \ {'bufnr': a:bnum, 'lnum': 4}, \ {'bufnr': a:bnum, 'lnum': 5}], 'r') diff --git a/src/nvim/version.c b/src/nvim/version.c index c8eae8b588..8af6579ac4 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -599,7 +599,7 @@ static int included_patches[] = { // 1844, // 1843 NA 1842, - // 1841, + 1841, 1840, // 1839, // 1838, -- cgit From d244068f4fda821888a08858c8a00722f0326da6 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:06 -0500 Subject: vim-patch:7.4.1871 Problem: Appending to the quickfix list while the quickfix window is open is very slow. Solution: Do not delete all the lines, only append the new ones. Avoid using a window while updating the list. (closes vim/vim#841) https://github.com/vim/vim/commit/864293abb72d62604d8d6b458addfb43c14230c3 --- src/nvim/quickfix.c | 144 ++++++++++++++++++++++++++++++++-------------------- src/nvim/version.c | 2 +- 2 files changed, 90 insertions(+), 56 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index a68c4eca2e..dcc4ebcc1b 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -187,15 +187,14 @@ static char_u *qf_grow_linebuf(char_u **growbuf, size_t *growbufsiz, return *growbuf; } -/* - * Read the errorfile "efile" into memory, line by line, building the error - * list. - * Alternative: when "efile" is null read errors from buffer "buf". - * Always use 'errorformat' from "buf" if there is a local value. - * Then "lnumfirst" and "lnumlast" specify the range of lines to use. - * Set the title of the list to "qf_title". - * Return -1 for error, number of errors for success. - */ +// Read the errorfile "efile" into memory, line by line, building the error +// list. +// Alternative: when "efile" is NULL read errors from buffer "buf". +// Alternative: when "tv" is not NULL get errors from the string or list. +// Always use 'errorformat' from "buf" if there is a local value. +// Then "lnumfirst" and "lnumlast" specify the range of lines to use. +// Set the title of the list to "qf_title". +// Return -1 for error, number of errors for success. static int qf_init_ext ( qf_info_T *qi, @@ -228,6 +227,7 @@ qf_init_ext ( int enr = 0; FILE *fd = NULL; qfline_T *qfprev = NULL; /* init to make SASC shut up */ + qfline_T *old_last = NULL; char_u *efmp; efm_T *fmt_first = NULL; efm_T *fmt_last = NULL; @@ -282,11 +282,13 @@ qf_init_ext ( if (newlist || qi->qf_curlist == qi->qf_listcount) /* make place for a new list */ qf_new_list(qi, qf_title); - else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) + else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { /* Adding to existing list, find last entry. */ for (qfprev = qi->qf_lists[qi->qf_curlist].qf_start; qfprev->qf_next != qfprev; qfprev = qfprev->qf_next) ; + old_last = qfprev; + } /* * Each part of the format string is copied and modified from errorformat to @@ -912,7 +914,7 @@ qf_init_end: xfree(fmtstr); xfree(growbuf); - qf_update_buffer(qi, true); + qf_update_buffer(qi, old_last); return retval; } @@ -2053,7 +2055,7 @@ static void qf_msg(qf_info_T *qi) smsg(_("error list %d of %d; %d errors"), qi->qf_curlist + 1, qi->qf_listcount, qi->qf_lists[qi->qf_curlist].qf_count); - qf_update_buffer(qi, true); + qf_update_buffer(qi, NULL); } /* @@ -2321,7 +2323,7 @@ void ex_copen(exarg_T *eap) qf_set_title_var(qi); // Fill the buffer with the quickfix list. - qf_fill_buffer(qi); + qf_fill_buffer(qi, curbuf, NULL); curwin->w_cursor.lnum = qi->qf_lists[qi->qf_curlist].qf_index; curwin->w_cursor.col = 0; @@ -2440,7 +2442,7 @@ static buf_T *qf_find_buf(qf_info_T *qi) /* * Find the quickfix buffer. If it exists, update the contents. */ -static void qf_update_buffer(qf_info_T *qi, bool update_cursor) +static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { buf_T *buf; win_T *win; @@ -2450,8 +2452,12 @@ static void qf_update_buffer(qf_info_T *qi, bool update_cursor) /* Check if a buffer for the quickfix list exists. Update it. */ buf = qf_find_buf(qi); if (buf != NULL) { - /* set curwin/curbuf to buf and save a few things */ - aucmd_prepbuf(&aco, buf); + linenr_T old_line_count = buf->b_ml.ml_line_count; + + if (old_last == NULL) { + // set curwin/curbuf to buf and save a few things + aucmd_prepbuf(&aco, buf); + } if ((win = qf_find_win(qi)) != NULL) { curwin_save = curwin; @@ -2459,12 +2465,20 @@ static void qf_update_buffer(qf_info_T *qi, bool update_cursor) qf_set_title_var(qi); curwin = curwin_save; } - qf_fill_buffer(qi); - /* restore curwin/curbuf and a few other things */ - aucmd_restbuf(&aco); - if (update_cursor) { + qf_fill_buffer(qi, buf, old_last); + + if (old_last == NULL) { (void)qf_win_pos_update(qi, 0); + + // restore curwin/curbuf and a few other things + aucmd_restbuf(&aco); + } + + // Only redraw when added lines are visible. This avoids flickering when + // the added lines are not visible. + if ((win = qf_find_win(qi)) != NULL && old_line_count < win->w_botline) { + redraw_buf_later(buf, NOT_VALID); } } } @@ -2478,11 +2492,12 @@ static void qf_set_title_var(qf_info_T *qi) } } -/* - * Fill current buffer with quickfix errors, replacing any previous contents. - * curbuf must be the quickfix buffer! - */ -static void qf_fill_buffer(qf_info_T *qi) +// Fill current buffer with quickfix errors, replacing any previous contents. +// curbuf must be the quickfix buffer! +// If "old_last" is not NULL append the items after this one. +// When "old_last" is NULL then "buf" must equal "curbuf"! Because ml_delete() +// is used and autocommands will be triggered. +static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) { linenr_T lnum; qfline_T *qfp; @@ -2490,15 +2505,28 @@ static void qf_fill_buffer(qf_info_T *qi) int len; int old_KeyTyped = KeyTyped; - /* delete all existing lines */ - while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) - (void)ml_delete((linenr_T)1, FALSE); + if (old_last == NULL) { + if (buf != curbuf) { + EMSG2(_(e_intern2), "qf_fill_buffer()"); + return; + } + + /* delete all existing lines */ + while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) + (void)ml_delete((linenr_T)1, FALSE); + } /* Check if there is anything to display */ if (qi->qf_curlist < qi->qf_listcount) { /* Add one line for each error */ - qfp = qi->qf_lists[qi->qf_curlist].qf_start; - for (lnum = 0; lnum < qi->qf_lists[qi->qf_curlist].qf_count; ++lnum) { + if (old_last == NULL) { + qfp = qi->qf_lists[qi->qf_curlist].qf_start; + lnum = 0; + } else { + qfp = old_last->qf_next; + lnum = buf->b_ml.ml_line_count; + } + while (lnum < qi->qf_lists[qi->qf_curlist].qf_count) { if (qfp->qf_fnum != 0 && (errbuf = buflist_findnr(qfp->qf_fnum)) != NULL && errbuf->b_fname != NULL) { @@ -2538,33 +2566,38 @@ static void qf_fill_buffer(qf_info_T *qi) qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff + len, IOSIZE - len); - if (ml_append(lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE) + if (ml_append_buf(buf, lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE) == FAIL) break; + lnum++; qfp = qfp->qf_next; } - /* Delete the empty line which is now at the end */ - (void)ml_delete(lnum + 1, FALSE); + if (old_last == NULL) { + /* Delete the empty line which is now at the end */ + (void)ml_delete(lnum + 1, FALSE); + } } /* correct cursor position */ check_lnums(TRUE); - /* Set the 'filetype' to "qf" each time after filling the buffer. This - * resembles reading a file into a buffer, it's more logical when using - * autocommands. */ - set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); - curbuf->b_p_ma = FALSE; + if (old_last == NULL) { + /* Set the 'filetype' to "qf" each time after filling the buffer. This + * resembles reading a file into a buffer, it's more logical when using + * autocommands. */ + set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); + curbuf->b_p_ma = FALSE; - keep_filetype = TRUE; /* don't detect 'filetype' */ - apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, - FALSE, curbuf); - apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, - FALSE, curbuf); - keep_filetype = FALSE; + keep_filetype = TRUE; /* don't detect 'filetype' */ + apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, + FALSE, curbuf); + apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, + FALSE, curbuf); + keep_filetype = FALSE; - /* make sure it will be redrawn */ - redraw_curbuf_later(NOT_VALID); + /* make sure it will be redrawn */ + redraw_curbuf_later(NOT_VALID); + } /* Restore KeyTyped, setting 'filetype' may reset it. */ KeyTyped = old_KeyTyped; @@ -3367,7 +3400,7 @@ void ex_vimgrep(exarg_T *eap) qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; qi->qf_lists[qi->qf_curlist].qf_index = 1; - qf_update_buffer(qi, true); + qf_update_buffer(qi, NULL); if (au_name != NULL) apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, @@ -3655,15 +3688,15 @@ int get_errorlist(win_T *wp, list_T *list) return OK; } -/* - * Populate the quickfix list with the items supplied in the list - * of dictionaries. "title" will be copied to w:quickfix_title - */ +// Populate the quickfix list with the items supplied in the list +// of dictionaries. "title" will be copied to w:quickfix_title +// "action" is 'a' for add, 'r' for replace. Otherwise create a new list. int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) { listitem_T *li; dict_T *d; qfline_T *prevp = NULL; + qfline_T *old_last = NULL; int retval = OK; qf_info_T *qi = &ql_info; bool did_bufnr_emsg = false; @@ -3675,12 +3708,13 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) if (action == ' ' || qi->qf_curlist == qi->qf_listcount) /* make place for a new list */ qf_new_list(qi, title); - else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) + else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) { /* Adding to existing list, find last entry. */ for (prevp = qi->qf_lists[qi->qf_curlist].qf_start; prevp->qf_next != prevp; prevp = prevp->qf_next) ; - else if (action == 'r') { + old_last = prevp; + } else if (action == 'r') { qf_free(qi, qi->qf_curlist); qf_store_title(qi, title); } @@ -3759,7 +3793,7 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) } // Don't update the cursor in quickfix window when appending entries - qf_update_buffer(qi, (action != 'a')); + qf_update_buffer(qi, old_last); return retval; } @@ -4015,7 +4049,7 @@ void ex_helpgrep(exarg_T *eap) /* Darn, some plugin changed the value. */ free_string_option(save_cpo); - qf_update_buffer(qi, true); + qf_update_buffer(qi, NULL); if (au_name != NULL) { apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, diff --git a/src/nvim/version.c b/src/nvim/version.c index 8af6579ac4..93ad69d5f0 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -569,7 +569,7 @@ static int included_patches[] = { // 1874 NA // 1873 NA // 1872 NA - // 1871, + 1871, // 1870 NA // 1869 NA // 1868, -- cgit From 1e49cf6f233f6681a5a269bba84a09d8f8dbac22 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:10 -0500 Subject: vim-patch:7.4.1881 Problem: Appending to a long quickfix list is slow. Solution: Add qf_last. https://github.com/vim/vim/commit/83e6d7ac6a1c2a0cb5ee6c8420a5dc792f1d5ffa --- src/nvim/quickfix.c | 94 ++++++++++++++++++++++++++--------------------------- src/nvim/version.c | 2 +- 2 files changed, 48 insertions(+), 48 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index dcc4ebcc1b..34918e4134 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -77,6 +77,7 @@ struct qfline_S { typedef struct qf_list_S { qfline_T *qf_start; /* pointer to the first error */ + qfline_T *qf_last; // pointer to the last error qfline_T *qf_ptr; /* pointer to the current error */ int qf_count; /* number of errors (0 means no error list) */ int qf_index; /* current index in the error list */ @@ -226,7 +227,6 @@ qf_init_ext ( long lnum = 0L; int enr = 0; FILE *fd = NULL; - qfline_T *qfprev = NULL; /* init to make SASC shut up */ qfline_T *old_last = NULL; char_u *efmp; efm_T *fmt_first = NULL; @@ -283,11 +283,8 @@ qf_init_ext ( /* make place for a new list */ qf_new_list(qi, qf_title); else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { - /* Adding to existing list, find last entry. */ - for (qfprev = qi->qf_lists[qi->qf_curlist].qf_start; - qfprev->qf_next != qfprev; qfprev = qfprev->qf_next) - ; - old_last = qfprev; + /* Adding to existing list, use last entry. */ + old_last = qi->qf_lists[qi->qf_curlist].qf_last; } /* @@ -805,6 +802,7 @@ restofline: multiignore = false; // reset continuation } else if (vim_strchr((char_u *)"CZ", idx) != NULL) { /* continuation of multi-line msg */ + qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; if (qfprev == NULL) goto error2; if (*errmsg && !multiignore) { @@ -857,7 +855,7 @@ restofline: } } - if (qf_add_entry(qi, &qfprev, + if (qf_add_entry(qi, directory, (*namebuf || directory) ? namebuf @@ -997,7 +995,6 @@ void qf_free_all(win_T *wp) /// Add an entry to the end of the list of errors. /// /// @param qi quickfix list -/// @param prevp nonnull pointer (to previously added entry or NULL) /// @param dir optional directory name /// @param fname file name or NULL /// @param bufnum buffer number or zero @@ -1011,12 +1008,12 @@ void qf_free_all(win_T *wp) /// @param valid valid entry /// /// @returns OK or FAIL. -static int qf_add_entry(qf_info_T *qi, qfline_T **prevp, char_u *dir, - char_u *fname, int bufnum, char_u *mesg, long lnum, - int col, char_u vis_col, char_u *pattern, int nr, - char_u type, char_u valid) +static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, + char_u *mesg, long lnum, int col, char_u vis_col, + char_u *pattern, int nr, char_u type, char_u valid) { qfline_T *qfp = xmalloc(sizeof(qfline_T)); + qfline_T **lastp; // pointer to qf_last or NULL if (bufnum != 0) qfp->qf_fnum = bufnum; @@ -1037,20 +1034,21 @@ static int qf_add_entry(qf_info_T *qi, qfline_T **prevp, char_u *dir, qfp->qf_type = type; qfp->qf_valid = valid; + lastp = &qi->qf_lists[qi->qf_curlist].qf_last; if (qi->qf_lists[qi->qf_curlist].qf_count == 0) { /* first element in the list */ qi->qf_lists[qi->qf_curlist].qf_start = qfp; qi->qf_lists[qi->qf_curlist].qf_ptr = qfp; qi->qf_lists[qi->qf_curlist].qf_index = 0; - qfp->qf_prev = qfp; // first element points to itself + qfp->qf_prev = NULL; } else { - assert(*prevp); - qfp->qf_prev = *prevp; - (*prevp)->qf_next = qfp; + assert(*lastp); + qfp->qf_prev = *lastp; + (*lastp)->qf_next = qfp; } - qfp->qf_next = qfp; /* last element points to itself */ + qfp->qf_next = NULL; qfp->qf_cleared = FALSE; - *prevp = qfp; + *lastp = qfp; ++qi->qf_lists[qi->qf_curlist].qf_count; if (qi->qf_lists[qi->qf_curlist].qf_index == 0 && qfp->qf_valid) { /* first valid entry */ @@ -1136,6 +1134,7 @@ void copy_loclist(win_T *from, win_T *to) to_qfl->qf_count = 0; to_qfl->qf_index = 0; to_qfl->qf_start = NULL; + to_qfl->qf_last = NULL; to_qfl->qf_ptr = NULL; if (from_qfl->qf_title != NULL) to_qfl->qf_title = vim_strsave(from_qfl->qf_title); @@ -1144,12 +1143,13 @@ void copy_loclist(win_T *from, win_T *to) if (from_qfl->qf_count) { qfline_T *from_qfp; - qfline_T *prevp = NULL; + qfline_T *prevp; /* copy all the location entries in this list */ - for (i = 0, from_qfp = from_qfl->qf_start; i < from_qfl->qf_count; + for (i = 0, from_qfp = from_qfl->qf_start; + i < from_qfl->qf_count && from_qfp != NULL; ++i, from_qfp = from_qfp->qf_next) { - if (qf_add_entry(to->w_llist, &prevp, + if (qf_add_entry(to->w_llist, NULL, NULL, 0, @@ -1169,6 +1169,7 @@ void copy_loclist(win_T *from, win_T *to) * directory and file names are not supplied. So the qf_fnum * field is copied here. */ + prevp = to->w_llist->qf_lists[to->w_llist->qf_curlist].qf_last; prevp->qf_fnum = from_qfp->qf_fnum; /* file number */ prevp->qf_type = from_qfp->qf_type; /* error type */ if (from_qfl->qf_ptr == from_qfp) @@ -1400,7 +1401,7 @@ static bool is_qf_entry_present(qf_info_T *qi, qfline_T *qf_ptr) // Search for the entry in the current list for (i = 0, qfp = qfl->qf_start; i < qfl->qf_count; i++, qfp = qfp->qf_next) { - if (qfp == qf_ptr) { + if (qfp == NULL || qfp == qf_ptr) { break; } } @@ -1981,6 +1982,9 @@ void qf_list(exarg_T *eap) } qfp = qfp->qf_next; + if (qfp == NULL) { + break; + } ++i; os_breakcheck(); } @@ -2064,22 +2068,24 @@ static void qf_msg(qf_info_T *qi) static void qf_free(qf_info_T *qi, int idx) { qfline_T *qfp; + qfline_T *qfpnext; int stop = FALSE; - while (qi->qf_lists[idx].qf_count) { - qfp = qi->qf_lists[idx].qf_start->qf_next; + while (qi->qf_lists[idx].qf_count && qi->qf_lists[idx].qf_start != NULL) { + qfp = qi->qf_lists[idx].qf_start; + qfpnext = qfp->qf_next; if (qi->qf_lists[idx].qf_title != NULL && !stop) { - xfree(qi->qf_lists[idx].qf_start->qf_text); - stop = (qi->qf_lists[idx].qf_start == qfp); - xfree(qi->qf_lists[idx].qf_start->qf_pattern); - xfree(qi->qf_lists[idx].qf_start); + xfree(qfp->qf_text); + stop = (qfp == qfpnext); + xfree(qfp->qf_pattern); + xfree(qfp); if (stop) /* Somehow qf_count may have an incorrect value, set it to 1 * to avoid crashing when it's wrong. * TODO: Avoid qf_count being incorrect. */ qi->qf_lists[idx].qf_count = 1; } - qi->qf_lists[idx].qf_start = qfp; + qi->qf_lists[idx].qf_start = qfpnext; --qi->qf_lists[idx].qf_count; } xfree(qi->qf_lists[idx].qf_title); @@ -2108,7 +2114,8 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long for (idx = 0; idx < qi->qf_listcount; ++idx) if (qi->qf_lists[idx].qf_count) for (i = 0, qfp = qi->qf_lists[idx].qf_start; - i < qi->qf_lists[idx].qf_count; ++i, qfp = qfp->qf_next) + i < qi->qf_lists[idx].qf_count && qfp != NULL; + ++i, qfp = qfp->qf_next) if (qfp->qf_fnum == curbuf->b_fnum) { if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) { if (amount == MAXLNUM) @@ -2571,6 +2578,9 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) break; lnum++; qfp = qfp->qf_next; + if (qfp == NULL) { + break; + } } if (old_last == NULL) { /* Delete the empty line which is now at the end */ @@ -3123,7 +3133,6 @@ void ex_vimgrep(exarg_T *eap) int fi; qf_info_T *qi = &ql_info; qfline_T *cur_qf_start; - qfline_T *prevp = NULL; long lnum; buf_T *buf; int duplicate_name = FALSE; @@ -3208,12 +3217,6 @@ void ex_vimgrep(exarg_T *eap) || qi->qf_curlist == qi->qf_listcount) { // make place for a new list qf_new_list(qi, title != NULL ? title : *eap->cmdlinep); - } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { - // Adding to existing list, find last entry. - for (prevp = qi->qf_lists[qi->qf_curlist].qf_start; - prevp->qf_next != prevp; - prevp = prevp->qf_next) { - } } /* parse the list of arguments */ @@ -3311,7 +3314,7 @@ void ex_vimgrep(exarg_T *eap) while (vim_regexec_multi(®match, curwin, buf, lnum, col, NULL) > 0) { ; - if (qf_add_entry(qi, &prevp, + if (qf_add_entry(qi, NULL, /* dir */ fname, 0, @@ -3684,6 +3687,9 @@ int get_errorlist(win_T *wp, list_T *list) return FAIL; qfp = qfp->qf_next; + if (qfp == NULL) { + break; + } } return OK; } @@ -3695,7 +3701,6 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) { listitem_T *li; dict_T *d; - qfline_T *prevp = NULL; qfline_T *old_last = NULL; int retval = OK; qf_info_T *qi = &ql_info; @@ -3709,11 +3714,8 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) /* make place for a new list */ qf_new_list(qi, title); else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) { - /* Adding to existing list, find last entry. */ - for (prevp = qi->qf_lists[qi->qf_curlist].qf_start; - prevp->qf_next != prevp; prevp = prevp->qf_next) - ; - old_last = prevp; + // Adding to existing list, use last entry. + old_last = qi->qf_lists[qi->qf_curlist].qf_last; } else if (action == 'r') { qf_free(qi, qi->qf_curlist); qf_store_title(qi, title); @@ -3756,7 +3758,6 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) } int status = qf_add_entry(qi, - &prevp, NULL, // dir filename, bufnum, @@ -3898,7 +3899,6 @@ void ex_helpgrep(exarg_T *eap) char_u **fnames; FILE *fd; int fi; - qfline_T *prevp = NULL; long lnum; char_u *lang; qf_info_T *qi = &ql_info; @@ -4001,7 +4001,7 @@ void ex_helpgrep(exarg_T *eap) while (l > 0 && line[l - 1] <= ' ') line[--l] = NUL; - if (qf_add_entry(qi, &prevp, + if (qf_add_entry(qi, NULL, /* dir */ fnames[fi], 0, diff --git a/src/nvim/version.c b/src/nvim/version.c index 93ad69d5f0..692bbb27c8 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -559,7 +559,7 @@ static int included_patches[] = { // 1884, // 1883 NA // 1882, - // 1881, + 1881, // 1880 NA // 1879 NA // 1878 NA -- cgit From a86d8b4088d21b784c1b72a03db9c22dcae67d00 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:15 -0500 Subject: vim-patch:7.4.1882 Problem: Check for line break at end of line wrong. (Dominique Pelle) Solution: Correct the logic. https://github.com/vim/vim/commit/b37662a0fbb952838fca87aff4d26b596030b67b --- src/nvim/quickfix.c | 4 ++-- src/nvim/version.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 34918e4134..9703d8763a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -556,9 +556,9 @@ qf_init_ext ( discard = false; linelen = STRLEN(IObuff); - if (linelen == IOSIZE - 1 && (IObuff[linelen - 1] != '\n' + if (linelen == IOSIZE - 1 && !(IObuff[linelen - 1] == '\n' #ifdef USE_CRNL - || IObuff[linelen - 1] != '\r' + || IObuff[linelen - 1] == '\r' #endif )) { // The current line exceeds IObuff, continue reading using growbuf diff --git a/src/nvim/version.c b/src/nvim/version.c index 692bbb27c8..17c1a85a95 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -558,7 +558,7 @@ static int included_patches[] = { // 1885 NA // 1884, // 1883 NA - // 1882, + 1882, 1881, // 1880 NA // 1879 NA -- cgit From ab43303df7f09d1789a70e2536552461657f08ac Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:20 -0500 Subject: vim-patch:7.4.1884 Problem: Updating marks in a quickfix list is very slow when the list is long. Solution: Only update marks if the buffer has a quickfix entry. https://github.com/vim/vim/commit/2f095a4bc4d786e0ac834f48dd18a94fe2d140e3 --- src/nvim/buffer_defs.h | 3 +- src/nvim/quickfix.c | 78 ++++++++++++++++++++++++++++++-------------------- src/nvim/version.c | 2 +- 3 files changed, 50 insertions(+), 33 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index 2f0e8ad974..da08357cb0 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -609,6 +609,7 @@ struct file_buffer { int b_p_bomb; ///< 'bomb' char_u *b_p_bh; ///< 'bufhidden' char_u *b_p_bt; ///< 'buftype' + bool b_has_qf_entry; ///< quickfix exists for buffer int b_p_bl; ///< 'buflisted' int b_p_cin; ///< 'cindent' char_u *b_p_cino; ///< 'cinoptions' @@ -1037,7 +1038,7 @@ struct window_S { int w_wrow, w_wcol; /* cursor position in window */ linenr_T w_botline; /* number of the line below the bottom of - the screen */ + the window */ int w_empty_rows; /* number of ~ rows in window */ int w_filler_rows; /* number of filler rows at the end of the window */ diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 9703d8763a..9b2dbf1bf5 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -1015,9 +1015,14 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, qfline_T *qfp = xmalloc(sizeof(qfline_T)); qfline_T **lastp; // pointer to qf_last or NULL - if (bufnum != 0) + if (bufnum != 0) { + buf_T *buf = buflist_findnr(bufnum); + qfp->qf_fnum = bufnum; - else + if (buf != NULL) { + buf->b_has_qf_entry = true; + } + } else qfp->qf_fnum = qf_get_fnum(dir, fname); qfp->qf_text = vim_strsave(mesg); qfp->qf_lnum = lnum; @@ -1190,45 +1195,47 @@ void copy_loclist(win_T *from, win_T *to) to->w_llist->qf_curlist = qi->qf_curlist; /* current list */ } -/* - * get buffer number for file "dir.name" - */ +// Get buffer number for file "dir.name". +// Also sets the b_has_qf_entry flag. static int qf_get_fnum(char_u *directory, char_u *fname) { + char_u *ptr; + buf_T *buf; if (fname == NULL || *fname == NUL) /* no file name */ return 0; - { - char_u *ptr; - int fnum; #ifdef BACKSLASH_IN_FILENAME - if (directory != NULL) - slash_adjust(directory); - slash_adjust(fname); + if (directory != NULL) + slash_adjust(directory); + slash_adjust(fname); #endif - if (directory != NULL && !vim_isAbsName(fname)) { - ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); - /* - * Here we check if the file really exists. - * This should normally be true, but if make works without - * "leaving directory"-messages we might have missed a - * directory change. - */ - if (!os_path_exists(ptr)) { - xfree(ptr); - directory = qf_guess_filepath(fname); - if (directory) - ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); - else - ptr = vim_strsave(fname); - } - /* Use concatenated directory name and file name */ - fnum = buflist_add(ptr, 0); + if (directory != NULL && !vim_isAbsName(fname)) { + ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); + /* + * Here we check if the file really exists. + * This should normally be true, but if make works without + * "leaving directory"-messages we might have missed a + * directory change. + */ + if (!os_path_exists(ptr)) { xfree(ptr); - return fnum; + directory = qf_guess_filepath(fname); + if (directory) + ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); + else + ptr = vim_strsave(fname); } - return buflist_add(fname, 0); + /* Use concatenated directory name and file name */ + buf = buflist_new(ptr, NULL, (linenr_T)0, 0); + xfree(ptr); + } else { + buf = buflist_new(fname, NULL, (linenr_T)0, 0); + } + if (buf == NULL) { + return 0; } + buf->b_has_qf_entry = true; + return buf->b_fnum; } /* @@ -2104,7 +2111,11 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long qfline_T *qfp; int idx; qf_info_T *qi = &ql_info; + bool found_one = false; + if (!curbuf->b_has_qf_entry) { + return; + } if (wp != NULL) { if (wp->w_llist == NULL) return; @@ -2117,6 +2128,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long i < qi->qf_lists[idx].qf_count && qfp != NULL; ++i, qfp = qfp->qf_next) if (qfp->qf_fnum == curbuf->b_fnum) { + found_one = true; if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) { if (amount == MAXLNUM) qfp->qf_cleared = TRUE; @@ -2125,6 +2137,10 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long } else if (amount_after && qfp->qf_lnum > line2) qfp->qf_lnum += amount_after; } + + if (!found_one) { + curbuf->b_has_qf_entry = false; + } } /* diff --git a/src/nvim/version.c b/src/nvim/version.c index 17c1a85a95..bf0baa8dbf 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -556,7 +556,7 @@ static int included_patches[] = { // 1887 NA // 1886 NA // 1885 NA - // 1884, + 1884, // 1883 NA 1882, 1881, -- cgit From fbcc854d49330aff7e4511eb6321487f7b4fdae4 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:24 -0500 Subject: vim-patch:7.4.1912 Problem: No test for using setqflist() on an older quickfix list. Solution: Add a couple of tests. https://github.com/vim/vim/commit/1cee693b310e1494115a1677fac064941092e1bb --- src/nvim/testdir/test_quickfix.vim | 43 ++++++++++++++++++++++++++++++++++++++ src/nvim/version.c | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 73ee240c77..a7ca42e021 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -734,9 +734,52 @@ function Test_setqflist() call SetXlistTests('c', bnum) call SetXlistTests('l', bnum) + enew! call delete('Xtestfile') endfunction +func Test_setqflist_empty_middle() + " create three quickfix lists + vimgrep Test_ test_quickfix.vim + let testlen = len(getqflist()) + call assert_true(testlen > 0) + vimgrep empty test_quickfix.vim + call assert_true(len(getqflist()) > 0) + vimgrep matches test_quickfix.vim + let matchlen = len(getqflist()) + call assert_true(matchlen > 0) + colder + " make the middle list empty + call setqflist([], 'r') + call assert_true(len(getqflist()) == 0) + colder + call assert_equal(testlen, len(getqflist())) + cnewer + cnewer + call assert_equal(matchlen, len(getqflist())) +endfunc + +func Test_setqflist_empty_older() + " create three quickfix lists + vimgrep one test_quickfix.vim + let onelen = len(getqflist()) + call assert_true(onelen > 0) + vimgrep two test_quickfix.vim + let twolen = len(getqflist()) + call assert_true(twolen > 0) + vimgrep three test_quickfix.vim + let threelen = len(getqflist()) + call assert_true(threelen > 0) + colder 2 + " make the first list empty, check the others didn't change + call setqflist([], 'r') + call assert_true(len(getqflist()) == 0) + cnewer + call assert_equal(twolen, len(getqflist())) + cnewer + call assert_equal(threelen, len(getqflist())) +endfunc + function! XquickfixSetListWithAct(cchar) let Xolder = a:cchar . 'older' let Xnewer = a:cchar . 'newer' diff --git a/src/nvim/version.c b/src/nvim/version.c index bf0baa8dbf..4ecf7b2dd3 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -528,7 +528,7 @@ static int included_patches[] = { // 1915 NA // 1914, 1913, - // 1912, + 1912, // 1911, // 1910, 1909, -- cgit From 4ac88c4faa1abe449e69263a3e6f8655b7a71d7c Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:29 -0500 Subject: vim-patch:7.4.1937 Problem: No test for directory stack in quickfix. Solution: Add a test. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/ab47c61f46f0797308217cd3c045472cb0ec3195 --- src/nvim/testdir/test_quickfix.vim | 120 +++++++++++++++++++++++++++++++------ src/nvim/version.c | 2 +- 2 files changed, 102 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index a7ca42e021..4e9f404528 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -80,9 +80,9 @@ function XageTests(cchar) let Xnewer = a:cchar . 'newer' let Xgetexpr = a:cchar . 'getexpr' if a:cchar == 'c' - let Xgetlist = 'getqflist()' + let Xgetlist = function('getqflist') else - let Xgetlist = 'getloclist(0)' + let Xgetlist = function('getloclist', [0]) endif " Jumping to a non existent list should return error @@ -99,21 +99,21 @@ function XageTests(cchar) " Go back two lists exe Xolder - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_equal('Line2', l[0].text) " Go forward two lists exe Xnewer - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_equal('Line3', l[0].text) " Test for the optional count argument exe Xolder . ' 2' - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_equal('Line1', l[0].text) exe Xnewer . ' 2' - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_equal('Line3', l[0].text) endfunction @@ -187,9 +187,9 @@ function XfileTests(cchar) let Xgetfile = a:cchar . 'getfile' let Xaddfile = a:cchar . 'addfile' if a:cchar == 'c' - let Xgetlist = 'getqflist()' + let Xgetlist = function('getqflist') else - let Xgetlist = 'getloclist(0)' + let Xgetlist = function('getloclist', [0]) endif call writefile(['Xtestfile1:700:10:Line 700', @@ -197,7 +197,7 @@ function XfileTests(cchar) enew! exe Xfile . ' Xqftestfile1' - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') @@ -210,7 +210,7 @@ function XfileTests(cchar) call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') exe Xaddfile . ' Xqftestfile1' - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 3 && \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') @@ -219,7 +219,7 @@ function XfileTests(cchar) enew! exe Xgetfile . ' Xqftestfile1' - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') @@ -239,16 +239,16 @@ function XbufferTests(cchar) let Xgetbuffer = a:cchar . 'getbuffer' let Xaddbuffer = a:cchar . 'addbuffer' if a:cchar == 'c' - let Xgetlist = 'getqflist()' + let Xgetlist = function('getqflist') else - let Xgetlist = 'getloclist(0)' + let Xgetlist = function('getloclist', [0]) endif enew! silent! call setline(1, ['Xtestfile7:700:10:Line 700', \ 'Xtestfile8:800:15:Line 800']) exe Xbuffer . "!" - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') @@ -257,7 +257,7 @@ function XbufferTests(cchar) silent! call setline(1, ['Xtestfile9:900:55:Line 900', \ 'Xtestfile10:950:66:Line 950']) exe Xgetbuffer - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') @@ -266,11 +266,12 @@ function XbufferTests(cchar) silent! call setline(1, ['Xtestfile11:700:20:Line 700', \ 'Xtestfile12:750:25:Line 750']) exe Xaddbuffer - exe 'let l = ' . Xgetlist + let l = Xgetlist() call assert_true(len(l) == 4 && \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && \ l[3].lnum == 750 && l[3].col == 25 && l[3].text ==# 'Line 750') + enew! endfunction @@ -321,15 +322,15 @@ endfunc function XqfTitleTests(cchar) let Xgetexpr = a:cchar . 'getexpr' if a:cchar == 'c' - let Xgetlist = 'getqflist()' + let Xgetlist = function('getqflist') else - let Xgetlist = 'getloclist(0)' + let Xgetlist = function('getloclist', [0]) endif let Xopen = a:cchar . 'open' let Xclose = a:cchar . 'close' exe Xgetexpr . " ['file:1:1:message']" - exe 'let l = ' . Xgetlist + let l = Xgetlist() if a:cchar == 'c' call setqflist(l, 'r') else @@ -620,6 +621,87 @@ function! Test_efm1() call delete('Xtestfile') endfunction +" Test for quickfix directory stack support +function! s:dir_stack_tests(cchar) + let Xgetexpr = a:cchar . 'getexpr' + if a:cchar == 'c' + let Xgetlist = function('getqflist') + else + let Xgetlist = function('getloclist', [0]) + endif + + let save_efm=&efm + set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' + + let l = "Entering dir 'dir1/a'\n" . + \ 'habits2.txt:1:Nine Healthy Habits' . "\n" . + \ "Entering dir 'b'\n" . + \ 'habits3.txt:2:0 Hours of television' . "\n" . + \ 'habits2.txt:7:5 Small meals' . "\n" . + \ "Entering dir 'dir1/c'\n" . + \ 'habits4.txt:3:1 Hour of exercise' . "\n" . + \ "Leaving dir 'dir1/c'\n" . + \ "Leaving dir 'dir1/a'\n" . + \ 'habits1.txt:4:2 Liters of water' . "\n" . + \ "Entering dir 'dir2'\n" . + \ 'habits5.txt:5:3 Cups of hot green tea' . "\n" . + \ "Leaving dir 'dir2'\n" + + exe Xgetexpr . " l" + + let qf = Xgetlist() + + call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr)) + call assert_equal(1, qf[1].lnum) + call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr)) + call assert_equal(2, qf[3].lnum) + call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr)) + call assert_equal(7, qf[4].lnum) + call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr)) + call assert_equal(3, qf[6].lnum) + call assert_equal('habits1.txt', bufname(qf[9].bufnr)) + call assert_equal(4, qf[9].lnum) + call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr)) + call assert_equal(5, qf[11].lnum) + + let &efm=save_efm +endfunction + +" Tests for %D and %X errorformat options +function! Test_efm_dirstack() + " Create the directory stack and files + call mkdir('dir1') + call mkdir('dir1/a') + call mkdir('dir1/a/b') + call mkdir('dir1/c') + call mkdir('dir2') + + let lines = ["Nine Healthy Habits", + \ "0 Hours of television", + \ "1 Hour of exercise", + \ "2 Liters of water", + \ "3 Cups of hot green tea", + \ "4 Short mental breaks", + \ "5 Small meals", + \ "6 AM wake up time", + \ "7 Minutes of laughter", + \ "8 Hours of sleep (at least)", + \ "9 PM end of the day and off to bed" + \ ] + call writefile(lines, 'habits1.txt') + call writefile(lines, 'dir1/a/habits2.txt') + call writefile(lines, 'dir1/a/b/habits3.txt') + call writefile(lines, 'dir1/c/habits4.txt') + call writefile(lines, 'dir2/habits5.txt') + + call s:dir_stack_tests('c') + call s:dir_stack_tests('l') + + call delete('dir1', 'rf') + call delete('dir2', 'rf') + call delete('habits1.txt') +endfunction + function XquickfixChangedByAutocmd(cchar) let Xolder = a:cchar . 'older' let Xgetexpr = a:cchar . 'getexpr' diff --git a/src/nvim/version.c b/src/nvim/version.c index 4ecf7b2dd3..04f995ee0a 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -503,7 +503,7 @@ static int included_patches[] = { // 1940, // 1939 NA // 1938 NA - // 1937, + 1937, // 1936, // 1935 NA // 1934 NA -- cgit From 2244253c14193be94dac4b40a24dcea56e1f1b15 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:34 -0500 Subject: vim-patch:7.4.1941 Problem: Not all quickfix tests are also done with the location lists. Solution: Test more quickfix code. Use user commands instead of "exe". (Yegappan Lakshmanan) https://github.com/vim/vim/commit/3ef5bf7d459d6b8a21aaefc80f65448f5a7aa59f --- src/nvim/testdir/test_quickfix.vim | 420 +++++++++++++++++++------------------ src/nvim/version.c | 2 +- 2 files changed, 215 insertions(+), 207 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 4e9f404528..025f26059f 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -6,24 +6,67 @@ endif set encoding=utf-8 +function! s:setup_commands(cchar) + if a:cchar == 'c' + command! -nargs=* -bang Xlist clist + command! -nargs=* Xgetexpr cgetexpr + command! -nargs=* Xolder colder + command! -nargs=* Xnewer cnewer + command! -nargs=* Xopen copen + command! -nargs=* Xwindow cwindow + command! -nargs=* Xclose cclose + command! -nargs=* -bang Xfile cfile + command! -nargs=* Xgetfile cgetfile + command! -nargs=* Xaddfile caddfile + command! -nargs=* -bang Xbuffer cbuffer + command! -nargs=* Xgetbuffer cgetbuffer + command! -nargs=* Xaddbuffer caddbuffer + command! -nargs=* Xrewind crewind + command! -nargs=* -bang Xnext cnext + command! -nargs=* Xexpr cexpr + command! -nargs=* Xvimgrep vimgrep + let g:Xgetlist = function('getqflist') + let g:Xsetlist = function('setqflist') + else + command! -nargs=* -bang Xlist llist + command! -nargs=* Xgetexpr lgetexpr + command! -nargs=* Xolder lolder + command! -nargs=* Xnewer lnewer + command! -nargs=* Xopen lopen + command! -nargs=* Xwindow lwindow + command! -nargs=* Xclose lclose + command! -nargs=* -bang Xfile lfile + command! -nargs=* Xgetfile lgetfile + command! -nargs=* Xaddfile laddfile + command! -nargs=* -bang Xbuffer lbuffer + command! -nargs=* Xgetbuffer lgetbuffer + command! -nargs=* Xaddbuffer laddbuffer + command! -nargs=* Xrewind lrewind + command! -nargs=* -bang Xnext lnext + command! -nargs=* Xexpr lexpr + command! -nargs=* Xvimgrep lvimgrep + let g:Xgetlist = function('getloclist', [0]) + let g:Xsetlist = function('setloclist', [0]) + endif +endfunction + " Tests for the :clist and :llist commands function XlistTests(cchar) - let Xlist = a:cchar . 'list' - let Xgetexpr = a:cchar . 'getexpr' + call s:setup_commands(a:cchar) " With an empty list, command should return error - exe Xgetexpr . ' []' - exe 'silent! ' . Xlist + Xgetexpr [] + silent! Xlist call assert_true(v:errmsg ==# 'E42: No Errors') " Populate the list and then try - exe Xgetexpr . " ['non-error 1', 'Xtestfile1:1:3:Line1', + Xgetexpr ['non-error 1', 'Xtestfile1:1:3:Line1', \ 'non-error 2', 'Xtestfile2:2:2:Line2', - \ 'non-error 3', 'Xtestfile3:3:1:Line3']" + \ 'non-error 3', 'Xtestfile3:3:1:Line3'] " List only valid entries redir => result - exe Xlist + Xlist redir END let l = split(result, "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', @@ -32,7 +75,7 @@ function XlistTests(cchar) " List all the entries redir => result - exe Xlist . "!" + Xlist! redir END let l = split(result, "\n") call assert_equal([' 1: non-error 1', ' 2 Xtestfile1:1 col 3: Line1', @@ -41,26 +84,26 @@ function XlistTests(cchar) " List a range of errors redir => result - exe Xlist . " 3,6" + Xlist 3,6 redir END let l = split(result, "\n") call assert_equal([' 4 Xtestfile2:2 col 2: Line2', \ ' 6 Xtestfile3:3 col 1: Line3'], l) redir => result - exe Xlist . "! 3,4" + Xlist! 3,4 redir END let l = split(result, "\n") call assert_equal([' 3: non-error 2', ' 4 Xtestfile2:2 col 2: Line2'], l) redir => result - exe Xlist . " -6,-4" + Xlist -6,-4 redir END let l = split(result, "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1'], l) redir => result - exe Xlist . "! -5,-3" + Xlist! -5,-3 redir END let l = split(result, "\n") call assert_equal([' 2 Xtestfile1:1 col 3: Line1', @@ -76,44 +119,37 @@ endfunction " Note that this test assumes that a quickfix/location list is " already set by the caller. function XageTests(cchar) - let Xolder = a:cchar . 'older' - let Xnewer = a:cchar . 'newer' - let Xgetexpr = a:cchar . 'getexpr' - if a:cchar == 'c' - let Xgetlist = function('getqflist') - else - let Xgetlist = function('getloclist', [0]) - endif + call s:setup_commands(a:cchar) " Jumping to a non existent list should return error - exe 'silent! ' . Xolder . ' 99' + silent! Xolder 99 call assert_true(v:errmsg ==# 'E380: At bottom of quickfix stack') - exe 'silent! ' . Xnewer . ' 99' + silent! Xnewer 99 call assert_true(v:errmsg ==# 'E381: At top of quickfix stack') " Add three quickfix/location lists - exe Xgetexpr . " ['Xtestfile1:1:3:Line1']" - exe Xgetexpr . " ['Xtestfile2:2:2:Line2']" - exe Xgetexpr . " ['Xtestfile3:3:1:Line3']" + Xgetexpr ['Xtestfile1:1:3:Line1'] + Xgetexpr ['Xtestfile2:2:2:Line2'] + Xgetexpr ['Xtestfile3:3:1:Line3'] " Go back two lists - exe Xolder - let l = Xgetlist() + Xolder + let l = g:Xgetlist() call assert_equal('Line2', l[0].text) " Go forward two lists - exe Xnewer - let l = Xgetlist() + Xnewer + let l = g:Xgetlist() call assert_equal('Line3', l[0].text) " Test for the optional count argument - exe Xolder . ' 2' - let l = Xgetlist() + Xolder 2 + let l = g:Xgetlist() call assert_equal('Line1', l[0].text) - exe Xnewer . ' 2' - let l = Xgetlist() + Xnewer 2 + let l = g:Xgetlist() call assert_equal('Line3', l[0].text) endfunction @@ -129,49 +165,46 @@ endfunction " Tests for the :cwindow, :lwindow :cclose, :lclose, :copen and :lopen " commands function XwindowTests(cchar) - let Xwindow = a:cchar . 'window' - let Xclose = a:cchar . 'close' - let Xopen = a:cchar . 'open' - let Xgetexpr = a:cchar . 'getexpr' + call s:setup_commands(a:cchar) " Create a list with no valid entries - exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3'] " Quickfix/Location window should not open with no valid errors - exe Xwindow + Xwindow call assert_true(winnr('$') == 1) " Create a list with valid entries - exe Xgetexpr . " ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', - \ 'Xtestfile3:3:1:Line3']" + Xgetexpr ['Xtestfile1:1:3:Line1', 'Xtestfile2:2:2:Line2', + \ 'Xtestfile3:3:1:Line3'] " Open the window - exe Xwindow + Xwindow call assert_true(winnr('$') == 2 && winnr() == 2 && \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') " Close the window - exe Xclose + Xclose call assert_true(winnr('$') == 1) " Create a list with no valid entries - exe Xgetexpr . " ['non-error 1', 'non-error 2', 'non-error 3']" + Xgetexpr ['non-error 1', 'non-error 2', 'non-error 3'] " Open the window - exe Xopen . ' 5' + Xopen 5 call assert_true(winnr('$') == 2 && getline('.') ==# '|| non-error 1' \ && winheight('.') == 5) " Opening the window again, should move the cursor to that window wincmd t - exe Xopen . ' 7' + Xopen 7 call assert_true(winnr('$') == 2 && winnr() == 2 && \ winheight('.') == 7 && \ getline('.') ==# '|| non-error 1') " Calling cwindow should close the quickfix window with no valid errors - exe Xwindow + Xwindow call assert_true(winnr('$') == 1) endfunction @@ -183,21 +216,14 @@ endfunction " Tests for the :cfile, :lfile, :caddfile, :laddfile, :cgetfile and :lgetfile " commands. function XfileTests(cchar) - let Xfile = a:cchar . 'file' - let Xgetfile = a:cchar . 'getfile' - let Xaddfile = a:cchar . 'addfile' - if a:cchar == 'c' - let Xgetlist = function('getqflist') - else - let Xgetlist = function('getloclist', [0]) - endif + call s:setup_commands(a:cchar) call writefile(['Xtestfile1:700:10:Line 700', \ 'Xtestfile2:800:15:Line 800'], 'Xqftestfile1') enew! - exe Xfile . ' Xqftestfile1' - let l = Xgetlist() + Xfile Xqftestfile1 + let l = g:Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') @@ -205,12 +231,12 @@ function XfileTests(cchar) " Run cfile/lfile from a modified buffer enew! silent! put ='Quickfix' - exe 'silent! ' . Xfile . ' Xqftestfile1' + silent! Xfile Xqftestfile1 call assert_true(v:errmsg ==# 'E37: No write since last change (add ! to override)') call writefile(['Xtestfile3:900:30:Line 900'], 'Xqftestfile1') - exe Xaddfile . ' Xqftestfile1' - let l = Xgetlist() + Xaddfile Xqftestfile1 + let l = g:Xgetlist() call assert_true(len(l) == 3 && \ l[2].lnum == 900 && l[2].col == 30 && l[2].text ==# 'Line 900') @@ -218,8 +244,8 @@ function XfileTests(cchar) \ 'Xtestfile2:333:88:Line 333'], 'Xqftestfile1') enew! - exe Xgetfile . ' Xqftestfile1' - let l = Xgetlist() + Xgetfile Xqftestfile1 + let l = g:Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 222 && l[0].col == 77 && l[0].text ==# 'Line 222' && \ l[1].lnum == 333 && l[1].col == 88 && l[1].text ==# 'Line 333') @@ -235,20 +261,13 @@ endfunction " Tests for the :cbuffer, :lbuffer, :caddbuffer, :laddbuffer, :cgetbuffer and " :lgetbuffer commands. function XbufferTests(cchar) - let Xbuffer = a:cchar . 'buffer' - let Xgetbuffer = a:cchar . 'getbuffer' - let Xaddbuffer = a:cchar . 'addbuffer' - if a:cchar == 'c' - let Xgetlist = function('getqflist') - else - let Xgetlist = function('getloclist', [0]) - endif + call s:setup_commands(a:cchar) enew! silent! call setline(1, ['Xtestfile7:700:10:Line 700', \ 'Xtestfile8:800:15:Line 800']) - exe Xbuffer . "!" - let l = Xgetlist() + Xbuffer! + let l = g:Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') @@ -256,8 +275,8 @@ function XbufferTests(cchar) enew! silent! call setline(1, ['Xtestfile9:900:55:Line 900', \ 'Xtestfile10:950:66:Line 950']) - exe Xgetbuffer - let l = Xgetlist() + Xgetbuffer + let l = g:Xgetlist() call assert_true(len(l) == 2 && \ l[0].lnum == 900 && l[0].col == 55 && l[0].text ==# 'Line 900' && \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950') @@ -265,8 +284,8 @@ function XbufferTests(cchar) enew! silent! call setline(1, ['Xtestfile11:700:20:Line 700', \ 'Xtestfile12:750:25:Line 750']) - exe Xaddbuffer - let l = Xgetlist() + Xaddbuffer + let l = g:Xgetlist() call assert_true(len(l) == 4 && \ l[1].lnum == 950 && l[1].col == 66 && l[1].text ==# 'Line 950' && \ l[2].lnum == 700 && l[2].col == 20 && l[2].text ==# 'Line 700' && @@ -320,37 +339,30 @@ func Test_vimgreptitle() endfunc function XqfTitleTests(cchar) - let Xgetexpr = a:cchar . 'getexpr' - if a:cchar == 'c' - let Xgetlist = function('getqflist') - else - let Xgetlist = function('getloclist', [0]) - endif - let Xopen = a:cchar . 'open' - let Xclose = a:cchar . 'close' + call s:setup_commands(a:cchar) - exe Xgetexpr . " ['file:1:1:message']" - let l = Xgetlist() + Xgetexpr ['file:1:1:message'] + let l = g:Xgetlist() if a:cchar == 'c' call setqflist(l, 'r') else call setloclist(0, l, 'r') endif - exe Xopen + Xopen if a:cchar == 'c' let title = ':setqflist()' else let title = ':setloclist()' endif call assert_equal(title, w:quickfix_title) - exe Xclose + Xclose endfunction " Tests for quickfix window's title function Test_qf_title() - call XqfTitleTests('c') - call XqfTitleTests('l') + call XqfTitleTests('c') + call XqfTitleTests('l') endfunction " Tests for 'errorformat' @@ -623,13 +635,6 @@ endfunction " Test for quickfix directory stack support function! s:dir_stack_tests(cchar) - let Xgetexpr = a:cchar . 'getexpr' - if a:cchar == 'c' - let Xgetlist = function('getqflist') - else - let Xgetlist = function('getloclist', [0]) - endif - let save_efm=&efm set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' @@ -644,12 +649,12 @@ function! s:dir_stack_tests(cchar) \ "Leaving dir 'dir1/a'\n" . \ 'habits1.txt:4:2 Liters of water' . "\n" . \ "Entering dir 'dir2'\n" . - \ 'habits5.txt:5:3 Cups of hot green tea' . "\n" . + \ 'habits5.txt:5:3 Cups of hot green tea' . "\n" \ "Leaving dir 'dir2'\n" - exe Xgetexpr . " l" + Xgetexpr l - let qf = Xgetlist() + let qf = g:Xgetlist() call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr)) call assert_equal(1, qf[1].lnum) @@ -703,18 +708,14 @@ function! Test_efm_dirstack() endfunction function XquickfixChangedByAutocmd(cchar) - let Xolder = a:cchar . 'older' - let Xgetexpr = a:cchar . 'getexpr' - let Xrewind = a:cchar . 'rewind' + call s:setup_commands(a:cchar) if a:cchar == 'c' - let Xsetlist = function('setqflist') let ErrorNr = 'E925' function! ReadFunc() colder cgetexpr [] endfunc else - let Xsetlist = function('setloclist', [0]) let ErrorNr = 'E926' function! ReadFunc() lolder @@ -732,9 +733,9 @@ function XquickfixChangedByAutocmd(cchar) let qflist = [] for word in words call add(qflist, {'filename': 'test_changed.txt'}) - call Xsetlist(qflist, ' ') + call g:Xsetlist(qflist, ' ') endfor - exec "call assert_fails('" . Xrewind . "', '" . ErrorNr . ":')" + call assert_fails('Xrewind', ErrorNr . ':') augroup! testgroup endfunc @@ -760,51 +761,44 @@ endfunc func Test_cgetexpr_works() " this must not crash Vim cgetexpr [$x] + lgetexpr [$x] endfunc " Tests for the setqflist() and setloclist() functions function SetXlistTests(cchar, bnum) - let Xwindow = a:cchar . 'window' - let Xnext = a:cchar . 'next' - if a:cchar == 'c' - let Xsetlist = function('setqflist') - let Xgetlist = function('getqflist') - else - let Xsetlist = function('setloclist', [0]) - let Xgetlist = function('getloclist', [0]) - endif + call s:setup_commands(a:cchar) - call Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, + call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 1}, \ {'bufnr': a:bnum, 'lnum': 2}]) - let l = Xgetlist() + let l = g:Xgetlist() call assert_equal(2, len(l)) call assert_equal(2, l[1].lnum) - exe Xnext - call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a') - let l = Xgetlist() + Xnext + call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}], 'a') + let l = g:Xgetlist() call assert_equal(3, len(l)) - exe Xnext + Xnext call assert_equal(3, line('.')) " Appending entries to the list should not change the cursor position " in the quickfix window - exe Xwindow + Xwindow 1 - call Xsetlist([{'bufnr': a:bnum, 'lnum': 4}, + call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 4}, \ {'bufnr': a:bnum, 'lnum': 5}], 'a') call assert_equal(1, line('.')) close - call Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, + call g:Xsetlist([{'bufnr': a:bnum, 'lnum': 3}, \ {'bufnr': a:bnum, 'lnum': 4}, \ {'bufnr': a:bnum, 'lnum': 5}], 'r') - let l = Xgetlist() + let l = g:Xgetlist() call assert_equal(3, len(l)) call assert_equal(5, l[2].lnum) - call Xsetlist([]) - let l = Xgetlist() + call g:Xsetlist([]) + let l = g:Xgetlist() call assert_equal(0, len(l)) endfunction @@ -820,58 +814,65 @@ function Test_setqflist() call delete('Xtestfile') endfunction -func Test_setqflist_empty_middle() +function Xlist_empty_middle(cchar) + call s:setup_commands(a:cchar) + " create three quickfix lists - vimgrep Test_ test_quickfix.vim - let testlen = len(getqflist()) + Xvimgrep Test_ test_quickfix.vim + let testlen = len(g:Xgetlist()) call assert_true(testlen > 0) - vimgrep empty test_quickfix.vim - call assert_true(len(getqflist()) > 0) - vimgrep matches test_quickfix.vim - let matchlen = len(getqflist()) + Xvimgrep empty test_quickfix.vim + call assert_true(len(g:Xgetlist()) > 0) + Xvimgrep matches test_quickfix.vim + let matchlen = len(g:Xgetlist()) call assert_true(matchlen > 0) - colder + Xolder " make the middle list empty - call setqflist([], 'r') - call assert_true(len(getqflist()) == 0) - colder - call assert_equal(testlen, len(getqflist())) - cnewer - cnewer - call assert_equal(matchlen, len(getqflist())) + call g:Xsetlist([], 'r') + call assert_true(len(g:Xgetlist()) == 0) + Xolder + call assert_equal(testlen, len(g:Xgetlist())) + Xnewer + Xnewer + call assert_equal(matchlen, len(g:Xgetlist())) endfunc -func Test_setqflist_empty_older() +function Test_setqflist_empty_middle() + call Xlist_empty_middle('c') + call Xlist_empty_middle('l') +endfunction + +function Xlist_empty_older(cchar) + call s:setup_commands(a:cchar) + " create three quickfix lists - vimgrep one test_quickfix.vim - let onelen = len(getqflist()) + Xvimgrep one test_quickfix.vim + let onelen = len(g:Xgetlist()) call assert_true(onelen > 0) - vimgrep two test_quickfix.vim - let twolen = len(getqflist()) + Xvimgrep two test_quickfix.vim + let twolen = len(g:Xgetlist()) call assert_true(twolen > 0) - vimgrep three test_quickfix.vim - let threelen = len(getqflist()) + Xvimgrep three test_quickfix.vim + let threelen = len(g:Xgetlist()) call assert_true(threelen > 0) - colder 2 + Xolder 2 " make the first list empty, check the others didn't change - call setqflist([], 'r') - call assert_true(len(getqflist()) == 0) - cnewer - call assert_equal(twolen, len(getqflist())) - cnewer - call assert_equal(threelen, len(getqflist())) -endfunc + call g:Xsetlist([], 'r') + call assert_true(len(g:Xgetlist()) == 0) + Xnewer + call assert_equal(twolen, len(g:Xgetlist())) + Xnewer + call assert_equal(threelen, len(g:Xgetlist())) +endfunction + +function Test_setqflist_empty_older() + call Xlist_empty_older('c') + call Xlist_empty_older('l') +endfunction function! XquickfixSetListWithAct(cchar) - let Xolder = a:cchar . 'older' - let Xnewer = a:cchar . 'newer' - if a:cchar == 'c' - let Xsetlist = function('setqflist') - let Xgetlist = function('getqflist') - else - let Xsetlist = function('setloclist', [0]) - let Xgetlist = function('getloclist', [0]) - endif + call s:setup_commands(a:cchar) + let list1 = [{'filename': 'fnameA', 'text': 'A'}, \ {'filename': 'fnameB', 'text': 'B'}] let list2 = [{'filename': 'fnameC', 'text': 'C'}, @@ -880,42 +881,42 @@ function! XquickfixSetListWithAct(cchar) " {action} is unspecified. Same as specifing ' '. new | only - exec "silent! " . Xnewer . "99" - call Xsetlist(list1) - call Xsetlist(list2) - let li = Xgetlist() + silent! Xnewer 99 + call g:Xsetlist(list1) + call g:Xsetlist(list2) + let li = g:Xgetlist() call assert_equal(3, len(li)) call assert_equal('C', li[0]['text']) call assert_equal('D', li[1]['text']) call assert_equal('E', li[2]['text']) - exec "silent! " . Xolder - let li = Xgetlist() + silent! Xolder + let li = g:Xgetlist() call assert_equal(2, len(li)) call assert_equal('A', li[0]['text']) call assert_equal('B', li[1]['text']) " {action} is specified ' '. new | only - exec "silent! " . Xnewer . "99" - call Xsetlist(list1) - call Xsetlist(list2, ' ') - let li = Xgetlist() + silent! Xnewer 99 + call g:Xsetlist(list1) + call g:Xsetlist(list2, ' ') + let li = g:Xgetlist() call assert_equal(3, len(li)) call assert_equal('C', li[0]['text']) call assert_equal('D', li[1]['text']) call assert_equal('E', li[2]['text']) - exec "silent! " . Xolder - let li = Xgetlist() + silent! Xolder + let li = g:Xgetlist() call assert_equal(2, len(li)) call assert_equal('A', li[0]['text']) call assert_equal('B', li[1]['text']) " {action} is specified 'a'. new | only - exec "silent! " . Xnewer . "99" - call Xsetlist(list1) - call Xsetlist(list2, 'a') - let li = Xgetlist() + silent! Xnewer 99 + call g:Xsetlist(list1) + call g:Xsetlist(list2, 'a') + let li = g:Xgetlist() call assert_equal(5, len(li)) call assert_equal('A', li[0]['text']) call assert_equal('B', li[1]['text']) @@ -925,10 +926,10 @@ function! XquickfixSetListWithAct(cchar) " {action} is specified 'r'. new | only - exec "silent! " . Xnewer . "99" - call Xsetlist(list1) - call Xsetlist(list2, 'r') - let li = Xgetlist() + silent! Xnewer 99 + call g:Xsetlist(list1) + call g:Xsetlist(list2, 'r') + let li = g:Xgetlist() call assert_equal(3, len(li)) call assert_equal('C', li[0]['text']) call assert_equal('D', li[1]['text']) @@ -936,11 +937,11 @@ function! XquickfixSetListWithAct(cchar) " Test for wrong value. new | only - call assert_fails("call Xsetlist(0)", 'E714:') - call assert_fails("call Xsetlist(list1, '')", 'E927:') - call assert_fails("call Xsetlist(list1, 'aa')", 'E927:') - call assert_fails("call Xsetlist(list1, ' a')", 'E927:') - call assert_fails("call Xsetlist(list1, 0)", 'E928:') + call assert_fails("call g:Xsetlist(0)", 'E714:') + call assert_fails("call g:Xsetlist(list1, '')", 'E927:') + call assert_fails("call g:Xsetlist(list1, 'aa')", 'E927:') + call assert_fails("call g:Xsetlist(list1, ' a')", 'E927:') + call assert_fails("call g:Xsetlist(list1, 0)", 'E928:') endfunc function Test_quickfix_set_list_with_act() @@ -948,8 +949,8 @@ function Test_quickfix_set_list_with_act() call XquickfixSetListWithAct('l') endfunction -func XLongLinesTests() - let l = getqflist() +function XLongLinesTests(cchar) + let l = g:Xgetlist() call assert_equal(3, len(l)) call assert_equal(1, l[0].lnum) @@ -962,25 +963,32 @@ func XLongLinesTests() call assert_equal(1, l[2].col) call assert_equal(10, len(l[2].text)) - call setqflist([], 'r') -endfunc + call g:Xsetlist([], 'r') +endfunction + +function s:long_lines_tests(cchar) + call s:setup_commands(a:cchar) -func Test_long_lines() let testfile = 'samples/quickfix.txt' " file - exe 'cgetfile' testfile - call XLongLinesTests() + exe 'Xgetfile' testfile + call XLongLinesTests(a:cchar) " list - cexpr readfile(testfile) - call XLongLinesTests() + Xexpr readfile(testfile) + call XLongLinesTests(a:cchar) " string - cexpr join(readfile(testfile), "\n") - call XLongLinesTests() + Xexpr join(readfile(testfile), "\n") + call XLongLinesTests(a:cchar) " buffer - e testfile - exe 'cbuffer' bufnr('%') -endfunc + exe 'edit' testfile + exe 'Xbuffer' bufnr('%') +endfunction + +function Test_long_lines() + call s:long_lines_tests('c') + call s:long_lines_tests('l') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index 04f995ee0a..f9385dcc93 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -499,7 +499,7 @@ static int included_patches[] = { // 1944 NA // 1943 NA // 1942 NA - // 1941, + 1941, // 1940, // 1939 NA // 1938 NA -- cgit From 63d4ac7b2515072bffabe1d69fd6eb62aeb860f4 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:38 -0500 Subject: vim-patch:7.4.1949 Problem: Minor problems with the quickfix code. Solution: Fix the problems. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/38df43bd13a2498cc96b3ddd9a20dd75126bd171 --- src/nvim/quickfix.c | 11 +++++------ src/nvim/testdir/test_quickfix.vim | 2 ++ src/nvim/version.c | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 9b2dbf1bf5..16d336c41f 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -541,11 +541,12 @@ qf_init_ext ( if (buflnum > lnumlast) break; p_buf = ml_get_buf(buf, buflnum++, false); - linelen = STRLEN(p_buf); - if (linelen > IOSIZE - 2) { + len = STRLEN(p_buf); + if (len > IOSIZE - 2) { linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); } else { linebuf = IObuff; + linelen = len; } STRLCPY(linebuf, p_buf, linelen + 1); } @@ -1238,10 +1239,8 @@ static int qf_get_fnum(char_u *directory, char_u *fname) return buf->b_fnum; } -/* - * push dirbuf onto the directory stack and return pointer to actual dir or - * NULL on error - */ +// Push dirbuf onto the directory stack and return pointer to actual dir or +// NULL on error. static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr) { struct dir_stack_T *ds_ptr; diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 025f26059f..bfdce9cd38 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -635,6 +635,8 @@ endfunction " Test for quickfix directory stack support function! s:dir_stack_tests(cchar) + call s:setup_commands(a:cchar) + let save_efm=&efm set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' diff --git a/src/nvim/version.c b/src/nvim/version.c index f9385dcc93..480e6723f3 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -491,7 +491,7 @@ static int included_patches[] = { 1952, // 1951 NA // 1950, - // 1949, + 1949, // 1948, // 1947 NA // 1946 NA -- cgit From d091faf2849dcd4ece60bffaaf8db61ae4f2fe5e Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:43 -0500 Subject: vim-patch:7.4.1950 Problem: Quickfix long lines test not executed for buffer. Solution: Call the function to test long lines. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/f50df3925b7c909d1cda4c868d8c7ba38189aabe --- src/nvim/testdir/test_quickfix.vim | 1 + src/nvim/version.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index bfdce9cd38..6ae60b1641 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -988,6 +988,7 @@ function s:long_lines_tests(cchar) " buffer exe 'edit' testfile exe 'Xbuffer' bufnr('%') + call XLongLinesTests(a:cchar) endfunction function Test_long_lines() diff --git a/src/nvim/version.c b/src/nvim/version.c index 480e6723f3..b75aae3226 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -490,7 +490,7 @@ static int included_patches[] = { // 1953, 1952, // 1951 NA - // 1950, + 1950, 1949, // 1948, // 1947 NA -- cgit From 8f0bf810ff9257b55afc2ee95c2e0f81bdec79bd Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:47 -0500 Subject: vim-patch:7.4.1953 Problem: Not all parts of the quickfix code are tested. Solution: Add more tests. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/049cba9e9760152b5695399a991dc61cea9ba143 --- src/nvim/testdir/samples/quickfix.txt | 5 +- src/nvim/testdir/test_quickfix.vim | 239 +++++++++++++++++++++++++++++++++- src/nvim/version.c | 2 +- 3 files changed, 236 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/samples/quickfix.txt b/src/nvim/testdir/samples/quickfix.txt index 38c8f49149..2de3835473 100644 --- a/src/nvim/testdir/samples/quickfix.txt +++ b/src/nvim/testdir/samples/quickfix.txt @@ -1,3 +1,4 @@ -samples/quickfix.txt:1:1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +samples/quickfix.txt:1:1:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa samples/quickfix.txt:2:1:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb -samples/quickfix.txt:3:1:cccccccccc +samples/quickfix.txt:3:1:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc +samples/quickfix.txt:4:1:dddddddddd diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 6ae60b1641..3bd7a8c4fb 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -25,6 +25,9 @@ function! s:setup_commands(cchar) command! -nargs=* -bang Xnext cnext command! -nargs=* Xexpr cexpr command! -nargs=* Xvimgrep vimgrep + command! -nargs=* Xgrep grep + command! -nargs=* Xgrepadd grepadd + command! -nargs=* Xhelpgrep helpgrep let g:Xgetlist = function('getqflist') let g:Xsetlist = function('setqflist') else @@ -45,6 +48,9 @@ function! s:setup_commands(cchar) command! -nargs=* -bang Xnext lnext command! -nargs=* Xexpr lexpr command! -nargs=* Xvimgrep lvimgrep + command! -nargs=* Xgrep lgrep + command! -nargs=* Xgrepadd lgrepadd + command! -nargs=* Xhelpgrep lhelpgrep let g:Xgetlist = function('getloclist', [0]) let g:Xsetlist = function('setloclist', [0]) endif @@ -228,6 +234,9 @@ function XfileTests(cchar) \ l[0].lnum == 700 && l[0].col == 10 && l[0].text ==# 'Line 700' && \ l[1].lnum == 800 && l[1].col == 15 && l[1].text ==# 'Line 800') + " Test with a non existent file + call assert_fails('Xfile non_existent_file', 'E40') + " Run cfile/lfile from a modified buffer enew! silent! put ='Quickfix' @@ -299,11 +308,23 @@ function Test_cbuffer() call XbufferTests('l') endfunction -function Test_helpgrep() - helpgrep quickfix - copen +function! s:test_xhelpgrep(cchar) + call s:setup_commands(a:cchar) + Xhelpgrep quickfix + Xopen + if a:cchar == 'c' + let title_text = ':helpgrep quickfix' + else + let title_text = ':lhelpgrep quickfix' + endif + call assert_true(w:quickfix_title =~ title_text, w:quickfix_title) " This wipes out the buffer, make sure that doesn't cause trouble. - cclose + Xclose +endfunction + +function Test_helpgrep() + call s:test_xhelpgrep('c') + call s:test_xhelpgrep('l') endfunc func Test_errortitle() @@ -709,6 +730,47 @@ function! Test_efm_dirstack() call delete('habits1.txt') endfunction +" TODO: +" Add tests for the following formats in 'errorformat' +" %n %t %r %+ %- %O +function! Test_efm2() + let save_efm = &efm + + " Test for invalid efm + set efm=%L%M%N + call assert_fails('cexpr "abc.txt:1:Hello world"', 'E376:') + call assert_fails('lexpr "abc.txt:1:Hello world"', 'E376:') + + " Test for %s format in efm + set efm=%f:%s + cexpr 'Xtestfile:Line search text' + + let l = getqflist() + call assert_equal(l[0].pattern, '^\VLine search text\$') + call assert_equal(l[0].lnum, 0) + + let lines=["[Xtestfile1]", + \ "(1,17) error: ';' missing", + \ "(21,2) warning: variable 'z' not defined", + \ "(67,3) error: end of file found before string ended", + \ "", + \ "[Xtestfile2]", + \ "", + \ "[Xtestfile3]", + \ "NEW compiler v1.1", + \ "(2,2) warning: variable 'x' not defined", + \ "(67,3) warning: 's' already defined" + \] + set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q + cgetexpr lines + let l = getqflist() + call assert_equal(9, len(l)) + call assert_equal(21, l[2].lnum) + call assert_equal(2, l[2].col) + + let &efm = save_efm +endfunction + function XquickfixChangedByAutocmd(cchar) call s:setup_commands(a:cchar) if a:cchar == 'c' @@ -954,16 +1016,19 @@ endfunction function XLongLinesTests(cchar) let l = g:Xgetlist() - call assert_equal(3, len(l)) + call assert_equal(4, len(l)) call assert_equal(1, l[0].lnum) call assert_equal(1, l[0].col) - call assert_equal(4070, len(l[0].text)) + call assert_equal(1975, len(l[0].text)) call assert_equal(2, l[1].lnum) call assert_equal(1, l[1].col) call assert_equal(4070, len(l[1].text)) call assert_equal(3, l[2].lnum) call assert_equal(1, l[2].col) - call assert_equal(10, len(l[2].text)) + call assert_equal(4070, len(l[2].text)) + call assert_equal(4, l[3].lnum) + call assert_equal(1, l[3].col) + call assert_equal(10, len(l[3].text)) call g:Xsetlist([], 'r') endfunction @@ -995,3 +1060,163 @@ function Test_long_lines() call s:long_lines_tests('c') call s:long_lines_tests('l') endfunction + +function! s:create_test_file(filename) + let l = [] + for i in range(1, 20) + call add(l, 'Line' . i) + endfor + call writefile(l, a:filename) +endfunction + +function! Test_switchbuf() + call s:create_test_file('Xqftestfile1') + call s:create_test_file('Xqftestfile2') + call s:create_test_file('Xqftestfile3') + + new | only + edit Xqftestfile1 + let file1_winid = win_getid() + new Xqftestfile2 + let file2_winid = win_getid() + cgetexpr ['Xqftestfile1:5:Line5', + \ 'Xqftestfile1:6:Line6', + \ 'Xqftestfile2:10:Line10', + \ 'Xqftestfile2:11:Line11', + \ 'Xqftestfile3:15:Line15', + \ 'Xqftestfile3:16:Line16'] + + new + let winid = win_getid() + cfirst | cnext + call assert_equal(winid, win_getid()) + cnext | cnext + call assert_equal(winid, win_getid()) + cnext | cnext + call assert_equal(winid, win_getid()) + enew + + set switchbuf=useopen + cfirst | cnext + call assert_equal(file1_winid, win_getid()) + cnext | cnext + call assert_equal(file2_winid, win_getid()) + cnext | cnext + call assert_equal(file2_winid, win_getid()) + + enew | only + set switchbuf=usetab + tabedit Xqftestfile1 + tabedit Xqftestfile2 + tabfirst + cfirst | cnext + call assert_equal(2, tabpagenr()) + cnext | cnext + call assert_equal(3, tabpagenr()) + cnext | cnext + call assert_equal(3, tabpagenr()) + tabfirst | tabonly | enew + + set switchbuf=split + cfirst | cnext + call assert_equal(1, winnr('$')) + cnext | cnext + call assert_equal(2, winnr('$')) + cnext | cnext + call assert_equal(3, winnr('$')) + enew | only + + set switchbuf=newtab + cfirst | cnext + call assert_equal(1, tabpagenr('$')) + cnext | cnext + call assert_equal(2, tabpagenr('$')) + cnext | cnext + call assert_equal(3, tabpagenr('$')) + tabfirst | enew | tabonly | only + + set switchbuf= + edit Xqftestfile1 + let file1_winid = win_getid() + new Xqftestfile2 + let file2_winid = win_getid() + copen + exe "normal 1G\" + call assert_equal(file1_winid, win_getid()) + copen + exe "normal 3G\" + call assert_equal(file2_winid, win_getid()) + copen | only + exe "normal 5G\" + call assert_equal(2, winnr('$')) + call assert_equal(1, bufwinnr('Xqftestfile3')) + + enew | only + + call delete('Xqftestfile1') + call delete('Xqftestfile2') + call delete('Xqftestfile3') +endfunction + +function! Xadjust_qflnum(cchar) + call s:setup_commands(a:cchar) + + enew | only + + call s:create_test_file('Xqftestfile') + edit Xqftestfile + + Xgetexpr ['Xqftestfile:5:Line5', + \ 'Xqftestfile:10:Line10', + \ 'Xqftestfile:15:Line15', + \ 'Xqftestfile:20:Line20'] + + 6,14delete + call append(6, ['Buffer', 'Window']) + + let l = g:Xgetlist() + + call assert_equal(5, l[0].lnum) + call assert_equal(6, l[2].lnum) + call assert_equal(13, l[3].lnum) + + enew! + call delete('Xqftestfile') +endfunction + +function! Test_adjust_lnum() + call Xadjust_qflnum('c') + call Xadjust_qflnum('l') +endfunction + +" Tests for the :grep/:lgrep and :grepadd/:lgrepadd commands +function! s:test_xgrep(cchar) + call s:setup_commands(a:cchar) + + " The following lines are used for the grep test. Don't remove. + " Grep_Test_Text: Match 1 + " Grep_Test_Text: Match 2 + " GrepAdd_Test_Text: Match 1 + " GrepAdd_Test_Text: Match 2 + enew! | only + set makeef&vim + silent Xgrep Grep_Test_Text: test_quickfix.vim + call assert_true(len(g:Xgetlist()) == 3) + Xopen + call assert_true(w:quickfix_title =~ '^:grep') + Xclose + enew + set makeef=Temp_File_## + silent Xgrepadd GrepAdd_Test_Text: test_quickfix.vim + call assert_true(len(g:Xgetlist()) == 6) +endfunction + +function! Test_grep() + if !has('unix') + " The grepprg may not be set on non-Unix systems + return + endif + + call s:test_xgrep('c') + call s:test_xgrep('l') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index b75aae3226..c4fdcd61f9 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -487,7 +487,7 @@ static int included_patches[] = { 1956, // 1955, // 1954, - // 1953, + 1953, 1952, // 1951 NA 1950, -- cgit From 82f54c0a5eea91dcfd7a509588b4ac37f7e55b57 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:52 -0500 Subject: vim-patch:7.4.1964 Problem: The quickfix init function is too big. Solution: Factor out parsing 'errorformat' to a separate function. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/688e3d1fd9b9129a5ba0e0d599ccfe6f4443daf3 --- src/nvim/quickfix.c | 430 +++++++++++++++++++++++++++++----------------------- src/nvim/version.c | 2 +- 2 files changed, 240 insertions(+), 192 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 16d336c41f..1499c3e12f 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -188,6 +188,243 @@ static char_u *qf_grow_linebuf(char_u **growbuf, size_t *growbufsiz, return *growbuf; } +static struct fmtpattern +{ + char_u convchar; + char *pattern; +} fmt_pat[FMT_PATTERNS] = +{ + {'f', ".\\+"}, // only used when at end + {'n', "\\d\\+"}, + {'l', "\\d\\+"}, + {'c', "\\d\\+"}, + {'t', "."}, + {'m', ".\\+"}, + {'r', ".*"}, + {'p', "[- .]*"}, + {'v', "\\d\\+"}, + {'s', ".\\+"} +}; + +// Converts a 'errorformat' string to regular expression pattern +static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, + char_u *regpat, char_u *errmsg) +{ + // Build regexp pattern from current 'errorformat' option + char_u *ptr = regpat; + *ptr++ = '^'; + int round = 0; + for (char_u *efmp = efm; efmp < efm + len; efmp++) { + if (*efmp == '%') { + efmp++; + int idx; + for (idx = 0; idx < FMT_PATTERNS; idx++) { + if (fmt_pat[idx].convchar == *efmp) { + break; + } + } + if (idx < FMT_PATTERNS) { + if (fmt_ptr->addr[idx]) { + sprintf((char *)errmsg, + _("E372: Too many %%%c in format string"), *efmp); + EMSG(errmsg); + return -1; + } + if ((idx + && idx < 6 + && vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL) + || (idx == 6 + && vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL)) { + sprintf((char *)errmsg, + _("E373: Unexpected %%%c in format string"), *efmp); + EMSG(errmsg); + return -1; + } + round++; + fmt_ptr->addr[idx] = (char_u)round; + *ptr++ = '\\'; + *ptr++ = '('; +#ifdef BACKSLASH_IN_FILENAME + if (*efmp == 'f') { + // Also match "c:" in the file name, even when + // checking for a colon next: "%f:". + // "\%(\a:\)\=" + STRCPY(ptr, "\\%(\\a:\\)\\="); + ptr += 10; + } +#endif + if (*efmp == 'f' && efmp[1] != NUL) { + if (efmp[1] != '\\' && efmp[1] != '%') { + // A file name may contain spaces, but this isn't + // in "\f". For "%f:%l:%m" there may be a ":" in + // the file name. Use ".\{-1,}x" instead (x is + // the next character), the requirement that :999: + // follows should work. + STRCPY(ptr, ".\\{-1,}"); + ptr += 7; + } else { + // File name followed by '\\' or '%': include as + // many file name chars as possible. + STRCPY(ptr, "\\f\\+"); + ptr += 4; + } + } else { + char_u *srcptr = (char_u *)fmt_pat[idx].pattern; + while ((*ptr = *srcptr++) != NUL) { + ptr++; + } + } + *ptr++ = '\\'; + *ptr++ = ')'; + } else if (*efmp == '*') { + if (*++efmp == '[' || *efmp == '\\') { + if ((*ptr++ = *efmp) == '[') { // %*[^a-z0-9] etc. + if (efmp[1] == '^') { + *ptr++ = *++efmp; + } + if (efmp < efm + len) { + efmp++; + *ptr++ = *efmp; // could be ']' + while (efmp < efm + len) { + efmp++; + if ((*ptr++ = *efmp) == ']') { + break; + } + } + if (efmp == efm + len) { + EMSG(_("E374: Missing ] in format string")); + return -1; + } + } + } else if (efmp < efm + len) { // %*\D, %*\s etc. + efmp++; + *ptr++ = *efmp; + } + *ptr++ = '\\'; + *ptr++ = '+'; + } else { + // TODO: scanf()-like: %*ud, %*3c, %*f, ... ? + sprintf((char *)errmsg, + _("E375: Unsupported %%%c in format string"), *efmp); + EMSG(errmsg); + return -1; + } + } else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) { + *ptr++ = *efmp; // regexp magic characters + } else if (*efmp == '#') { + *ptr++ = '*'; + } else if (*efmp == '>') { + fmt_ptr->conthere = true; + } else if (efmp == efm + 1) { // analyse prefix + if (vim_strchr((char_u *)"+-", *efmp) != NULL) { + fmt_ptr->flags = *efmp++; + } + if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) { + fmt_ptr->prefix = *efmp; + } else { + sprintf((char *)errmsg, + _("E376: Invalid %%%c in format string prefix"), *efmp); + EMSG(errmsg); + return -1; + } + } else { + sprintf((char *)errmsg, + _("E377: Invalid %%%c in format string"), *efmp); + EMSG(errmsg); + return -1; + } + } else { // copy normal character + if (*efmp == '\\' && efmp + 1 < efm + len) { + efmp++; + } else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL) { + *ptr++ = '\\'; // escape regexp atoms + } + if (*efmp) { + *ptr++ = *efmp; + } + } + } + *ptr++ = '$'; + *ptr = NUL; + + return 0; +} + +static void free_efm_list(efm_T **efm_first) +{ + for (efm_T *efm_ptr = *efm_first; efm_ptr != NULL; efm_ptr = *efm_first) { + *efm_first = efm_ptr->next; + vim_regfree(efm_ptr->prog); + xfree(efm_ptr); + } +} + +// Parse 'errorformat' option +static efm_T * parse_efm_option(char_u *efm) +{ + efm_T *fmt_ptr = NULL; + efm_T *fmt_first = NULL; + efm_T *fmt_last = NULL; + int len; + + size_t errmsglen = CMDBUFFSIZE + 1; + char_u *errmsg = xmalloc(errmsglen); + + // Get some space to modify the format string into. + size_t i = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2); + for (int round = FMT_PATTERNS - 1; round >= 0; ) { + i += STRLEN(fmt_pat[round--].pattern); + } +#ifdef COLON_IN_FILENAME + i += 12; /* "%f" can become twelve chars longer */ +#else + i += 2; /* "%f" can become two chars longer */ +#endif + char_u *fmtstr = xmalloc(i); + + while (efm[0] != NUL) { + // Allocate a new eformat structure and put it at the end of the list + fmt_ptr = (efm_T *)xcalloc(1, sizeof(efm_T)); + if (fmt_first == NULL) { // first one + fmt_first = fmt_ptr; + } else { + fmt_last->next = fmt_ptr; + } + fmt_last = fmt_ptr; + + // Isolate one part in the 'errorformat' option + for (len = 0; efm[len] != NUL && efm[len] != ','; len++) { + if (efm[len] == '\\' && efm[len + 1] != NUL) { + len++; + } + } + + if (efm_to_regpat(efm, len, fmt_ptr, fmtstr, errmsg) == -1) { + goto parse_efm_error; + } + if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) { + goto parse_efm_error; + } + // Advance to next part + efm = skip_to_option_part(efm + len); // skip comma and spaces + } + + if (fmt_first == NULL) { // nothing found + EMSG(_("E378: 'errorformat' contains no pattern")); + } + + goto parse_efm_end; + +parse_efm_error: + free_efm_list(&fmt_first); + +parse_efm_end: + xfree(fmtstr); + xfree(errmsg); + + return fmt_first; +} + // Read the errorfile "efile" into memory, line by line, building the error // list. // Alternative: when "efile" is NULL read errors from buffer "buf". @@ -213,7 +450,6 @@ qf_init_ext ( char_u *errmsg; size_t errmsglen; char_u *pattern; - char_u *fmtstr = NULL; char_u *growbuf = NULL; size_t growbuflen; size_t growbufsiz = 0; @@ -228,17 +464,13 @@ qf_init_ext ( int enr = 0; FILE *fd = NULL; qfline_T *old_last = NULL; - char_u *efmp; efm_T *fmt_first = NULL; - efm_T *fmt_last = NULL; efm_T *fmt_ptr; efm_T *fmt_start = NULL; char_u *efm; char_u *ptr; - char_u *srcptr; size_t len; int i; - int round; int idx = 0; bool multiline = false; bool multiignore = false; @@ -252,22 +484,6 @@ qf_init_ext ( listitem_T *p_li = NULL; struct dir_stack_T *file_stack = NULL; regmatch_T regmatch; - static struct fmtpattern { - char_u convchar; - char *pattern; - } fmt_pat[FMT_PATTERNS] = - { - {'f', ".\\+"}, /* only used when at end */ - {'n', "\\d\\+"}, - {'l', "\\d\\+"}, - {'c', "\\d\\+"}, - {'t', "."}, - {'m', ".\\+"}, - {'r', ".*"}, - {'p', "[- .]*"}, - {'v', "\\d\\+"}, - {'s', ".\\+"} - }; namebuf = xmalloc(CMDBUFFSIZE + 1); errmsglen = CMDBUFFSIZE + 1; @@ -296,172 +512,9 @@ qf_init_ext ( efm = buf->b_p_efm; else efm = errorformat; - /* - * Get some space to modify the format string into. - */ - size_t fmtstr_size = 3 * FMT_PATTERNS + 4 * STRLEN(efm); - for (round = FMT_PATTERNS; round > 0; ) { - fmtstr_size += STRLEN(fmt_pat[--round].pattern); - } -#ifdef COLON_IN_FILENAME - fmtstr_size += 12; // "%f" can become twelve chars longer -#else - fmtstr_size += 2; // "%f" can become two chars longer -#endif - fmtstr = xmalloc(fmtstr_size); - while (efm[0] != NUL) { - /* - * Allocate a new eformat structure and put it at the end of the list - */ - fmt_ptr = xcalloc(1, sizeof(efm_T)); - if (fmt_first == NULL) /* first one */ - fmt_first = fmt_ptr; - else - fmt_last->next = fmt_ptr; - fmt_last = fmt_ptr; - - /* - * Isolate one part in the 'errorformat' option - */ - for (len = 0; efm[len] != NUL && efm[len] != ','; ++len) - if (efm[len] == '\\' && efm[len + 1] != NUL) - ++len; - - /* - * Build regexp pattern from current 'errorformat' option - */ - ptr = fmtstr; - *ptr++ = '^'; - round = 0; - for (efmp = efm; efmp < efm + len; ++efmp) { - if (*efmp == '%') { - ++efmp; - for (idx = 0; idx < FMT_PATTERNS; ++idx) - if (fmt_pat[idx].convchar == *efmp) - break; - if (idx < FMT_PATTERNS) { - if (fmt_ptr->addr[idx]) { - sprintf((char *)errmsg, - _("E372: Too many %%%c in format string"), *efmp); - EMSG(errmsg); - goto error2; - } - if ((idx - && idx < 6 - && vim_strchr((char_u *)"DXOPQ", - fmt_ptr->prefix) != NULL) - || (idx == 6 - && vim_strchr((char_u *)"OPQ", - fmt_ptr->prefix) == NULL)) { - sprintf((char *)errmsg, - _("E373: Unexpected %%%c in format string"), *efmp); - EMSG(errmsg); - goto error2; - } - fmt_ptr->addr[idx] = (char_u)++ round; - *ptr++ = '\\'; - *ptr++ = '('; -#ifdef BACKSLASH_IN_FILENAME - if (*efmp == 'f') { - /* Also match "c:" in the file name, even when - * checking for a colon next: "%f:". - * "\%(\a:\)\=" */ - STRCPY(ptr, "\\%(\\a:\\)\\="); - ptr += 10; - } -#endif - if (*efmp == 'f' && efmp[1] != NUL) { - if (efmp[1] != '\\' && efmp[1] != '%') { - /* A file name may contain spaces, but this isn't - * in "\f". For "%f:%l:%m" there may be a ":" in - * the file name. Use ".\{-1,}x" instead (x is - * the next character), the requirement that :999: - * follows should work. */ - STRCPY(ptr, ".\\{-1,}"); - ptr += 7; - } else { - /* File name followed by '\\' or '%': include as - * many file name chars as possible. */ - STRCPY(ptr, "\\f\\+"); - ptr += 4; - } - } else { - srcptr = (char_u *)fmt_pat[idx].pattern; - while ((*ptr = *srcptr++) != NUL) - ++ptr; - } - *ptr++ = '\\'; - *ptr++ = ')'; - } else if (*efmp == '*') { - if (*++efmp == '[' || *efmp == '\\') { - if ((*ptr++ = *efmp) == '[') { /* %*[^a-z0-9] etc. */ - if (efmp[1] == '^') - *ptr++ = *++efmp; - if (efmp < efm + len) { - *ptr++ = *++efmp; /* could be ']' */ - while (efmp < efm + len - && (*ptr++ = *++efmp) != ']') - /* skip */; - if (efmp == efm + len) { - EMSG(_("E374: Missing ] in format string")); - goto error2; - } - } - } else if (efmp < efm + len) /* %*\D, %*\s etc. */ - *ptr++ = *++efmp; - *ptr++ = '\\'; - *ptr++ = '+'; - } else { - /* TODO: scanf()-like: %*ud, %*3c, %*f, ... ? */ - sprintf((char *)errmsg, - _("E375: Unsupported %%%c in format string"), *efmp); - EMSG(errmsg); - goto error2; - } - } else if (vim_strchr((char_u *)"%\\.^$~[", *efmp) != NULL) - *ptr++ = *efmp; /* regexp magic characters */ - else if (*efmp == '#') - *ptr++ = '*'; - else if (*efmp == '>') - fmt_ptr->conthere = TRUE; - else if (efmp == efm + 1) { /* analyse prefix */ - if (vim_strchr((char_u *)"+-", *efmp) != NULL) - fmt_ptr->flags = *efmp++; - if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) - fmt_ptr->prefix = *efmp; - else { - sprintf((char *)errmsg, - _("E376: Invalid %%%c in format string prefix"), *efmp); - EMSG(errmsg); - goto error2; - } - } else { - sprintf((char *)errmsg, - _("E377: Invalid %%%c in format string"), *efmp); - EMSG(errmsg); - goto error2; - } - } else { /* copy normal character */ - if (*efmp == '\\' && efmp + 1 < efm + len) - ++efmp; - else if (vim_strchr((char_u *)".*^$~[", *efmp) != NULL) - *ptr++ = '\\'; /* escape regexp atoms */ - if (*efmp) - *ptr++ = *efmp; - } - } - *ptr++ = '$'; - *ptr = NUL; - if ((fmt_ptr->prog = vim_regcomp(fmtstr, RE_MAGIC + RE_STRING)) == NULL) - goto error2; - /* - * Advance to next part - */ - efm = skip_to_option_part(efm + len); /* skip comma and spaces */ - } + fmt_first = parse_efm_option(efm); if (fmt_first == NULL) { /* nothing found */ - EMSG(_("E378: 'errorformat' contains no pattern")); goto error2; } @@ -899,18 +952,13 @@ error2: qf_init_ok: if (fd != NULL) fclose(fd); - for (fmt_ptr = fmt_first; fmt_ptr != NULL; fmt_ptr = fmt_first) { - fmt_first = fmt_ptr->next; - vim_regfree(fmt_ptr->prog); - xfree(fmt_ptr); - } + free_efm_list(&fmt_first); qf_clean_dir_stack(&dir_stack); qf_clean_dir_stack(&file_stack); qf_init_end: xfree(namebuf); xfree(errmsg); xfree(pattern); - xfree(fmtstr); xfree(growbuf); qf_update_buffer(qi, old_last); diff --git a/src/nvim/version.c b/src/nvim/version.c index c4fdcd61f9..3efc161b05 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -476,7 +476,7 @@ static int included_patches[] = { 1967, // 1966, // 1965 NA - // 1964, + 1964, // 1963 NA // 1962, 1961, -- cgit From fd94e6313b3e7314561cbe90b4cacd44d1088c8f Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:05:58 -0500 Subject: vim-patch:7.4.1966 Problem: Coverity reports a resource leak. Solution: Close "fd" also when bailing out. https://github.com/vim/vim/commit/bcf7772a23624edc0942120e564f6b4ac95604ad --- src/nvim/quickfix.c | 5 ++--- src/nvim/version.c | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 1499c3e12f..39f95d19ae 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -941,7 +941,7 @@ restofline: } /* return number of matches */ retval = qi->qf_lists[qi->qf_curlist].qf_count; - goto qf_init_ok; + goto qf_init_end; } EMSG(_(e_readerrf)); error2: @@ -949,13 +949,12 @@ error2: qi->qf_listcount--; if (qi->qf_curlist > 0) --qi->qf_curlist; -qf_init_ok: +qf_init_end: if (fd != NULL) fclose(fd); free_efm_list(&fmt_first); qf_clean_dir_stack(&dir_stack); qf_clean_dir_stack(&file_stack); -qf_init_end: xfree(namebuf); xfree(errmsg); xfree(pattern); diff --git a/src/nvim/version.c b/src/nvim/version.c index 3efc161b05..576843e61d 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -474,7 +474,7 @@ static int included_patches[] = { // 1969 NA // 1968, 1967, - // 1966, + 1966, // 1965 NA 1964, // 1963 NA -- cgit From 5f6eb62a316712554644a5a76d255df77fba0091 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Dec 2016 10:55:21 -0500 Subject: vim-patch:7.4.1980 Problem: 'errorformat' is parsed for every call to ":caddexpr". Can't add to two location lists asynchronously. Solution: Keep the previously parsed data when appropriate. (mostly by Yegappan Lakshmanan) https://github.com/vim/vim/commit/361c8f0e517e41f1f1d34dae328044406fde80ac --- src/nvim/quickfix.c | 127 +++++++++++++++++++++++-------------- src/nvim/testdir/test_quickfix.vim | 84 +++++++++++++++++++----- src/nvim/version.c | 2 +- 3 files changed, 148 insertions(+), 65 deletions(-) (limited to 'src') diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 39f95d19ae..f4654628fb 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -48,8 +48,6 @@ struct dir_stack_T { char_u *dirname; }; -static struct dir_stack_T *dir_stack = NULL; - /* * For each error the next struct is allocated and linked in a list. */ @@ -97,6 +95,15 @@ struct qf_info_S { int qf_listcount; /* current number of lists */ int qf_curlist; /* current error list */ qf_list_T qf_lists[LISTCOUNT]; + + int qf_dir_curlist; ///< error list for qf_dir_stack + struct dir_stack_T *qf_dir_stack; + char_u *qf_directory; + struct dir_stack_T *qf_file_stack; + char_u *qf_currfile; + bool qf_multiline; + bool qf_multiignore; + bool qf_multiscan; }; static qf_info_T ql_info; /* global quickfix list */ @@ -464,25 +471,20 @@ qf_init_ext ( int enr = 0; FILE *fd = NULL; qfline_T *old_last = NULL; - efm_T *fmt_first = NULL; + static efm_T *fmt_first = NULL; efm_T *fmt_ptr; efm_T *fmt_start = NULL; char_u *efm; + static char_u *last_efm = NULL; char_u *ptr; size_t len; int i; int idx = 0; - bool multiline = false; - bool multiignore = false; - bool multiscan = false; int retval = -1; // default: return error flag - char_u *directory = NULL; - char_u *currfile = NULL; char_u *tail = NULL; char_u *p_buf = NULL; char_u *p_str = NULL; listitem_T *p_li = NULL; - struct dir_stack_T *file_stack = NULL; regmatch_T regmatch; namebuf = xmalloc(CMDBUFFSIZE + 1); @@ -513,7 +515,33 @@ qf_init_ext ( else efm = errorformat; - fmt_first = parse_efm_option(efm); + // If we are not adding or adding to another list: clear the state. + if (newlist || qi->qf_curlist != qi->qf_dir_curlist) { + qi->qf_dir_curlist = qi->qf_curlist; + qf_clean_dir_stack(&qi->qf_dir_stack); + qi->qf_directory = NULL; + qf_clean_dir_stack(&qi->qf_file_stack); + qi->qf_currfile = NULL; + qi->qf_multiline = false; + qi->qf_multiignore = false; + qi->qf_multiscan = false; + } + + // If the errorformat didn't change between calls, then reuse the previously + // parsed values. + if (last_efm == NULL || (STRCMP(last_efm, efm) != 0)) { + // free the previously parsed data + xfree(last_efm); + last_efm = NULL; + free_efm_list(&fmt_first); + + // parse the current 'efm' + fmt_first = parse_efm_option(efm); + if (fmt_first != NULL) { + last_efm = vim_strsave(efm); + } + } + if (fmt_first == NULL) { /* nothing found */ goto error2; } @@ -696,11 +724,11 @@ qf_init_ext ( restofline: for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { idx = fmt_ptr->prefix; - if (multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) + if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) continue; namebuf[0] = NUL; pattern[0] = NUL; - if (!multiscan) + if (!qi->qf_multiscan) errmsg[0] = NUL; lnum = 0; col = 0; @@ -713,7 +741,7 @@ restofline: int r = vim_regexec(®match, linebuf, (colnr_T)0); fmt_ptr->prog = regmatch.regprog; if (r) { - if ((idx == 'C' || idx == 'Z') && !multiline) { + if ((idx == 'C' || idx == 'Z') && !qi->qf_multiline) { continue; } if (vim_strchr((char_u *)"EWI", idx) != NULL) { @@ -759,7 +787,7 @@ restofline: continue; type = *regmatch.startp[i]; } - if (fmt_ptr->flags == '+' && !multiscan) { // %+ + if (fmt_ptr->flags == '+' && !qi->qf_multiscan) { // %+ if (linelen > errmsglen) { // linelen + null terminator errmsg = xrealloc(errmsg, linelen + 1); @@ -820,7 +848,7 @@ restofline: break; } } - multiscan = false; + qi->qf_multiscan = false; if (fmt_ptr == NULL || idx == 'D' || idx == 'X') { if (fmt_ptr != NULL) { @@ -829,10 +857,12 @@ restofline: EMSG(_("E379: Missing or empty directory name")); goto error2; } - if ((directory = qf_push_dir(namebuf, &dir_stack)) == NULL) + qi->qf_directory = qf_push_dir(namebuf, &qi->qf_dir_stack, false); + if (qi->qf_directory == NULL) { goto error2; + } } else if (idx == 'X') /* leave directory */ - directory = qf_pop_dir(&dir_stack); + qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); } namebuf[0] = NUL; // no match found, remove file name lnum = 0; // don't jump to this line @@ -844,7 +874,7 @@ restofline: // copy whole line to error message STRLCPY(errmsg, linebuf, linelen + 1); if (fmt_ptr == NULL) { - multiline = multiignore = false; + qi->qf_multiline = qi->qf_multiignore = false; } } else if (fmt_ptr != NULL) { /* honor %> item */ @@ -852,14 +882,14 @@ restofline: fmt_start = fmt_ptr; if (vim_strchr((char_u *)"AEWI", idx) != NULL) { - multiline = true; // start of a multi-line message - multiignore = false; // reset continuation + qi->qf_multiline = true; // start of a multi-line message + qi->qf_multiignore = false; // reset continuation } else if (vim_strchr((char_u *)"CZ", idx) != NULL) { /* continuation of multi-line msg */ qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; if (qfprev == NULL) goto error2; - if (*errmsg && !multiignore) { + if (*errmsg && !qi->qf_multiignore) { size_t len = STRLEN(qfprev->qf_text); qfprev->qf_text = xrealloc(qfprev->qf_text, len + STRLEN(errmsg) + 2); qfprev->qf_text[len] = '\n'; @@ -875,12 +905,13 @@ restofline: qfprev->qf_col = col; qfprev->qf_viscol = use_viscol; if (!qfprev->qf_fnum) - qfprev->qf_fnum = qf_get_fnum(directory, + qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, *namebuf - || directory ? namebuf : currfile - && valid ? currfile : 0); + || qi->qf_directory + ? namebuf : qi->qf_currfile + && valid ? qi->qf_currfile : 0); if (idx == 'Z') { - multiline = multiignore = false; + qi->qf_multiline = qi->qf_multiignore = false; } line_breakcheck(); continue; @@ -889,31 +920,32 @@ restofline: valid = false; if (*namebuf == NUL || os_path_exists(namebuf)) { if (*namebuf && idx == 'P') { - currfile = qf_push_dir(namebuf, &file_stack); + qi->qf_currfile = qf_push_dir(namebuf, &qi->qf_file_stack, true); } else if (idx == 'Q') { - currfile = qf_pop_dir(&file_stack); + qi->qf_currfile = qf_pop_dir(&qi->qf_file_stack); } *namebuf = NUL; if (tail && *tail) { STRMOVE(IObuff, skipwhite(tail)); - multiscan = true; + qi->qf_multiscan = true; goto restofline; } } } if (fmt_ptr->flags == '-') { // generally exclude this line - if (multiline) { - multiignore = true; // also exclude continuation lines + if (qi->qf_multiline) { + // also exclude continuation lines + qi->qf_multiignore = true; } continue; } } if (qf_add_entry(qi, - directory, - (*namebuf || directory) + qi->qf_directory, + (*namebuf || qi->qf_directory) ? namebuf - : ((currfile && valid) ? currfile : (char_u *)NULL), + : ((qi->qf_currfile && valid) ? qi->qf_currfile : (char_u *)NULL), 0, errmsg, lnum, @@ -952,9 +984,6 @@ error2: qf_init_end: if (fd != NULL) fclose(fd); - free_efm_list(&fmt_first); - qf_clean_dir_stack(&dir_stack); - qf_clean_dir_stack(&file_stack); xfree(namebuf); xfree(errmsg); xfree(pattern); @@ -1071,7 +1100,7 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, buf->b_has_qf_entry = true; } } else - qfp->qf_fnum = qf_get_fnum(dir, fname); + qfp->qf_fnum = qf_get_fnum(qi, dir, fname); qfp->qf_text = vim_strsave(mesg); qfp->qf_lnum = lnum; qfp->qf_col = col; @@ -1245,7 +1274,7 @@ void copy_loclist(win_T *from, win_T *to) // Get buffer number for file "dir.name". // Also sets the b_has_qf_entry flag. -static int qf_get_fnum(char_u *directory, char_u *fname) +static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) { char_u *ptr; buf_T *buf; @@ -1267,7 +1296,7 @@ static int qf_get_fnum(char_u *directory, char_u *fname) */ if (!os_path_exists(ptr)) { xfree(ptr); - directory = qf_guess_filepath(fname); + directory = qf_guess_filepath(qi, fname); if (directory) ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); else @@ -1288,7 +1317,7 @@ static int qf_get_fnum(char_u *directory, char_u *fname) // Push dirbuf onto the directory stack and return pointer to actual dir or // NULL on error. -static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr) +static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, bool is_file_stack) { struct dir_stack_T *ds_ptr; @@ -1301,7 +1330,7 @@ static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr) /* store directory on the stack */ if (vim_isAbsName(dirbuf) || (*stackptr)->next == NULL - || (*stackptr && dir_stack != *stackptr)) + || (*stackptr && is_file_stack)) (*stackptr)->dirname = vim_strsave(dirbuf); else { /* Okay we don't have an absolute path. @@ -1403,17 +1432,17 @@ static void qf_clean_dir_stack(struct dir_stack_T **stackptr) * Then qf_push_dir thinks we are in ./aa/bb, but we are in ./bb. * qf_guess_filepath will return NULL. */ -static char_u *qf_guess_filepath(char_u *filename) +static char_u *qf_guess_filepath(qf_info_T *qi, char_u *filename) { struct dir_stack_T *ds_ptr; struct dir_stack_T *ds_tmp; char_u *fullname; /* no dirs on the stack - there's nothing we can do */ - if (dir_stack == NULL) + if (qi->qf_dir_stack == NULL) return NULL; - ds_ptr = dir_stack->next; + ds_ptr = qi->qf_dir_stack->next; fullname = NULL; while (ds_ptr) { xfree(fullname); @@ -1429,15 +1458,14 @@ static char_u *qf_guess_filepath(char_u *filename) xfree(fullname); /* clean up all dirs we already left */ - while (dir_stack->next != ds_ptr) { - ds_tmp = dir_stack->next; - dir_stack->next = dir_stack->next->next; + while (qi->qf_dir_stack->next != ds_ptr) { + ds_tmp = qi->qf_dir_stack->next; + qi->qf_dir_stack->next = qi->qf_dir_stack->next->next; xfree(ds_tmp->dirname); xfree(ds_tmp); } return ds_ptr==NULL ? NULL : ds_ptr->dirname; - } /// When loading a file from the quickfix, the auto commands may modify it. @@ -2146,6 +2174,9 @@ static void qf_free(qf_info_T *qi, int idx) qi->qf_lists[idx].qf_ptr = NULL; qi->qf_lists[idx].qf_title = NULL; qi->qf_lists[idx].qf_index = 0; + + qf_clean_dir_stack(&qi->qf_dir_stack); + qf_clean_dir_stack(&qi->qf_file_stack); } /* diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 3bd7a8c4fb..2c6a3600e1 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -10,6 +10,7 @@ function! s:setup_commands(cchar) if a:cchar == 'c' command! -nargs=* -bang Xlist clist command! -nargs=* Xgetexpr cgetexpr + command! -nargs=* Xaddexpr caddexpr command! -nargs=* Xolder colder command! -nargs=* Xnewer cnewer command! -nargs=* Xopen copen @@ -33,6 +34,7 @@ function! s:setup_commands(cchar) else command! -nargs=* -bang Xlist llist command! -nargs=* Xgetexpr lgetexpr + command! -nargs=* Xaddexpr laddexpr command! -nargs=* Xolder lolder command! -nargs=* Xnewer lnewer command! -nargs=* Xopen lopen @@ -661,21 +663,25 @@ function! s:dir_stack_tests(cchar) let save_efm=&efm set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' - let l = "Entering dir 'dir1/a'\n" . - \ 'habits2.txt:1:Nine Healthy Habits' . "\n" . - \ "Entering dir 'b'\n" . - \ 'habits3.txt:2:0 Hours of television' . "\n" . - \ 'habits2.txt:7:5 Small meals' . "\n" . - \ "Entering dir 'dir1/c'\n" . - \ 'habits4.txt:3:1 Hour of exercise' . "\n" . - \ "Leaving dir 'dir1/c'\n" . - \ "Leaving dir 'dir1/a'\n" . - \ 'habits1.txt:4:2 Liters of water' . "\n" . - \ "Entering dir 'dir2'\n" . - \ 'habits5.txt:5:3 Cups of hot green tea' . "\n" - \ "Leaving dir 'dir2'\n" - - Xgetexpr l + let lines = ["Entering dir 'dir1/a'", + \ 'habits2.txt:1:Nine Healthy Habits', + \ "Entering dir 'b'", + \ 'habits3.txt:2:0 Hours of television', + \ 'habits2.txt:7:5 Small meals', + \ "Entering dir 'dir1/c'", + \ 'habits4.txt:3:1 Hour of exercise', + \ "Leaving dir 'dir1/c'", + \ "Leaving dir 'dir1/a'", + \ 'habits1.txt:4:2 Liters of water', + \ "Entering dir 'dir2'", + \ 'habits5.txt:5:3 Cups of hot green tea', + \ "Leaving dir 'dir2'" + \] + + Xexpr "" + for l in lines + Xaddexpr l + endfor let qf = g:Xgetlist() @@ -762,7 +768,10 @@ function! Test_efm2() \ "(67,3) warning: 's' already defined" \] set efm=%+P[%f],(%l\\,%c)%*[\ ]%t%*[^:]:\ %m,%-Q - cgetexpr lines + cexpr "" + for l in lines + caddexpr l + endfor let l = getqflist() call assert_equal(9, len(l)) call assert_equal(21, l[2].lnum) @@ -1220,3 +1229,46 @@ function! Test_grep() call s:test_xgrep('c') call s:test_xgrep('l') endfunction + +function! Test_two_windows() + " Use one 'errorformat' for two windows. Add an expression to each of them, + " make sure they each keep their own state. + set efm=%DEntering\ dir\ '%f',%f:%l:%m,%XLeaving\ dir\ '%f' + call mkdir('Xone/a', 'p') + call mkdir('Xtwo/a', 'p') + let lines = ['1', '2', 'one one one', '4', 'two two two', '6', '7'] + call writefile(lines, 'Xone/a/one.txt') + call writefile(lines, 'Xtwo/a/two.txt') + + new one + let one_id = win_getid() + lexpr "" + new two + let two_id = win_getid() + lexpr "" + + laddexpr "Entering dir 'Xtwo/a'" + call win_gotoid(one_id) + laddexpr "Entering dir 'Xone/a'" + call win_gotoid(two_id) + laddexpr 'two.txt:5:two two two' + call win_gotoid(one_id) + laddexpr 'one.txt:3:one one one' + + let loc_one = getloclist(one_id) +echo string(loc_one) + call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) + call assert_equal(3, loc_one[1].lnum) + + let loc_two = getloclist(two_id) +echo string(loc_two) + call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) + call assert_equal(5, loc_two[1].lnum) + + call win_gotoid(one_id) + bwipe! + call win_gotoid(two_id) + bwipe! + call delete('Xone', 'rf') + call delete('Xtwo', 'rf') +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 576843e61d..17bb4aa356 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -460,7 +460,7 @@ static int included_patches[] = { // 1983 NA // 1982 NA // 1981, - // 1980, + 1980, // 1979, // 1978, // 1977, -- cgit From f613c61dae7be1c4f9eadc223a77684a128508b0 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Mon, 12 Dec 2016 15:06:02 -0500 Subject: vim-patch:7.4.1984 Problem: Not all quickfix features are tested. Solution: Add a few more tests. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/0fcc7c6dd1902b71e0e7d0a35ddabafef6455a83 --- src/nvim/testdir/test_quickfix.vim | 138 +++++++++++++++++++++++++++++++++++-- src/nvim/version.c | 2 +- 2 files changed, 132 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 2c6a3600e1..a91e65df6c 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -24,6 +24,11 @@ function! s:setup_commands(cchar) command! -nargs=* Xaddbuffer caddbuffer command! -nargs=* Xrewind crewind command! -nargs=* -bang Xnext cnext + command! -nargs=* -bang Xprev cprev + command! -nargs=* -bang Xfirst cfirst + command! -nargs=* -bang Xlast clast + command! -nargs=* -bang Xnfile cnfile + command! -nargs=* -bang Xpfile cpfile command! -nargs=* Xexpr cexpr command! -nargs=* Xvimgrep vimgrep command! -nargs=* Xgrep grep @@ -48,6 +53,11 @@ function! s:setup_commands(cchar) command! -nargs=* Xaddbuffer laddbuffer command! -nargs=* Xrewind lrewind command! -nargs=* -bang Xnext lnext + command! -nargs=* -bang Xprev lprev + command! -nargs=* -bang Xfirst lfirst + command! -nargs=* -bang Xlast llast + command! -nargs=* -bang Xnfile lnfile + command! -nargs=* -bang Xpfile lpfile command! -nargs=* Xexpr lexpr command! -nargs=* Xvimgrep lvimgrep command! -nargs=* Xgrep lgrep @@ -310,6 +320,56 @@ function Test_cbuffer() call XbufferTests('l') endfunction +function XexprTests(cchar) + call s:setup_commands(a:cchar) + + call assert_fails('Xexpr 10', 'E777:') +endfunction + +function Test_cexpr() + call XexprTests('c') + call XexprTests('l') +endfunction + +" Tests for :cnext, :cprev, :cfirst, :clast commands +function Xtest_browse(cchar) + call s:setup_commands(a:cchar) + + call s:create_test_file('Xqftestfile1') + call s:create_test_file('Xqftestfile2') + + Xgetexpr ['Xqftestfile1:5:Line5', + \ 'Xqftestfile1:6:Line6', + \ 'Xqftestfile2:10:Line10', + \ 'Xqftestfile2:11:Line11'] + + Xfirst + call assert_fails('Xprev', 'E553') + call assert_fails('Xpfile', 'E553') + Xnfile + call assert_equal('Xqftestfile2', bufname('%')) + call assert_equal(10, line('.')) + Xpfile + call assert_equal('Xqftestfile1', bufname('%')) + call assert_equal(6, line('.')) + Xlast + call assert_equal('Xqftestfile2', bufname('%')) + call assert_equal(11, line('.')) + call assert_fails('Xnext', 'E553') + call assert_fails('Xnfile', 'E553') + Xrewind + call assert_equal('Xqftestfile1', bufname('%')) + call assert_equal(5, line('.')) + + call delete('Xqftestfile1') + call delete('Xqftestfile2') +endfunction + +function Test_browse() + call Xtest_browse('c') + call Xtest_browse('l') +endfunction + function! s:test_xhelpgrep(cchar) call s:setup_commands(a:cchar) Xhelpgrep quickfix @@ -736,25 +796,61 @@ function! Test_efm_dirstack() call delete('habits1.txt') endfunction +" Tests for invalid error format specifies +function Xinvalid_efm_Tests(cchar) + call s:setup_commands(a:cchar) + + let save_efm = &efm + + set efm=%f:%l:%m,%f:%f:%l:%m + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E372:') + + set efm=%f:%l:%m,%f:%l:%r:%m + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:') + + set efm=%f:%l:%m,%O:%f:%l:%m + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E373:') + + set efm=%f:%l:%m,%f:%l:%*[^a-z + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E374:') + + set efm=%f:%l:%m,%f:%l:%*c + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E375:') + + set efm=%f:%l:%m,%L%M%N + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E376:') + + set efm=%f:%l:%m,%f:%l:%m:%R + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E377:') + + set efm= + call assert_fails('Xexpr "abc.txt:1:Hello world"', 'E378:') + + set efm=%DEntering\ dir\ abc,%f:%l:%m + call assert_fails('Xexpr ["Entering dir abc", "abc.txt:1:Hello world"]', 'E379:') + + let &efm = save_efm +endfunction + +function Test_invalid_efm() + call Xinvalid_efm_Tests('c') + call Xinvalid_efm_Tests('l') +endfunction + " TODO: " Add tests for the following formats in 'errorformat' -" %n %t %r %+ %- %O +" %r %O function! Test_efm2() let save_efm = &efm - " Test for invalid efm - set efm=%L%M%N - call assert_fails('cexpr "abc.txt:1:Hello world"', 'E376:') - call assert_fails('lexpr "abc.txt:1:Hello world"', 'E376:') - " Test for %s format in efm set efm=%f:%s cexpr 'Xtestfile:Line search text' - let l = getqflist() call assert_equal(l[0].pattern, '^\VLine search text\$') call assert_equal(l[0].lnum, 0) + " Test for %P, %Q and %t format specifiers let lines=["[Xtestfile1]", \ "(1,17) error: ';' missing", \ "(21,2) warning: variable 'z' not defined", @@ -776,6 +872,34 @@ function! Test_efm2() call assert_equal(9, len(l)) call assert_equal(21, l[2].lnum) call assert_equal(2, l[2].col) + call assert_equal('w', l[2].type) + call assert_equal('e', l[3].type) + + " Tests for %E, %C and %Z format specifiers + let lines = ["Error 275", + \ "line 42", + \ "column 3", + \ "' ' expected after '--'" + \] + set efm=%EError\ %n,%Cline\ %l,%Ccolumn\ %c,%Z%m + cgetexpr lines + let l = getqflist() + call assert_equal(275, l[0].nr) + call assert_equal(42, l[0].lnum) + call assert_equal(3, l[0].col) + call assert_equal('E', l[0].type) + call assert_equal("\n' ' expected after '--'", l[0].text) + + " Test for %> + let lines = ["Error in line 147 of foo.c:", + \"unknown variable 'i'" + \] + set efm=unknown\ variable\ %m,%E%>Error\ in\ line\ %l\ of\ %f:,%Z%m + cgetexpr lines + let l = getqflist() + call assert_equal(147, l[0].lnum) + call assert_equal('E', l[0].type) + call assert_equal("\nunknown variable 'i'", l[0].text) let &efm = save_efm endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index 17bb4aa356..b5168f565b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -456,7 +456,7 @@ static int included_patches[] = { // 1987 NA // 1986, // 1985 NA - // 1984, + 1984, // 1983 NA // 1982 NA // 1981, -- cgit From f224f3fbf11ffd3095843c597045ca95c8241fcf Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Dec 2016 14:36:38 -0500 Subject: vim-patch:7.4.1997 Problem: Cannot easily scroll the quickfix window. Solution: Add ":cbottom". https://github.com/vim/vim/commit/dcb170018642ec144cd87d9d9fe076575b8d1263 --- src/nvim/ex_cmds.lua | 6 +++++ src/nvim/quickfix.c | 48 ++++++++++++++++++++++++++------------ src/nvim/testdir/test_quickfix.vim | 13 +++++++++++ src/nvim/version.c | 2 +- 4 files changed, 53 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index b056fff667..e39e374e2e 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -357,6 +357,12 @@ return { addr_type=ADDR_LINES, func='ex_cbuffer', }, + { + command='cbottom', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='ex_cbottom', + }, { command='cc', flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR, BANG), diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index f4654628fb..c40b7173c5 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2431,6 +2431,34 @@ void ex_copen(exarg_T *eap) update_topline(); /* scroll to show the line */ } +// Move the cursor in the quickfix window to "lnum". +static void qf_win_goto(win_T *win, linenr_T lnum) +{ + win_T *old_curwin = curwin; + + curwin = win; + curbuf = win->w_buffer; + curwin->w_cursor.lnum = lnum; + curwin->w_cursor.col = 0; + curwin->w_cursor.coladd = 0; + curwin->w_curswant = 0; + update_topline(); // scroll to show the line + redraw_later(VALID); + curwin->w_redr_status = true; // update ruler + curwin = old_curwin; + curbuf = curwin->w_buffer; +} + +// :cbottom command. +void ex_cbottom(exarg_T *eap) +{ + win_T *win = qf_find_win(&ql_info); + + if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count) { + qf_win_goto(win, win->w_buffer->b_ml.ml_line_count); + } +} + /* * Return the number of the current entry (line number in the quickfix * window). @@ -2467,24 +2495,14 @@ qf_win_pos_update ( if (win != NULL && qf_index <= win->w_buffer->b_ml.ml_line_count && old_qf_index != qf_index) { - win_T *old_curwin = curwin; - - curwin = win; - curbuf = win->w_buffer; if (qf_index > old_qf_index) { - curwin->w_redraw_top = old_qf_index; - curwin->w_redraw_bot = qf_index; + win->w_redraw_top = old_qf_index; + win->w_redraw_bot = qf_index; } else { - curwin->w_redraw_top = qf_index; - curwin->w_redraw_bot = old_qf_index; + win->w_redraw_top = qf_index; + win->w_redraw_bot = old_qf_index; } - curwin->w_cursor.lnum = qf_index; - curwin->w_cursor.col = 0; - update_topline(); /* scroll to show the line */ - redraw_later(VALID); - curwin->w_redr_status = TRUE; /* update ruler */ - curwin = old_curwin; - curbuf = curwin->w_buffer; + qf_win_goto(win, qf_index); } return win != NULL; } diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index a91e65df6c..7b141f17a4 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -1396,3 +1396,16 @@ echo string(loc_two) call delete('Xone', 'rf') call delete('Xtwo', 'rf') endfunc + +function Test_cbottom() + call setqflist([{'filename': 'foo', 'lnum': 42}]) + copen + let wid = win_getid() + call assert_equal(1, line('.')) + wincmd w + call setqflist([{'filename': 'var', 'lnum': 24}], 'a') + cbottom + call win_gotoid(wid) + call assert_equal(2, line('.')) + cclose +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index b5168f565b..9a273dd66c 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -443,7 +443,7 @@ static int included_patches[] = { // 2000, // 1999, // 1998 NA - // 1997, + 1997, // 1996, // 1995 NA // 1994, -- cgit From 2c59277ca867cb3cb0144adedcfe05373d5498de Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Dec 2016 15:33:06 -0500 Subject: vim-patch:7.4.2010 Problem: There is a :cbottom command but no :lbottom command. Solution: Add :lbottom. (Yegappan Lakshmanan) https://github.com/vim/vim/commit/537ef08408c50e0c4104d57f74993b3b0ed9560d --- src/nvim/ex_cmds.lua | 6 ++++++ src/nvim/quickfix.c | 14 ++++++++++++-- src/nvim/testdir/test_quickfix.vim | 23 +++++++++++++++++------ src/nvim/version.c | 2 +- 4 files changed, 36 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index e39e374e2e..eaf18fc664 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1271,6 +1271,12 @@ return { addr_type=ADDR_LINES, func='ex_later', }, + { + command='lbottom', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='ex_cbottom', + }, { command='lbuffer', flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR), diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index c40b7173c5..93d0df1076 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -2449,10 +2449,20 @@ static void qf_win_goto(win_T *win, linenr_T lnum) curbuf = curwin->w_buffer; } -// :cbottom command. +// :cbottom/:lbottom command. void ex_cbottom(exarg_T *eap) { - win_T *win = qf_find_win(&ql_info); + qf_info_T *qi = &ql_info; + + if (eap->cmdidx == CMD_lbottom) { + qi = GET_LOC_LIST(curwin); + if (qi == NULL) { + EMSG(_(e_loclist)); + return; + } + } + + win_T *win = qf_find_win(qi); if (win != NULL && win->w_cursor.lnum != win->w_buffer->b_ml.ml_line_count) { qf_win_goto(win, win->w_buffer->b_ml.ml_line_count); diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index 7b141f17a4..f30902b915 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -15,6 +15,7 @@ function! s:setup_commands(cchar) command! -nargs=* Xnewer cnewer command! -nargs=* Xopen copen command! -nargs=* Xwindow cwindow + command! -nargs=* Xbottom cbottom command! -nargs=* Xclose cclose command! -nargs=* -bang Xfile cfile command! -nargs=* Xgetfile cgetfile @@ -44,6 +45,7 @@ function! s:setup_commands(cchar) command! -nargs=* Xnewer lnewer command! -nargs=* Xopen lopen command! -nargs=* Xwindow lwindow + command! -nargs=* Xbottom lbottom command! -nargs=* Xclose lclose command! -nargs=* -bang Xfile lfile command! -nargs=* Xgetfile lgetfile @@ -200,6 +202,7 @@ function XwindowTests(cchar) Xwindow call assert_true(winnr('$') == 2 && winnr() == 2 && \ getline('.') ==# 'Xtestfile1|1 col 3| Line1') + redraw! " Close the window Xclose @@ -1397,15 +1400,23 @@ echo string(loc_two) call delete('Xtwo', 'rf') endfunc -function Test_cbottom() - call setqflist([{'filename': 'foo', 'lnum': 42}]) - copen +function XbottomTests(cchar) + call s:setup_commands(a:cchar) + + call g:Xsetlist([{'filename': 'foo', 'lnum': 42}]) + Xopen let wid = win_getid() call assert_equal(1, line('.')) wincmd w - call setqflist([{'filename': 'var', 'lnum': 24}], 'a') - cbottom + call g:Xsetlist([{'filename': 'var', 'lnum': 24}], 'a') + Xbottom call win_gotoid(wid) call assert_equal(2, line('.')) - cclose + Xclose endfunc + +" Tests for the :cbottom and :lbottom commands +function Test_cbottom() + call XbottomTests('c') + call XbottomTests('l') +endfunction diff --git a/src/nvim/version.c b/src/nvim/version.c index 9a273dd66c..512d52cbc4 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -430,7 +430,7 @@ static int included_patches[] = { 2013, 2012, 2011, - // 2010, + 2010, // 2009, // 2008, 2007, -- cgit From 7565b48e9cc4f64d7bf008d62b4a7479676a7b09 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Dec 2016 15:44:31 -0500 Subject: vim-patch:8.0.0006 Problem: ":lb" is interpreted as ":lbottom" while the documentation says it means ":lbuffer". Solution: Adjust the order of the commands. (haya14busa, closes vim/vim#1093) https://github.com/vim/vim/commit/ebdd90ac282909c0bfcd6e83e70505abbbd5a38d --- src/nvim/ex_cmds.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index eaf18fc664..b998b81284 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1271,18 +1271,18 @@ return { addr_type=ADDR_LINES, func='ex_later', }, - { - command='lbottom', - flags=bit.bor(TRLBAR), - addr_type=ADDR_LINES, - func='ex_cbottom', - }, { command='lbuffer', flags=bit.bor(BANG, RANGE, NOTADR, WORD1, TRLBAR), addr_type=ADDR_LINES, func='ex_cbuffer', }, + { + command='lbottom', + flags=bit.bor(TRLBAR), + addr_type=ADDR_LINES, + func='ex_cbottom', + }, { command='lcd', flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN), -- cgit From 3224ade9c3b6e339083ab9e66ce3d3f32e050e09 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Wed, 14 Dec 2016 16:16:37 -0500 Subject: lint --- src/nvim/buffer_defs.h | 10 +- src/nvim/eval.c | 3 +- src/nvim/quickfix.c | 380 ++++++++++++++++++++++++++----------------------- 3 files changed, 205 insertions(+), 188 deletions(-) (limited to 'src') diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index da08357cb0..0418a737eb 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -1037,11 +1037,11 @@ struct window_S { */ int w_wrow, w_wcol; /* cursor position in window */ - linenr_T w_botline; /* number of the line below the bottom of - the window */ - int w_empty_rows; /* number of ~ rows in window */ - int w_filler_rows; /* number of filler rows at the end of the - window */ + linenr_T w_botline; // number of the line below the bottom of + // the window + int w_empty_rows; // number of ~ rows in window + int w_filler_rows; // number of filler rows at the end of the + // window /* * Info about the lines currently in the window is remembered to avoid diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 45364a1666..bdbd77337d 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -15018,8 +15018,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) char_u *act = get_tv_string_chk(action_arg); if ((*act == 'a' || *act == 'r' || *act == ' ') && act[1] == NUL) { action = *act; - } - else { + } else { EMSG2(_(e_invact), act); return; } diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 93d0df1076..33a84660c1 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -74,14 +74,14 @@ struct qfline_S { #define LISTCOUNT 10 typedef struct qf_list_S { - qfline_T *qf_start; /* pointer to the first error */ + qfline_T *qf_start; // pointer to the first error qfline_T *qf_last; // pointer to the last error - qfline_T *qf_ptr; /* pointer to the current error */ - int qf_count; /* number of errors (0 means no error list) */ - int qf_index; /* current index in the error list */ - int qf_nonevalid; /* TRUE if not a single valid entry found */ - char_u *qf_title; /* title derived from the command that created - * the error list */ + qfline_T *qf_ptr; // pointer to the current error + int qf_count; // number of errors (0 means no error list) + int qf_index; // current index in the error list + int qf_nonevalid; // TRUE if not a single valid entry found + char_u *qf_title; // title derived from the command that created + // the error list } qf_list_T; struct qf_info_S { @@ -201,16 +201,16 @@ static struct fmtpattern char *pattern; } fmt_pat[FMT_PATTERNS] = { - {'f', ".\\+"}, // only used when at end - {'n', "\\d\\+"}, - {'l', "\\d\\+"}, - {'c', "\\d\\+"}, - {'t', "."}, - {'m', ".\\+"}, - {'r', ".*"}, - {'p', "[- .]*"}, - {'v', "\\d\\+"}, - {'s', ".\\+"} + { 'f', ".\\+" }, // only used when at end + { 'n', "\\d\\+" }, + { 'l', "\\d\\+" }, + { 'c', "\\d\\+" }, + { 't', "." }, + { 'm', ".\\+" }, + { 'r', ".*" }, + { 'p', "[- .]*" }, // NOLINT(whitespace/tab) + { 'v', "\\d\\+" }, + { 's', ".\\+" } }; // Converts a 'errorformat' string to regular expression pattern @@ -232,8 +232,8 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, } if (idx < FMT_PATTERNS) { if (fmt_ptr->addr[idx]) { - sprintf((char *)errmsg, - _("E372: Too many %%%c in format string"), *efmp); + snprintf((char *)errmsg, CMDBUFFSIZE + 1, + _("E372: Too many %%%c in format string"), *efmp); EMSG(errmsg); return -1; } @@ -242,8 +242,8 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, && vim_strchr((char_u *)"DXOPQ", fmt_ptr->prefix) != NULL) || (idx == 6 && vim_strchr((char_u *)"OPQ", fmt_ptr->prefix) == NULL)) { - sprintf((char *)errmsg, - _("E373: Unexpected %%%c in format string"), *efmp); + snprintf((char *)errmsg, CMDBUFFSIZE + 1, + _("E373: Unexpected %%%c in format string"), *efmp); EMSG(errmsg); return -1; } @@ -310,9 +310,9 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, *ptr++ = '\\'; *ptr++ = '+'; } else { - // TODO: scanf()-like: %*ud, %*3c, %*f, ... ? - sprintf((char *)errmsg, - _("E375: Unsupported %%%c in format string"), *efmp); + // TODO(vim): scanf()-like: %*ud, %*3c, %*f, ... ? + snprintf((char *)errmsg, CMDBUFFSIZE + 1, + _("E375: Unsupported %%%c in format string"), *efmp); EMSG(errmsg); return -1; } @@ -329,14 +329,14 @@ static int efm_to_regpat(char_u *efm, int len, efm_T *fmt_ptr, if (vim_strchr((char_u *)"DXAEWICZGOPQ", *efmp) != NULL) { fmt_ptr->prefix = *efmp; } else { - sprintf((char *)errmsg, - _("E376: Invalid %%%c in format string prefix"), *efmp); + snprintf((char *)errmsg, CMDBUFFSIZE + 1, + _("E376: Invalid %%%c in format string prefix"), *efmp); EMSG(errmsg); return -1; } } else { - sprintf((char *)errmsg, - _("E377: Invalid %%%c in format string"), *efmp); + snprintf((char *)errmsg, CMDBUFFSIZE + 1, + _("E377: Invalid %%%c in format string"), *efmp); EMSG(errmsg); return -1; } @@ -382,11 +382,7 @@ static efm_T * parse_efm_option(char_u *efm) for (int round = FMT_PATTERNS - 1; round >= 0; ) { i += STRLEN(fmt_pat[round--].pattern); } -#ifdef COLON_IN_FILENAME - i += 12; /* "%f" can become twelve chars longer */ -#else - i += 2; /* "%f" can become two chars longer */ -#endif + i += 2; // "%f" can become two chars longer char_u *fmtstr = xmalloc(i); while (efm[0] != NUL) { @@ -440,8 +436,8 @@ parse_efm_end: // Then "lnumfirst" and "lnumlast" specify the range of lines to use. // Set the title of the list to "qf_title". // Return -1 for error, number of errors for success. -static int -qf_init_ext ( +static int +qf_init_ext( qf_info_T *qi, char_u *efile, buf_T *buf, @@ -476,7 +472,6 @@ qf_init_ext ( efm_T *fmt_start = NULL; char_u *efm; static char_u *last_efm = NULL; - char_u *ptr; size_t len; int i; int idx = 0; @@ -497,11 +492,11 @@ qf_init_ext ( goto qf_init_end; } - if (newlist || qi->qf_curlist == qi->qf_listcount) - /* make place for a new list */ + if (newlist || qi->qf_curlist == qi->qf_listcount) { + // make place for a new list qf_new_list(qi, qf_title); - else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { - /* Adding to existing list, use last entry. */ + } else if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { + // Adding to existing list, use last entry. old_last = qi->qf_lists[qi->qf_curlist].qf_last; } @@ -542,7 +537,7 @@ qf_init_ext ( } } - if (fmt_first == NULL) { /* nothing found */ + if (fmt_first == NULL) { // nothing found goto error2; } @@ -574,14 +569,16 @@ qf_init_ext ( /* Get the next line from the supplied string */ char_u *p; - if (*p_str == NUL) // Reached the end of the string + if (*p_str == NUL) { // Reached the end of the string break; + } p = vim_strchr(p_str, '\n'); - if (p != NULL) + if (p != NULL) { len = (size_t)(p - p_str) + 1; - else + } else { len = STRLEN(p_str); + } if (len > IOSIZE - 2) { linebuf = qf_grow_linebuf(&growbuf, &growbufsiz, len, &linelen); @@ -602,8 +599,9 @@ qf_init_ext ( p_li = p_li->li_next; // Skip non-string items } - if (p_li == NULL) // End of the list + if (p_li == NULL) { // End of the list break; + } len = STRLEN(p_li->li_tv.vval.v_string); if (len > IOSIZE - 2) { @@ -640,9 +638,9 @@ qf_init_ext ( linelen = STRLEN(IObuff); if (linelen == IOSIZE - 1 && !(IObuff[linelen - 1] == '\n' #ifdef USE_CRNL - || IObuff[linelen - 1] == '\r' + || IObuff[linelen - 1] == '\r' #endif - )) { + )) { // NOLINT(whitespace/parens) // The current line exceeds IObuff, continue reading using growbuf // until EOL or LINE_MAXLEN bytes is read. if (growbuf == NULL) { @@ -655,7 +653,7 @@ qf_init_ext ( growbuflen = linelen; for (;;) { - if (fgets((char*)growbuf + growbuflen, + if (fgets((char *)growbuf + growbuflen, (int)(growbufsiz - growbuflen), fd) == NULL) { break; } @@ -665,7 +663,7 @@ qf_init_ext ( #ifdef USE_CRNL || growbuf[growbuflen - 1] == '\r' #endif - ) { + ) { break; } if (growbufsiz == LINE_MAXLEN) { @@ -687,7 +685,7 @@ qf_init_ext ( #ifdef USE_CRNL || IObuff[IOSIZE - 1] == '\r' #endif - ) { + ) { break; } } @@ -724,12 +722,14 @@ qf_init_ext ( restofline: for (; fmt_ptr != NULL; fmt_ptr = fmt_ptr->next) { idx = fmt_ptr->prefix; - if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) + if (qi->qf_multiscan && vim_strchr((char_u *)"OPQ", idx) == NULL) { continue; + } namebuf[0] = NUL; pattern[0] = NUL; - if (!qi->qf_multiscan) + if (!qi->qf_multiscan) { errmsg[0] = NUL; + } lnum = 0; col = 0; use_viscol = false; @@ -794,9 +794,10 @@ restofline: errmsglen = linelen + 1; } STRLCPY(errmsg, linebuf, linelen + 1); - } else if ((i = (int)fmt_ptr->addr[5]) > 0) { /* %m */ - if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) + } else if ((i = (int)fmt_ptr->addr[5]) > 0) { // %m + if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) { continue; + } len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); if (len > errmsglen) { // len + null terminator @@ -837,8 +838,9 @@ restofline: if (regmatch.startp[i] == NULL || regmatch.endp[i] == NULL) continue; len = (size_t)(regmatch.endp[i] - regmatch.startp[i]); - if (len > CMDBUFFSIZE - 5) + if (len > CMDBUFFSIZE - 5) { len = CMDBUFFSIZE - 5; + } STRCPY(pattern, "^\\V"); STRNCAT(pattern, regmatch.startp[i], len); pattern[len + 3] = '\\'; @@ -861,8 +863,9 @@ restofline: if (qi->qf_directory == NULL) { goto error2; } - } else if (idx == 'X') /* leave directory */ + } else if (idx == 'X') { // leave directory qi->qf_directory = qf_pop_dir(&qi->qf_dir_stack); + } } namebuf[0] = NUL; // no match found, remove file name lnum = 0; // don't jump to this line @@ -885,10 +888,11 @@ restofline: qi->qf_multiline = true; // start of a multi-line message qi->qf_multiignore = false; // reset continuation } else if (vim_strchr((char_u *)"CZ", idx) - != NULL) { /* continuation of multi-line msg */ + != NULL) { // continuation of multi-line msg qfline_T *qfprev = qi->qf_lists[qi->qf_curlist].qf_last; - if (qfprev == NULL) + if (qfprev == NULL) { goto error2; + } if (*errmsg && !qi->qf_multiignore) { size_t len = STRLEN(qfprev->qf_text); qfprev->qf_text = xrealloc(qfprev->qf_text, len + STRLEN(errmsg) + 2); @@ -904,12 +908,13 @@ restofline: if (!qfprev->qf_col) qfprev->qf_col = col; qfprev->qf_viscol = use_viscol; - if (!qfprev->qf_fnum) + if (!qfprev->qf_fnum) { qfprev->qf_fnum = qf_get_fnum(qi, qi->qf_directory, *namebuf || qi->qf_directory ? namebuf : qi->qf_currfile && valid ? qi->qf_currfile : 0); + } if (idx == 'Z') { qi->qf_multiline = qi->qf_multiignore = false; } @@ -942,20 +947,21 @@ restofline: } if (qf_add_entry(qi, - qi->qf_directory, - (*namebuf || qi->qf_directory) - ? namebuf - : ((qi->qf_currfile && valid) ? qi->qf_currfile : (char_u *)NULL), - 0, - errmsg, - lnum, - col, - use_viscol, - pattern, - enr, - type, - valid) == FAIL) + qi->qf_directory, + (*namebuf || qi->qf_directory) + ? namebuf : ((qi->qf_currfile && valid) + ? qi->qf_currfile : (char_u *)NULL), + 0, + errmsg, + lnum, + col, + use_viscol, + pattern, + enr, + type, + valid) == FAIL) { goto error2; + } line_breakcheck(); } if (fd == NULL || !ferror(fd)) { @@ -979,11 +985,13 @@ restofline: error2: qf_free(qi, qi->qf_curlist); qi->qf_listcount--; - if (qi->qf_curlist > 0) - --qi->qf_curlist; + if (qi->qf_curlist > 0) { + qi->qf_curlist--; + } qf_init_end: - if (fd != NULL) + if (fd != NULL) { fclose(fd); + } xfree(namebuf); xfree(errmsg); xfree(pattern); @@ -1099,8 +1107,9 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, if (buf != NULL) { buf->b_has_qf_entry = true; } - } else + } else { qfp->qf_fnum = qf_get_fnum(qi, dir, fname); + } qfp->qf_text = vim_strsave(mesg); qfp->qf_lnum = lnum; qfp->qf_col = col; @@ -1129,9 +1138,9 @@ static int qf_add_entry(qf_info_T *qi, char_u *dir, char_u *fname, int bufnum, (*lastp)->qf_next = qfp; } qfp->qf_next = NULL; - qfp->qf_cleared = FALSE; + qfp->qf_cleared = false; *lastp = qfp; - ++qi->qf_lists[qi->qf_curlist].qf_count; + qi->qf_lists[qi->qf_curlist].qf_count++; if (qi->qf_lists[qi->qf_curlist].qf_index == 0 && qfp->qf_valid) { /* first valid entry */ qi->qf_lists[qi->qf_curlist].qf_index = @@ -1227,22 +1236,22 @@ void copy_loclist(win_T *from, win_T *to) qfline_T *from_qfp; qfline_T *prevp; - /* copy all the location entries in this list */ + // copy all the location entries in this list for (i = 0, from_qfp = from_qfl->qf_start; i < from_qfl->qf_count && from_qfp != NULL; - ++i, from_qfp = from_qfp->qf_next) { + i++, from_qfp = from_qfp->qf_next) { if (qf_add_entry(to->w_llist, - NULL, - NULL, - 0, - from_qfp->qf_text, - from_qfp->qf_lnum, - from_qfp->qf_col, - from_qfp->qf_viscol, - from_qfp->qf_pattern, - from_qfp->qf_nr, - 0, - from_qfp->qf_valid) == FAIL) { + NULL, + NULL, + 0, + from_qfp->qf_text, + from_qfp->qf_lnum, + from_qfp->qf_col, + from_qfp->qf_viscol, + from_qfp->qf_pattern, + from_qfp->qf_nr, + 0, + from_qfp->qf_valid) == FAIL) { qf_free_all(to); return; } @@ -1252,10 +1261,11 @@ void copy_loclist(win_T *from, win_T *to) * field is copied here. */ prevp = to->w_llist->qf_lists[to->w_llist->qf_curlist].qf_last; - prevp->qf_fnum = from_qfp->qf_fnum; /* file number */ - prevp->qf_type = from_qfp->qf_type; /* error type */ - if (from_qfl->qf_ptr == from_qfp) - to_qfl->qf_ptr = prevp; /* current location */ + prevp->qf_fnum = from_qfp->qf_fnum; // file number + prevp->qf_type = from_qfp->qf_type; // error type + if (from_qfl->qf_ptr == from_qfp) { + to_qfl->qf_ptr = prevp; // current location + } } } @@ -1278,31 +1288,32 @@ static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) { char_u *ptr; buf_T *buf; - if (fname == NULL || *fname == NUL) /* no file name */ + if (fname == NULL || *fname == NUL) { // no file name return 0; + } #ifdef BACKSLASH_IN_FILENAME - if (directory != NULL) + if (directory != NULL) { slash_adjust(directory); + } slash_adjust(fname); #endif if (directory != NULL && !vim_isAbsName(fname)) { - ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); - /* - * Here we check if the file really exists. - * This should normally be true, but if make works without - * "leaving directory"-messages we might have missed a - * directory change. - */ + ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, true); + // Here we check if the file really exists. + // This should normally be true, but if make works without + // "leaving directory"-messages we might have missed a + // directory change. if (!os_path_exists(ptr)) { xfree(ptr); directory = qf_guess_filepath(qi, fname); - if (directory) - ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, TRUE); - else + if (directory) { + ptr = (char_u *)concat_fnames((char *)directory, (char *)fname, true); + } else { ptr = vim_strsave(fname); + } } - /* Use concatenated directory name and file name */ + // Use concatenated directory name and file name buf = buflist_new(ptr, NULL, (linenr_T)0, 0); xfree(ptr); } else { @@ -1317,7 +1328,8 @@ static int qf_get_fnum(qf_info_T *qi, char_u *directory, char_u *fname) // Push dirbuf onto the directory stack and return pointer to actual dir or // NULL on error. -static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, bool is_file_stack) +static char_u *qf_push_dir(char_u *dirbuf, struct dir_stack_T **stackptr, + bool is_file_stack) { struct dir_stack_T *ds_ptr; @@ -1438,9 +1450,10 @@ static char_u *qf_guess_filepath(qf_info_T *qi, char_u *filename) struct dir_stack_T *ds_tmp; char_u *fullname; - /* no dirs on the stack - there's nothing we can do */ - if (qi->qf_dir_stack == NULL) + // no dirs on the stack - there's nothing we can do + if (qi->qf_dir_stack == NULL) { return NULL; + } ds_ptr = qi->qf_dir_stack->next; fullname = NULL; @@ -1457,7 +1470,7 @@ static char_u *qf_guess_filepath(qf_info_T *qi, char_u *filename) xfree(fullname); - /* clean up all dirs we already left */ + // clean up all dirs we already left while (qi->qf_dir_stack->next != ds_ptr) { ds_tmp = qi->qf_dir_stack->next; qi->qf_dir_stack->next = qi->qf_dir_stack->next->next; @@ -1465,7 +1478,7 @@ static char_u *qf_guess_filepath(qf_info_T *qi, char_u *filename) xfree(ds_tmp); } - return ds_ptr==NULL ? NULL : ds_ptr->dirname; + return ds_ptr == NULL ? NULL : ds_ptr->dirname; } /// When loading a file from the quickfix, the auto commands may modify it. @@ -2066,7 +2079,7 @@ void qf_list(exarg_T *eap) if (qfp == NULL) { break; } - ++i; + i++; os_breakcheck(); } } @@ -2138,8 +2151,8 @@ void qf_age(exarg_T *eap) static void qf_msg(qf_info_T *qi) { smsg(_("error list %d of %d; %d errors"), - qi->qf_curlist + 1, qi->qf_listcount, - qi->qf_lists[qi->qf_curlist].qf_count); + qi->qf_curlist + 1, qi->qf_listcount, + qi->qf_lists[qi->qf_curlist].qf_count); qf_update_buffer(qi, NULL); } @@ -2150,7 +2163,7 @@ static void qf_free(qf_info_T *qi, int idx) { qfline_T *qfp; qfline_T *qfpnext; - int stop = FALSE; + bool stop = false; while (qi->qf_lists[idx].qf_count && qi->qf_lists[idx].qf_start != NULL) { qfp = qi->qf_lists[idx].qf_start; @@ -2160,14 +2173,15 @@ static void qf_free(qf_info_T *qi, int idx) stop = (qfp == qfpnext); xfree(qfp->qf_pattern); xfree(qfp); - if (stop) - /* Somehow qf_count may have an incorrect value, set it to 1 - * to avoid crashing when it's wrong. - * TODO: Avoid qf_count being incorrect. */ + if (stop) { + // Somehow qf_count may have an incorrect value, set it to 1 + // to avoid crashing when it's wrong. + // TODO(vim): Avoid qf_count being incorrect. qi->qf_lists[idx].qf_count = 1; + } } qi->qf_lists[idx].qf_start = qfpnext; - --qi->qf_lists[idx].qf_count; + qi->qf_lists[idx].qf_count--; } xfree(qi->qf_lists[idx].qf_title); qi->qf_lists[idx].qf_start = NULL; @@ -2203,7 +2217,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long if (qi->qf_lists[idx].qf_count) for (i = 0, qfp = qi->qf_lists[idx].qf_start; i < qi->qf_lists[idx].qf_count && qfp != NULL; - ++i, qfp = qfp->qf_next) + i++, qfp = qfp->qf_next) { if (qfp->qf_fnum == curbuf->b_fnum) { found_one = true; if (qfp->qf_lnum >= line1 && qfp->qf_lnum <= line2) { @@ -2214,6 +2228,7 @@ void qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, long amount, long } else if (amount_after && qfp->qf_lnum > line2) qfp->qf_lnum += amount_after; } + } if (!found_one) { curbuf->b_has_qf_entry = false; @@ -2442,9 +2457,9 @@ static void qf_win_goto(win_T *win, linenr_T lnum) curwin->w_cursor.col = 0; curwin->w_cursor.coladd = 0; curwin->w_curswant = 0; - update_topline(); // scroll to show the line + update_topline(); // scroll to show the line redraw_later(VALID); - curwin->w_redr_status = true; // update ruler + curwin->w_redr_status = true; // update ruler curwin = old_curwin; curbuf = curwin->w_buffer; } @@ -2639,14 +2654,15 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) return; } - /* delete all existing lines */ - while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) - (void)ml_delete((linenr_T)1, FALSE); + // delete all existing lines + while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) { + (void)ml_delete((linenr_T)1, false); + } } /* Check if there is anything to display */ if (qi->qf_curlist < qi->qf_listcount) { - /* Add one line for each error */ + // Add one line for each error if (old_last == NULL) { qfp = qi->qf_lists[qi->qf_curlist].qf_start; lnum = 0; @@ -2694,9 +2710,10 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) qf_fmt_text(len > 3 ? skipwhite(qfp->qf_text) : qfp->qf_text, IObuff + len, IOSIZE - len); - if (ml_append_buf(buf, lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, FALSE) - == FAIL) + if (ml_append_buf(buf, lnum, IObuff, (colnr_T)STRLEN(IObuff) + 1, false) + == FAIL) { break; + } lnum++; qfp = qfp->qf_next; if (qfp == NULL) { @@ -2704,8 +2721,8 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) } } if (old_last == NULL) { - /* Delete the empty line which is now at the end */ - (void)ml_delete(lnum + 1, FALSE); + // Delete the empty line which is now at the end + (void)ml_delete(lnum + 1, false); } } @@ -2713,20 +2730,20 @@ static void qf_fill_buffer(qf_info_T *qi, buf_T *buf, qfline_T *old_last) check_lnums(TRUE); if (old_last == NULL) { - /* Set the 'filetype' to "qf" each time after filling the buffer. This - * resembles reading a file into a buffer, it's more logical when using - * autocommands. */ + // Set the 'filetype' to "qf" each time after filling the buffer. This + // resembles reading a file into a buffer, it's more logical when using + // autocommands. set_option_value((char_u *)"ft", 0L, (char_u *)"qf", OPT_LOCAL); - curbuf->b_p_ma = FALSE; + curbuf->b_p_ma = false; - keep_filetype = TRUE; /* don't detect 'filetype' */ + keep_filetype = true; // don't detect 'filetype' apply_autocmds(EVENT_BUFREADPOST, (char_u *)"quickfix", NULL, - FALSE, curbuf); + false, curbuf); apply_autocmds(EVENT_BUFWINENTER, (char_u *)"quickfix", NULL, - FALSE, curbuf); - keep_filetype = FALSE; + false, curbuf); + keep_filetype = false; - /* make sure it will be redrawn */ + // make sure it will be redrawn redraw_curbuf_later(NOT_VALID); } @@ -3433,23 +3450,22 @@ void ex_vimgrep(exarg_T *eap) ++lnum) { col = 0; while (vim_regexec_multi(®match, curwin, buf, lnum, - col, NULL) > 0) { - ; + col, NULL) > 0) { if (qf_add_entry(qi, - NULL, /* dir */ - fname, - 0, - ml_get_buf(buf, - regmatch.startpos[0].lnum + lnum, FALSE), - regmatch.startpos[0].lnum + lnum, - regmatch.startpos[0].col + 1, - FALSE, /* vis_col */ - NULL, /* search pattern */ - 0, /* nr */ - 0, /* type */ - TRUE /* valid */ - ) == FAIL) { - got_int = TRUE; + NULL, // dir + fname, + 0, + ml_get_buf(buf, + regmatch.startpos[0].lnum + lnum, false), + regmatch.startpos[0].lnum + lnum, + regmatch.startpos[0].col + 1, + false, // vis_col + NULL, // search pattern + 0, // nr + 0, // type + true) // valid + == FAIL) { + got_int = true; break; } found_match = TRUE; @@ -3831,10 +3847,10 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) qi = ll_get_or_alloc_list(wp); } - if (action == ' ' || qi->qf_curlist == qi->qf_listcount) - /* make place for a new list */ + if (action == ' ' || qi->qf_curlist == qi->qf_listcount) { + // make place for a new list qf_new_list(qi, title); - else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) { + } else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0) { // Adding to existing list, use last entry. old_last = qi->qf_lists[qi->qf_curlist].qf_last; } else if (action == 'r') { @@ -3902,11 +3918,12 @@ int set_errorlist(win_T *wp, list_T *list, int action, char_u *title) } } - if (qi->qf_lists[qi->qf_curlist].qf_index == 0) - /* no valid entry */ - qi->qf_lists[qi->qf_curlist].qf_nonevalid = TRUE; - else - qi->qf_lists[qi->qf_curlist].qf_nonevalid = FALSE; + if (qi->qf_lists[qi->qf_curlist].qf_index == 0) { + // no valid entry + qi->qf_lists[qi->qf_curlist].qf_nonevalid = true; + } else { + qi->qf_lists[qi->qf_curlist].qf_nonevalid = false; + } if (action != 'a') { qi->qf_lists[qi->qf_curlist].qf_ptr = qi->qf_lists[qi->qf_curlist].qf_start; if (qi->qf_lists[qi->qf_curlist].qf_count > 0) { @@ -4123,22 +4140,23 @@ void ex_helpgrep(exarg_T *eap) line[--l] = NUL; if (qf_add_entry(qi, - NULL, /* dir */ - fnames[fi], - 0, - line, - lnum, - (int)(regmatch.startp[0] - line) - + 1, /* col */ - FALSE, /* vis_col */ - NULL, /* search pattern */ - 0, /* nr */ - 1, /* type */ - TRUE /* valid */ - ) == FAIL) { - got_int = TRUE; - if (line != IObuff) + NULL, // dir + fnames[fi], + 0, + line, + lnum, + (int)(regmatch.startp[0] - line) + + 1, // col + false, // vis_col + NULL, // search pattern + 0, // nr + 1, // type + true) // valid + == FAIL) { + got_int = true; + if (line != IObuff) { xfree(line); + } break; } } -- cgit