From da51dc9cf202772f60bd2da975dbef257bd9237c Mon Sep 17 00:00:00 2001 From: Eliseo Martínez Date: Mon, 12 May 2014 02:25:17 +0200 Subject: Introduce nvim namespace: Move files. Move files from src/ to src/nvim/. - src/nvim/ becomes the new root dir for nvim executable sources. - src/libnvim/ is planned to become root dir of the neovim library. --- src/nvim/testdir/test49.vim | 9852 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 9852 insertions(+) create mode 100644 src/nvim/testdir/test49.vim (limited to 'src/nvim/testdir/test49.vim') diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim new file mode 100644 index 0000000000..21c2a0c582 --- /dev/null +++ b/src/nvim/testdir/test49.vim @@ -0,0 +1,9852 @@ +" Vim script language tests +" Author: Servatius Brandt +" Last Change: 2013 Jun 06 + +"------------------------------------------------------------------------------- +" Test environment {{{1 +"------------------------------------------------------------------------------- + + +" Adding new tests easily. {{{2 +" +" Writing new tests is eased considerably with the following functions and +" abbreviations (see "Commands for recording the execution path", "Automatic +" argument generation"). +" +" To get the abbreviations, execute the command +" +" :let test49_set_env = 1 | source test49.vim +" +" To get them always (from src/testdir), put a line +" +" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim +" +" into the local .vimrc file in the src/testdir directory. +" +if exists("test49_set_env") && test49_set_env + + " Automatic argument generation for the test environment commands. + + function! Xsum() + let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "") + " Evaluate arithmetic expression. + if addend != "" + exec "let g:Xsum = g:Xsum + " . addend + endif + endfunction + + function! Xcheck() + let g:Xsum=0 + ?XpathINIT?,.call Xsum() + exec "norm A " + return g:Xsum + endfunction + + iab Xcheck Xcheck=Xcheck()x + + function! Xcomment(num) + let str = "" + let tabwidth = &sts ? &sts : &ts + let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth + while tabs > 0 + let str = str . "\t" + let tabs = tabs - 1 + endwhile + let str = str . '" X:' + return str + endfunction + + function! Xloop() + let back = line(".") . "|norm" . virtcol(".") . "|" + norm 0 + let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW") + exec back + let theline = getline(last) + if theline =~ 'X\(loop\|path\)INIT' + let num = 1 + else + let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "") + endif + ?X\(loop\|path\)INIT? + \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/ + exec back + exec "norm a " + return num . Xcomment(strlen(num)) + endfunction + + iab Xloop Xloop=Xloop()x + + function! Xpath(loopinit) + let back = line(".") . "|norm" . virtcol(".") . "|" + norm 0 + let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW") + exec back + let theline = getline(last) + if theline =~ 'XpathINIT' + let num = 1 + elseif theline =~ 'Xpath\>' + let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "") + else + let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*' + let num = substitute(theline, pattern, '\1', "") + let factor = substitute(theline, pattern, '\2', "") + " The "x" from the "Xpath" iab and the character triggering its + " expansion are in the input buffer. Save and clear typeahead so + " that it is not read away by the call to "input()" below. Restore + " afterwards. + call inputsave() + let loops = input("Number of iterations in previous loop? ") + call inputrestore() + while (loops > 0) + let num = num * factor + let loops = loops - 1 + endwhile + endif + exec "norm a " + if a:loopinit + return num . " 1" + endif + return num . Xcomment(strlen(num)) + endfunction + + iab Xpath Xpath=Xpath(0)x + iab XloopINIT XloopINIT=Xpath(1)x + + " Also useful (see ExtraVim below): + aug ExtraVim + au! + au BufEnter syn region ExtraVim + \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+ + \ transparent keepend + au BufEnter syn match ExtraComment /^"/ + \ contained containedin=ExtraVim + au BufEnter hi link ExtraComment vimComment + aug END + + aug Xpath + au BufEnter syn keyword Xpath + \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout + au BufEnter hi link Xpath Special + aug END + + do BufEnter + + " Do not execute the tests when sourcing this file for getting the functions + " and abbreviations above, which are intended for easily adding new test + " cases; they are not needed for test execution. Unlet the variable + " controlling this so that an explicit ":source" command for this file will + " execute the tests. + unlet test49_set_env + finish + +endif + + +" Commands for recording the execution path. {{{2 +" +" The Xpath/Xloop commands can be used for computing the eXecution path by +" adding (different) powers of 2 from those script lines, for which the +" execution should be checked. Xloop provides different addends for each +" execution of a loop. Permitted values are 2^0 to 2^30, so that 31 execution +" points (multiply counted inside loops) can be tested. +" +" Note that the arguments of the following commands can be generated +" automatically, see below. +" +" Usage: {{{3 +" +" - Use XpathINIT at the beginning of the test. +" +" - Use Xpath to check if a line is executed. +" Argument: power of 2 (decimal). +" +" - To check multiple execution of loops use Xloop for automatically +" computing Xpath values: +" +" - Use XloopINIT before the loop. +" Two arguments: +" - the first Xpath value (power of 2) to be used (Xnext), +" - factor for computing a new Xnext value when reexecuting a loop +" (by a ":continue" or ":endwhile"); this should be 2^n where +" n is the number of Xloop commands inside the loop. +" If XloopINIT! is used, the first execution of XloopNEXT is +" a no-operation. +" +" - Use Xloop inside the loop: +" One argument: +" The argument and the Xnext value are multiplied to build the +" next Xpath value. No new Xnext value is prepared. The argument +" should be 2^(n-1) for the nth Xloop command inside the loop. +" If the loop has only one Xloop command, the argument can be +" ommitted (default: 1). +" +" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new +" Xnext value for the next execution of the loop by multiplying the old +" one with the factor specified in the XloopINIT command. No Argument. +" Alternatively, when XloopINIT! is used, a single XloopNEXT at the +" beginning of the loop can be used. +" +" Nested loops are not supported. +" +" - Use Xcheck at end of each test. It prints the test number, the expected +" execution path value, the test result ("OK" or "FAIL"), and, if the tests +" fails, the actual execution path. +" One argument: +" Expected Xpath/Xloop sum for the correct execution path. +" In order that this value can be computed automatically, do the +" following: For each line in the test with an Xpath and Xloop +" command, add a comment starting with "X:" and specifying an +" expression that evaluates to the value contributed by this line to +" the correct execution path. (For copying an Xpath argument of at +" least two digits into the comment, press .) At the end of the +" test, just type "Xcheck" and press . +" +" - In order to add additional information to the test output file, use the +" Xout command. Argument(s) like ":echo". +" +" Automatic argument generation: {{{3 +" +" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be +" generated automatically, so that new tests can easily be written without +" mental arithmetic. The Xcheck argument is computed from the "X:" comments +" of the preceding Xpath and Xloop commands. See the commands and +" abbreviations at the beginning of this file. +" +" Implementation: {{{3 +" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout. +" +" The variants for existing g:ExtraVimResult are needed when executing a script +" in an extra Vim process, see ExtraVim below. + +" EXTRA_VIM_START - do not change or remove this line. + +com! XpathINIT let g:Xpath = 0 + +if exists("g:ExtraVimResult") + com! -count -bar Xpath exec "!echo >>" . g:ExtraVimResult +else + com! -count -bar Xpath let g:Xpath = g:Xpath + +endif + +com! -count -nargs=1 -bang + \ XloopINIT let g:Xnext = | + \ let g:Xfactor = | + \ let g:Xskip = strlen("") + +if exists("g:ExtraVimResult") + com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * ) . " >>" . + \ g:ExtraVimResult +else + com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * +endif + +com! XloopNEXT let g:Xnext = g:Xnext * + \ (g:Xskip ? 1 : g:Xfactor) | + \ let g:Xskip = 0 + +let @r = "" +let Xtest = 1 +com! -count Xcheck let Xresult = "*** Test " . + \ (Xtest<10?" ":Xtest<100?" ":"") . + \ Xtest . ": " . ( + \ (Xpath==) ? "OK (".Xpath.")" : + \ "FAIL (".Xpath." instead of )" + \ ) | + \ let @R = Xresult . "\n" | + \ echo Xresult | + \ let Xtest = Xtest + 1 + +if exists("g:ExtraVimResult") + com! -nargs=+ Xoutq exec "!echo @R:'" . + \ substitute(substitute(, + \ "'", '&\\&&', "g"), "\n", "@NL@", "g") + \ . "' >>" . g:ExtraVimResult +else + com! -nargs=+ Xoutq let @R = "--- Test " . + \ (g:Xtest<10?" ":g:Xtest<100?" ":"") . + \ g:Xtest . ": " . substitute(, + \ "\n", "&\t ", "g") . "\n" +endif +com! -nargs=+ Xout exec 'Xoutq' + +" Switch off storing of lines for undoing changes. Speeds things up a little. +set undolevels=-1 + +" EXTRA_VIM_STOP - do not change or remove this line. + + +" ExtraVim() - Run a script file in an extra Vim process. {{{2 +" +" This is useful for testing immediate abortion of the script processing due to +" an error in a command dynamically enclosed by a :try/:tryend region or when an +" exception is thrown but not caught or when an interrupt occurs. It can also +" be used for testing :finish. +" +" An interrupt location can be specified by an "INTERRUPT" comment. A number +" telling how often this location is reached (in a loop or in several function +" calls) should be specified as argument. When missing, once per script +" invocation or function call is assumed. INTERRUPT locations are tested by +" setting a breakpoint in that line and using the ">quit" debug command when +" the breakpoint is reached. A function for which an INTERRUPT location is +" specified must be defined before calling it (or executing it as a script by +" using ExecAsScript below). +" +" This function is only called in normal modus ("g:ExtraVimResult" undefined). +" +" Tests to be executed as an extra script should be written as follows: +" +" column 1 column 1 +" | | +" v v +" +" XpathINIT XpathINIT +" if ExtraVim() if ExtraVim() +" ... " ... +" ... " ... +" endif endif +" Xcheck Xcheck +" +" Double quotes in column 1 are removed before the script is executed. +" They should be used if the test has unbalanced conditionals (:if/:endif, +" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The +" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual. +" +" A file name may be specified as argument. All messages of the extra Vim +" process are then redirected to the file. An existing file is overwritten. +" +let ExtraVimCount = 0 +let ExtraVimBase = expand("") +let ExtraVimTestEnv = "" +" +function! ExtraVim(...) + " Count how often this function is called. + let g:ExtraVimCount = g:ExtraVimCount + 1 + + " Disable folds to prevent that the ranges in the ":write" commands below + " are extended up to the end of a closed fold. This also speeds things up + " considerably. + set nofoldenable + + " Open a buffer for this test script and copy the test environment to + " a temporary file. Take account of parts relevant for the extra script + " execution only. + let current_buffnr = bufnr("%") + execute "view +1" g:ExtraVimBase + if g:ExtraVimCount == 1 + let g:ExtraVimTestEnv = tempname() + execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w" + \ g:ExtraVimTestEnv "|']+" + execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" + \ g:ExtraVimTestEnv "|']+" + execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" + \ g:ExtraVimTestEnv "|']+" + execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>" + \ g:ExtraVimTestEnv "|']+" + endif + + " Start the extra Vim script with a ":source" command for the test + " environment. The source line number where the extra script will be + " appended, needs to be passed as variable "ExtraVimBegin" to the script. + let extra_script = tempname() + exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script + let extra_begin = 1 + + " Starting behind the test environment, skip over the first g:ExtraVimCount + " occurrences of "if ExtraVim()" and copy the following lines up to the + " matching "endif" to the extra Vim script. + execute "/E" . "ND_OF_TEST_ENVIRONMENT/" + exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n" + execute ".,/^endif/-write >>" . extra_script + + " Open a buffer for the extra Vim script, delete all ^", and write the + " script if was actually modified. + execute "edit +" . (extra_begin + 1) extra_script + ,$s/^"//e + update + + " Count the INTERRUPTs and build the breakpoint and quit commands. + let breakpoints = "" + let debug_quits = "" + let in_func = 0 + exec extra_begin + while search( + \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|' + \ . '^\s*\\\|^\s*endf\%[unction]\>\|' + \ . '\%(^\s*fu\%[nction]!\=\s*\)\@ 0 + let theline = getline(".") + if theline =~ '^\s*fu' + " Function definition. + let in_func = 1 + let func_start = line(".") + let func_name = substitute(theline, + \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "") + elseif theline =~ '^\s*endf' + " End of function definition. + let in_func = 0 + else + let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)', + \ '\1', "") + if finding =~ '^"\s*INTERRUPT\h\@!' + " Interrupt comment. Compose as many quit commands as + " specified. + let cnt = substitute(finding, + \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "") + let quits = "" + while cnt > 0 + " Use "\r" rather than "\n" to separate the quit commands. + " "\r" is not interpreted as command separator by the ":!" + " command below but works to separate commands in the + " external vim. + let quits = quits . "q\r" + let cnt = cnt - 1 + endwhile + if in_func + " Add the function breakpoint and note the number of quits + " to be used, if specified, or one for every call else. + let breakpoints = breakpoints . " -c 'breakadd func " . + \ (line(".") - func_start) . " " . + \ func_name . "'" + if quits != "" + let debug_quits = debug_quits . quits + elseif !exists("quits{func_name}") + let quits{func_name} = "q\r" + else + let quits{func_name} = quits{func_name} . "q\r" + endif + else + " Add the file breakpoint and the quits to be used for it. + let breakpoints = breakpoints . " -c 'breakadd file " . + \ line(".") . " " . extra_script . "'" + if quits == "" + let quits = "q\r" + endif + let debug_quits = debug_quits . quits + endif + else + " Add the quits to be used for calling the function or executing + " it as script file. + if finding =~ '^ExecAsScript' + " Sourcing function as script. + let finding = substitute(finding, + \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "") + else + " Function call. + let finding = substitute(finding, + \ '^\(\%(\u\|s:\)\w*\).*', '\1', "") + endif + if exists("quits{finding}") + let debug_quits = debug_quits . quits{finding} + endif + endif + endif + endwhile + + " Close the buffer for the script and create an (empty) resultfile. + bwipeout + let resultfile = tempname() + exec "!>" . resultfile + + " Run the script in an extra vim. Switch to extra modus by passing the + " resultfile in ExtraVimResult. Redirect messages to the file specified as + " argument if any. Use ":debuggreedy" so that the commands provided on the + " pipe are consumed at the debug prompt. Use "-N" to enable command-line + " continuation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid + " messing up the user's viminfo file. + let redirect = a:0 ? + \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : "" + exec "!echo '" . debug_quits . "q' | ../../build/bin/nvim -u NONE -N -Xes" . redirect . + \ " -c 'debuggreedy|set viminfo+=nviminfo'" . + \ " -c 'let ExtraVimBegin = " . extra_begin . "'" . + \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints . + \ " -S " . extra_script + + " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout + " information provided by the extra Vim process to the test output. + let sum = 0 + exec "edit" resultfile + let line = 1 + while line <= line("$") + let theline = getline(line) + if theline =~ '^@R:' + exec 'Xout "' . substitute(substitute( + \ escape(escape(theline, '"'), '\"'), + \ '^@R:', '', ""), '@NL@', "\n", "g") . '"' + else + let sum = sum + getline(line) + endif + let line = line + 1 + endwhile + bwipeout + let g:Xpath = g:Xpath + sum + + " Delete the extra script and the resultfile. + call delete(extra_script) + call delete(resultfile) + + " Switch back to the buffer that was active when this function was entered. + exec "buffer" current_buffnr + + " Return 0. This protects extra scripts from being run in the main Vim + " process. + return 0 +endfunction + + +" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2 +" +" Evaluates v:throwpoint and returns the throwpoint relative to the beginning of +" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin. +" +" EXTRA_VIM_START - do not change or remove this line. +function! ExtraVimThrowpoint() + if !exists("g:ExtraVimBegin") + Xout "ExtraVimThrowpoint() used outside ExtraVim() script." + return v:throwpoint + endif + + if v:throwpoint =~ '^function\>' + return v:throwpoint + endif + + return "line " . + \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) . + \ " of ExtraVim() script" +endfunction +" EXTRA_VIM_STOP - do not change or remove this line. + + +" MakeScript() - Make a script file from a function. {{{2 +" +" Create a script that consists of the body of the function a:funcname. +" Replace any ":return" by a ":finish", any argument variable by a global +" variable, and and every ":call" by a ":source" for the next following argument +" in the variable argument list. This function is useful if similar tests are +" to be made for a ":return" from a function call or a ":finish" in a script +" file. +" +" In order to execute a function specifying an INTERRUPT location (see ExtraVim) +" as a script file, use ExecAsScript below. +" +" EXTRA_VIM_START - do not change or remove this line. +function! MakeScript(funcname, ...) + let script = tempname() + execute "redir! >" . script + execute "function" a:funcname + redir END + execute "edit" script + " Delete the "function" and the "endfunction" lines. Do not include the + " word "function" in the pattern since it might be translated if LANG is + " set. When MakeScript() is being debugged, this deletes also the debugging + " output of its line 3 and 4. + exec '1,/.*' . a:funcname . '(.*)/d' + /^\d*\s*endfunction\>/,$d + %s/^\d*//e + %s/return/finish/e + %s/\ 0 + let cnt = cnt + 1 + s/\" . bplist + breaklist + redir END + execute "edit" bplist + " Get the line number from the function breakpoint. Works also when + " LANG is set. + execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d' + %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e + let cnt = 0 + while cnt < line("$") + let cnt = cnt + 1 + if getline(cnt) != "" + execute "breakadd file" getline(cnt) script + endif + endwhile + bwipeout! + call delete(bplist) + endif + + " Source and delete the script. + exec "source" script + call delete(script) +endfunction + +com! -nargs=1 -bar ExecAsScript call ExecAsScript() +" EXTRA_VIM_STOP - do not change or remove this line. + + +" END_OF_TEST_ENVIRONMENT - do not change or remove this line. + + +"------------------------------------------------------------------------------- +" Test 1: :endwhile in function {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :return to prevent an endless loop, and make +" this test first to get a meaningful result on an error before other +" tests will hang. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + Xpath 1 " X: 1 + let first = 1 + XloopINIT 2 8 + while 1 + Xloop 1 " X: 2 + 0 * 16 + if first + Xloop 2 " X: 4 + 0 * 32 + let first = 0 + XloopNEXT + break + else + Xloop 4 " X: 0 + 0 * 64 + return + endif + endwhile +endfunction + +call F() +Xpath 128 " X: 128 + +function! G() + Xpath 256 " X: 256 + 0 * 2048 + let first = 1 + XloopINIT 512 8 + while 1 + Xloop 1 " X: 512 + 0 * 4096 + if first + Xloop 2 " X: 1024 + 0 * 8192 + let first = 0 + XloopNEXT + break + else + Xloop 4 " X: 0 + 0 * 16384 + return + endif + if 1 " unmatched :if + endwhile +endfunction + +call G() +Xpath 32768 " X: 32768 + +Xcheck 34695 + +" Leave F and G for execution as scripts in the next test. + + +"------------------------------------------------------------------------------- +" Test 2: :endwhile in script {{{1 +" +" Detect if a broken loop is (incorrectly) reactivated by the +" :endwhile. Use a :finish to prevent an endless loop, and place +" this test before others that might hang to get a meaningful result +" on an error. +" +" This test executes the bodies of the functions F and G from the +" previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +XpathINIT + +ExecAsScript F " X: 1 + 2 + 4 +Xpath 128 " X: 128 + +ExecAsScript G " X: 256 + 512 + 1024 +Xpath 32768 " X: 32768 + +unlet first +delfunction F +delfunction G + +Xcheck 34695 + + +"------------------------------------------------------------------------------- +" Test 3: :if, :elseif, :while, :continue, :break {{{1 +"------------------------------------------------------------------------------- + +XpathINIT +if 1 + Xpath 1 " X: 1 + let loops = 3 + XloopINIT 2 512 + while loops > -1 " main loop: loops == 3, 2, 1 (which breaks) + if loops <= 0 + let break_err = 1 + let loops = -1 + else " 3: 2: 1: + Xloop 1 " X: 2 + 2*512 + 2*512*512 + endif + if (loops == 2) + while loops == 2 " dummy loop + Xloop 2 " X: 4*512 + let loops = loops - 1 + continue " stop dummy loop + Xloop 4 " X: 0 + endwhile + XloopNEXT + continue " continue main loop + Xloop 8 " X: 0 + elseif (loops == 1) + let p = 1 + while p " dummy loop + Xloop 16 " X: 32*512*512 + let p = 0 + break " break dummy loop + Xloop 32 " X: 0 + endwhile + Xloop 64 " X: 128*512*512 + unlet p + break " break main loop + Xloop 128 " X: 0 + endif + if (loops > 0) + Xloop 256 " X: 512 + endif + while loops == 3 " dummy loop + let loops = loops - 1 + endwhile " end dummy loop + XloopNEXT + endwhile " end main loop + Xpath 268435456 " X: 1024*512*512 +else + Xpath 536870912 " X: 0 +endif +Xpath 1073741824 " X: 4096*512*512 +if exists("break_err") + " The Xpath command does not accept 2^31 (negative); add explicitly: + let Xpath = Xpath + 2147483648 " X: 0 + unlet break_err +endif + +unlet loops + +Xcheck 1384648195 + + +"------------------------------------------------------------------------------- +" Test 4: :return {{{1 +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + if 1 + Xpath 1 " X: 1 + let loops = 3 + XloopINIT 2 16 + while loops > 0 " 3: 2: 1: + Xloop 1 " X: 2 + 2*16 + 0*16*16 + if (loops == 2) + Xloop 2 " X: 4*16 + return + Xloop 4 " X: 0 + endif + Xloop 8 " X: 16 + let loops = loops - 1 + XloopNEXT + endwhile + Xpath 8192 " X: 0 + else + Xpath 16384 " X: 0 + endif +endfunction + +call F() +Xpath 32768 " X: 8*16*16*16 + +Xcheck 32883 + +" Leave F for execution as a script in the next test. + + +"------------------------------------------------------------------------------- +" Test 5: :finish {{{1 +" +" This test executes the body of the function F from the previous test +" as a script file (:return replaced by :finish). +"------------------------------------------------------------------------------- + +XpathINIT + +ExecAsScript F " X: 1 + 2 + 2*16 + 4*16 + 16 +Xpath 32768 " X: 32768 + +unlet loops +delfunction F + +Xcheck 32883 + + +"------------------------------------------------------------------------------- +" Test 6: Defining functions in :while loops {{{1 +" +" Functions can be defined inside other functions. An inner function +" gets defined when the outer function is executed. Functions may +" also be defined inside while loops. Expressions in braces for +" defining the function name are allowed. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + + " The command CALL collects the argument of all its invocations in "calls" + " when used from a function (that is, when the global variable "calls" needs + " the "g:" prefix). This is to check that the function code is skipped when + " the function is defined. For inner functions, do so only if the outer + " function is not being executed. + " + let calls = "" + com! -nargs=1 CALL + \ if !exists("calls") && !exists("outer") | + \ let g:calls = g:calls . | + \ endif + + + XloopINIT! 1 16 + + let i = 0 + while i < 3 + + XloopNEXT + let i = i + 1 + + if i == 1 + Xloop 1 " X: 1 + function! F1(arg) + CALL a:arg + let outer = 1 + + XloopINIT! 4096 4 + let j = 0 + while j < 1 + XloopNEXT + Xloop 1 " X: 4096 + let j = j + 1 + function! G1(arg) + CALL a:arg + endfunction + Xloop 2 " X: 8192 + endwhile + endfunction + Xloop 2 " X: 2 + + continue + endif + + Xloop 4 " X: 4 * (16 + 256) + function! F{i}(i, arg) + CALL a:arg + let outer = 1 + + XloopINIT! 16384 4 + if a:i == 3 + XloopNEXT + XloopNEXT + XloopNEXT + endif + let k = 0 + while k < 3 + XloopNEXT + Xloop 1 " X: 16384*(1+4+16+64+256+1024) + let k = k + 1 + function! G{a:i}{k}(arg) + CALL a:arg + endfunction + Xloop 2 " X: 32768*(1+4+16+64+256+1024) + endwhile + endfunction + Xloop 8 " X: 8 * (16 + 256) + + endwhile + + if exists("*G1") + Xpath 67108864 " X: 0 + endif + if exists("*F1") + call F1("F1") + if exists("*G1") + call G1("G1") + endif + endif + + if exists("G21") || exists("G21") || exists("G21") + Xpath 134217728 " X: 0 + endif + if exists("*F2") + call F2(2, "F2") + if exists("*G21") + call G21("G21") + endif + if exists("*G22") + call G22("G22") + endif + if exists("*G23") + call G23("G23") + endif + endif + + if exists("G31") || exists("G31") || exists("G31") + Xpath 268435456 " X: 0 + endif + if exists("*F3") + call F3(3, "F3") + if exists("*G31") + call G31("G31") + endif + if exists("*G32") + call G32("G32") + endif + if exists("*G33") + call G33("G33") + endif + endif + + Xpath 536870912 " X: 536870912 + + if calls != "F1G1F2G21G22G23F3G31G32G33" + Xpath 1073741824 " X: 0 + Xout "calls is" calls + endif + + delfunction F1 + delfunction G1 + delfunction F2 + delfunction G21 + delfunction G22 + delfunction G23 + delfunction G31 + delfunction G32 + delfunction G33 + +endif + +Xcheck 603978947 + + +"------------------------------------------------------------------------------- +" Test 7: Continuing on errors outside functions {{{1 +" +" On an error outside a function, the script processing continues +" at the line following the outermost :endif or :endwhile. When not +" inside an :if or :while, the script processing continues at the next +" line. +"------------------------------------------------------------------------------- + +XpathINIT + +if 1 + Xpath 1 " X: 1 + while 1 + Xpath 2 " X: 2 + asdf + Xpath 4 " X: 0 + break + endwhile | Xpath 8 " X: 0 + Xpath 16 " X: 0 +endif | Xpath 32 " X: 0 +Xpath 64 " X: 64 + +while 1 + Xpath 128 " X: 128 + if 1 + Xpath 256 " X: 256 + asdf + Xpath 512 " X: 0 + endif | Xpath 1024 " X: 0 + Xpath 2048 " X: 0 + break +endwhile | Xpath 4096 " X: 0 +Xpath 8192 " X: 8192 + +asdf +Xpath 16384 " X: 16384 + +asdf | Xpath 32768 " X: 0 +Xpath 65536 " X: 65536 + +Xcheck 90563 + + +"------------------------------------------------------------------------------- +" Test 8: Aborting and continuing on errors inside functions {{{1 +" +" On an error inside a function without the "abort" attribute, the +" script processing continues at the next line (unless the error was +" in a :return command). On an error inside a function with the +" "abort" attribute, the function is aborted and the script processing +" continues after the function call; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + if 1 + Xpath 1 " X: 1 + while 1 + Xpath 2 " X: 2 + asdf + Xpath 4 " X: 4 + asdf | Xpath 8 " X: 0 + Xpath 16 " X: 16 + break + endwhile + Xpath 32 " X: 32 + endif | Xpath 64 " X: 64 + Xpath 128 " X: 128 + + while 1 + Xpath 256 " X: 256 + if 1 + Xpath 512 " X: 512 + asdf + Xpath 1024 " X: 1024 + asdf | Xpath 2048 " X: 0 + Xpath 4096 " X: 4096 + endif + Xpath 8192 " X: 8192 + break + endwhile | Xpath 16384 " X: 16384 + Xpath 32768 " X: 32768 + + return novar " returns (default return value 0) + Xpath 65536 " X: 0 + return 1 " not reached +endfunction + +function! G() abort + if 1 + Xpath 131072 " X: 131072 + while 1 + Xpath 262144 " X: 262144 + asdf " returns -1 + Xpath 524288 " X: 0 + break + endwhile + Xpath 1048576 " X: 0 + endif | Xpath 2097152 " X: 0 + Xpath Xpath 4194304 " X: 0 + + return -4 " not reached +endfunction + +function! H() abort + while 1 + Xpath 8388608 " X: 8388608 + if 1 + Xpath 16777216 " X: 16777216 + asdf " returns -1 + Xpath 33554432 " X: 0 + endif + Xpath 67108864 " X: 0 + break + endwhile | Xpath 134217728 " X: 0 + Xpath 268435456 " X: 0 + + return -4 " not reached +endfunction + +" Aborted functions (G and H) return -1. +let sum = (F() + 1) - 4*G() - 8*H() +Xpath 536870912 " X: 536870912 +if sum != 13 + Xpath 1073741824 " X: 0 + Xout "sum is" sum +endif + +unlet sum +delfunction F +delfunction G +delfunction H + +Xcheck 562493431 + + +"------------------------------------------------------------------------------- +" Test 9: Continuing after aborted functions {{{1 +" +" When a function with the "abort" attribute is aborted due to an +" error, the next function back in the call hierarchy without an +" "abort" attribute continues; the value -1 is returned then. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() abort + Xpath 1 " X: 1 + let result = G() " not aborted + Xpath 2 " X: 2 + if result != 2 + Xpath 4 " X: 0 + endif + return 1 +endfunction + +function! G() " no abort attribute + Xpath 8 " X: 8 + if H() != -1 " aborted + Xpath 16 " X: 0 + endif + Xpath 32 " X: 32 + return 2 +endfunction + +function! H() abort + Xpath 64 " X: 64 + call I() " aborted + Xpath 128 " X: 0 + return 4 +endfunction + +function! I() abort + Xpath 256 " X: 256 + asdf " error + Xpath 512 " X: 0 + return 8 +endfunction + +if F() != 1 + Xpath 1024 " X: 0 +endif + +delfunction F +delfunction G +delfunction H +delfunction I + +Xcheck 363 + + +"------------------------------------------------------------------------------- +" Test 10: :if, :elseif, :while argument parsing {{{1 +" +" A '"' or '|' in an argument expression must not be mixed up with +" a comment or a next command after a bar. Parsing errors should +" be recognized. +"------------------------------------------------------------------------------- + +XpathINIT + +function! MSG(enr, emsg) + let english = v:lang == "C" || v:lang =~ '^[Ee]n' + if a:enr == "" + Xout "TODO: Add message number for:" a:emsg + let v:errmsg = ":" . v:errmsg + endif + let match = 1 + if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) + let match = 0 + if v:errmsg == "" + Xout "Message missing." + else + let v:errmsg = escape(v:errmsg, '"') + Xout "Unexpected message:" v:errmsg + endif + endif + return match +endfunction + +if 1 || strlen("\"") | Xpath 1 " X: 1 + Xpath 2 " X: 2 +endif +Xpath 4 " X: 4 + +if 0 +elseif 1 || strlen("\"") | Xpath 8 " X: 8 + Xpath 16 " X: 16 +endif +Xpath 32 " X: 32 + +while 1 || strlen("\"") | Xpath 64 " X: 64 + Xpath 128 " X: 128 + break +endwhile +Xpath 256 " X: 256 + +let v:errmsg = "" +if 1 ||| strlen("\"") | Xpath 512 " X: 0 + Xpath 1024 " X: 0 +endif +Xpath 2048 " X: 2048 +if !MSG('E15', "Invalid expression") + Xpath 4096 " X: 0 +endif + +let v:errmsg = "" +if 0 +elseif 1 ||| strlen("\"") | Xpath 8192 " X: 0 + Xpath 16384 " X: 0 +endif +Xpath 32768 " X: 32768 +if !MSG('E15', "Invalid expression") + Xpath 65536 " X: 0 +endif + +let v:errmsg = "" +while 1 ||| strlen("\"") | Xpath 131072 " X: 0 + Xpath 262144 " X: 0 + break +endwhile +Xpath 524288 " X: 524288 +if !MSG('E15', "Invalid expression") + Xpath 1048576 " X: 0 +endif + +delfunction MSG + +Xcheck 559615 + + +"------------------------------------------------------------------------------- +" Test 11: :if, :elseif, :while argument evaluation after abort {{{1 +" +" When code is skipped over due to an error, the boolean argument to +" an :if, :elseif, or :while must not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +let calls = 0 + +function! P(num) + let g:calls = g:calls + a:num " side effect on call + return 0 +endfunction + +if 1 + Xpath 1 " X: 1 + asdf " error + Xpath 2 " X: 0 + if P(1) " should not be called + Xpath 4 " X: 0 + elseif !P(2) " should not be called + Xpath 8 " X: 0 + else + Xpath 16 " X: 0 + endif + Xpath 32 " X: 0 + while P(4) " should not be called + Xpath 64 " X: 0 + endwhile + Xpath 128 " X: 0 +endif + +if calls % 2 + Xpath 256 " X: 0 +endif +if (calls/2) % 2 + Xpath 512 " X: 0 +endif +if (calls/4) % 2 + Xpath 1024 " X: 0 +endif +Xpath 2048 " X: 2048 + +unlet calls +delfunction P + +Xcheck 2049 + + +"------------------------------------------------------------------------------- +" Test 12: Expressions in braces in skipped code {{{1 +" +" In code skipped over due to an error or inactive conditional, +" an expression in braces as part of a variable or function name +" should not be evaluated. +"------------------------------------------------------------------------------- + +XpathINIT + +XloopINIT 1 8 + +function! NULL() + Xloop 1 " X: 0 + return 0 +endfunction + +function! ZERO() + Xloop 2 " X: 0 + return 0 +endfunction + +function! F0() + Xloop 4 " X: 0 +endfunction + +function! F1(arg) + Xpath 4096 " X: 0 +endfunction + +let V0 = 1 + +Xpath 8192 " X: 8192 +echo 0 ? F{NULL() + V{ZERO()}}() : 1 +XloopNEXT + +Xpath 16384 " X: 16384 +if 0 + Xpath 32768 " X: 0 + call F{NULL() + V{ZERO()}}() +endif +XloopNEXT + +Xpath 65536 " X: 65536 +if 1 + asdf " error + Xpath 131072 " X: 0 + call F1(F{NULL() + V{ZERO()}}()) +endif +XloopNEXT + +Xpath 262144 " X: 262144 +if 1 + asdf " error + Xpath 524288 " X: 0 + call F{NULL() + V{ZERO()}}() +endif + +Xcheck 352256 + + +"------------------------------------------------------------------------------- +" Test 13: Failure in argument evaluation for :while {{{1 +" +" A failure in the expression evaluation for the condition of a :while +" causes the whole :while loop until the matching :endwhile being +" ignored. Continuation is at the next following line. +"------------------------------------------------------------------------------- + +XpathINIT + +Xpath 1 " X: 1 +while asdf + Xpath 2 " X: 0 + while 1 + Xpath 4 " X: 0 + break + endwhile + Xpath 8 " X: 0 + break +endwhile +Xpath 16 " X: 16 + +while asdf | Xpath 32 | endwhile | Xpath 64 " X: 0 +Xpath 128 " X: 128 + +Xcheck 145 + + +"------------------------------------------------------------------------------- +" Test 14: Failure in argument evaluation for :if {{{1 +" +" A failure in the expression evaluation for the condition of an :if +" does not cause the corresponding :else or :endif being matched to +" a previous :if/:elseif. Neither of both branches of the failed :if +" are executed. +"------------------------------------------------------------------------------- + +XpathINIT +XloopINIT 1 256 + +function! F() + Xloop 1 " X: 1 + 256 * 1 + let x = 0 + if x " false + Xloop 2 " X: 0 + 256 * 0 + elseif !x " always true + Xloop 4 " X: 4 + 256 * 4 + let x = 1 + if g:boolvar " possibly undefined + Xloop 8 " X: 8 + 256 * 0 + else + Xloop 16 " X: 0 + 256 * 0 + endif + Xloop 32 " X: 32 + 256 * 32 + elseif x " never executed + Xloop 64 " X: 0 + 256 * 0 + endif + Xloop 128 " X: 128 + 256 * 128 +endfunction + +let boolvar = 1 +call F() + +XloopNEXT +unlet boolvar +call F() + +delfunction F + +Xcheck 42413 + + +"------------------------------------------------------------------------------- +" Test 15: Failure in argument evaluation for :if (bar) {{{1 +" +" Like previous test, except that the failing :if ... | ... | :endif +" is in a single line. +"------------------------------------------------------------------------------- + +XpathINIT +XloopINIT 1 256 + +function! F() + Xloop 1 " X: 1 + 256 * 1 + let x = 0 + if x " false + Xloop 2 " X: 0 + 256 * 0 + elseif !x " always true + Xloop 4 " X: 4 + 256 * 4 + let x = 1 + if g:boolvar | Xloop 8 | else | Xloop 16 | endif " X: 8 + Xloop 32 " X: 32 + 256 * 32 + elseif x " never executed + Xloop 64 " X: 0 + 256 * 0 + endif + Xloop 128 " X: 128 + 256 * 128 +endfunction + +let boolvar = 1 +call F() + +XloopNEXT +unlet boolvar +call F() + +delfunction F + +Xcheck 42413 + + +"------------------------------------------------------------------------------- +" Test 16: Double :else or :elseif after :else {{{1 +" +" Multiple :elses or an :elseif after an :else are forbidden. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() abort + if 0 + Xpath 1 " X: 0 + else + Xpath 2 " X: 2 + else " aborts function + Xpath 4 " X: 0 + endif +endfunction + +function! G() abort + if 0 + Xpath 8 " X: 0 + else + Xpath 16 " X: 16 + elseif 1 " aborts function + Xpath 32 " X: 0 + else + Xpath 64 " X: 0 + endif +endfunction + +function! H() abort + if 0 + Xpath 128 " X: 0 + elseif 0 + Xpath 256 " X: 0 + else + Xpath 512 " X: 512 + else " aborts function + Xpath 1024 " X: 0 + endif +endfunction + +function! I() abort + if 0 + Xpath 2048 " X: 0 + elseif 0 + Xpath 4096 " X: 0 + else + Xpath 8192 " X: 8192 + elseif 1 " aborts function + Xpath 16384 " X: 0 + else + Xpath 32768 " X: 0 + endif +endfunction + +call F() +call G() +call H() +call I() + +delfunction F +delfunction G +delfunction H +delfunction I + +Xcheck 8722 + + +"------------------------------------------------------------------------------- +" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1 +" +" The :while/:endwhile takes precedence in nesting over an unclosed +" :if or an unopened :endif. +"------------------------------------------------------------------------------- + +XpathINIT + +function! MSG(enr, emsg) + let english = v:lang == "C" || v:lang =~ '^[Ee]n' + if a:enr == "" + Xout "TODO: Add message number for:" a:emsg + let v:errmsg = ":" . v:errmsg + endif + let match = 1 + if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg) + let match = 0 + if v:errmsg == "" + Xout "Message missing." + else + let v:errmsg = escape(v:errmsg, '"') + Xout "Unexpected message:" v:errmsg + endif + endif + return match +endfunction + +let messages = "" + +" While loops inside a function are continued on error. +function! F() + let v:errmsg = "" + XloopINIT 1 16 + let loops = 3 + while loops > 0 + let loops = loops - 1 " 2: 1: 0: + Xloop 1 " X: 1 + 1*16 + 1*16*16 + if (loops == 1) + Xloop 2 " X: 2*16 + XloopNEXT + continue + elseif (loops == 0) + Xloop 4 " X: 4*16*16 + break + elseif 1 + Xloop 8 " X: 8 + XloopNEXT + " endif missing! + endwhile " :endwhile after :if 1 + Xpath 4096 " X: 16*16*16 + if MSG('E171', "Missing :endif") + let g:messages = g:messages . "A" + endif + + let v:errmsg = "" + XloopINIT! 8192 4 + let loops = 2 + while loops > 0 " 2: 1: + XloopNEXT + let loops = loops - 1 + Xloop 1 " X: 8192 + 8192*4 + if 0 + Xloop 2 " X: 0 + " endif missing + endwhile " :endwhile after :if 0 + Xpath 131072 " X: 8192*4*4 + if MSG('E171', "Missing :endif") + let g:messages = g:messages . "B" + endif + + let v:errmsg = "" + XloopINIT 262144 4 + let loops = 2 + while loops > 0 " 2: 1: + let loops = loops - 1 + Xloop 1 " X: 262144 + 262144 * 4 + " if missing! + endif " :endif without :if in while + Xloop 2 " X: 524288 + 524288 * 4 + XloopNEXT + endwhile + Xpath 4194304 " X: 262144*4*4 + if MSG('E580', ":endif without :if") + let g:messages = g:messages . "C" + endif +endfunction + +call F() + +" Error continuation outside a function is at the outermost :endwhile or :endif. +let v:errmsg = "" +XloopINIT! 8388608 4 +let loops = 2 +while loops > 0 " 2: 1: + XloopNEXT + let loops = loops - 1 + Xloop 1 " X: 8388608 + 0 * 4 + if 0 + Xloop 2 " X: 0 + " endif missing! Following :endwhile fails. +endwhile | Xpath 134217728 " X: 0 +Xpath 268435456 " X: 2*8388608*4*4 +if MSG('E171', "Missing :endif") + let messages = g:messages . "D" +endif + +if messages != "ABCD" + Xpath 536870912 " X: 0 + Xout "messages is" messages "instead of ABCD" +endif + +unlet loops messages +delfunction F +delfunction MSG + +Xcheck 285127993 + + +"------------------------------------------------------------------------------- +" Test 18: Interrupt (Ctrl-C pressed) {{{1 +" +" On an interrupt, the script processing is terminated immediately. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + if 1 + Xpath 1 " X: 1 + while 1 + Xpath 2 " X: 2 + if 1 + Xpath 4 " X: 4 + "INTERRUPT + Xpath 8 " X: 0 + break + finish + endif | Xpath 16 " X: 0 + Xpath 32 " X: 0 + endwhile | Xpath 64 " X: 0 + Xpath 128 " X: 0 + endif | Xpath 256 " X: 0 + Xpath 512 " X: 0 +endif + +if ExtraVim() + try + Xpath 1024 " X: 1024 + "INTERRUPT + Xpath 2048 " X: 0 + endtry | Xpath 4096 " X: 0 + Xpath 8192 " X: 0 +endif + +if ExtraVim() + function! F() + if 1 + Xpath 16384 " X: 16384 + while 1 + Xpath 32768 " X: 32768 + if 1 + Xpath 65536 " X: 65536 + "INTERRUPT + Xpath 131072 " X: 0 + break + return + endif | Xpath 262144 " X: 0 + Xpath Xpath 524288 " X: 0 + endwhile | Xpath 1048576 " X: 0 + Xpath Xpath 2097152 " X: 0 + endif | Xpath Xpath 4194304 " X: 0 + Xpath Xpath 8388608 " X: 0 + endfunction + + call F() | Xpath 16777216 " X: 0 + Xpath 33554432 " X: 0 +endif + +if ExtraVim() + function! G() + try + Xpath 67108864 " X: 67108864 + "INTERRUPT + Xpath 134217728 " X: 0 + endtry | Xpath 268435456 " X: 0 + Xpath 536870912 " X: 0 + endfunction + + call G() | Xpath 1073741824 " X: 0 + " The Xpath command does not accept 2^31 (negative); display explicitly: + exec "!echo 2147483648 >>" . g:ExtraVimResult + " X: 0 +endif + +Xcheck 67224583 + + +"------------------------------------------------------------------------------- +" Test 19: Aborting on errors inside :try/:endtry {{{1 +" +" An error in a command dynamically enclosed in a :try/:endtry region +" aborts script processing immediately. It does not matter whether +" the failing command is outside or inside a function and whether a +" function has an "abort" attribute. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + function! F() abort + Xpath 1 " X: 1 + asdf + Xpath 2 " X: 0 + endfunction + + try + Xpath 4 " X: 4 + call F() + Xpath 8 " X: 0 + endtry | Xpath 16 " X: 0 + Xpath 32 " X: 0 +endif + +if ExtraVim() + function! G() + Xpath 64 " X: 64 + asdf + Xpath 128 " X: 0 + endfunction + + try + Xpath 256 " X: 256 + call G() + Xpath 512 " X: 0 + endtry | Xpath 1024 " X: 0 + Xpath 2048 " X: 0 +endif + +if ExtraVim() + try + Xpath 4096 " X: 4096 + asdf + Xpath 8192 " X: 0 + endtry | Xpath 16384 " X: 0 + Xpath 32768 " X: 0 +endif + +if ExtraVim() + if 1 + try + Xpath 65536 " X: 65536 + asdf + Xpath 131072 " X: 0 + endtry | Xpath 262144 " X: 0 + endif | Xpath 524288 " X: 0 + Xpath 1048576 " X: 0 +endif + +if ExtraVim() + let p = 1 + while p + let p = 0 + try + Xpath 2097152 " X: 2097152 + asdf + Xpath 4194304 " X: 0 + endtry | Xpath 8388608 " X: 0 + endwhile | Xpath 16777216 " X: 0 + Xpath 33554432 " X: 0 +endif + +if ExtraVim() + let p = 1 + while p + let p = 0 +" try + Xpath 67108864 " X: 67108864 + endwhile | Xpath 134217728 " X: 0 + Xpath 268435456 " X: 0 +endif + +Xcheck 69275973 +"------------------------------------------------------------------------------- +" Test 20: Aborting on errors after :try/:endtry {{{1 +" +" When an error occurs after the last active :try/:endtry region has +" been left, termination behavior is as if no :try/:endtry has been +" seen. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + let p = 1 + while p + let p = 0 + try + Xpath 1 " X: 1 + endtry + asdf + endwhile | Xpath 2 " X: 0 + Xpath 4 " X: 4 +endif + +if ExtraVim() + while 1 + try + Xpath 8 " X: 8 + break + Xpath 16 " X: 0 + endtry + endwhile + Xpath 32 " X: 32 + asdf + Xpath 64 " X: 64 +endif + +if ExtraVim() + while 1 + try + Xpath 128 " X: 128 + break + Xpath 256 " X: 0 + finally + Xpath 512 " X: 512 + endtry + endwhile + Xpath 1024 " X: 1024 + asdf + Xpath 2048 " X: 2048 +endif + +if ExtraVim() + while 1 + try + Xpath 4096 " X: 4096 + finally + Xpath 8192 " X: 8192 + break + Xpath 16384 " X: 0 + endtry + endwhile + Xpath 32768 " X: 32768 + asdf + Xpath 65536 " X: 65536 +endif + +if ExtraVim() + let p = 1 + while p + let p = 0 + try + Xpath 131072 " X: 131072 + continue + Xpath 262144 " X: 0 + endtry + endwhile + Xpath 524288 " X: 524288 + asdf + Xpath 1048576 " X: 1048576 +endif + +if ExtraVim() + let p = 1 + while p + let p = 0 + try + Xpath 2097152 " X: 2097152 + continue + Xpath 4194304 " X: 0 + finally + Xpath 8388608 " X: 8388608 + endtry + endwhile + Xpath 16777216 " X: 16777216 + asdf + Xpath 33554432 " X: 33554432 +endif + +if ExtraVim() + let p = 1 + while p + let p = 0 + try + Xpath 67108864 " X: 67108864 + finally + Xpath 134217728 " X: 134217728 + continue + Xpath 268435456 " X: 0 + endtry + endwhile + Xpath 536870912 " X: 536870912 + asdf + Xpath 1073741824 " X: 1073741824 +endif + +Xcheck 1874575085 + + +"------------------------------------------------------------------------------- +" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1 +" +" If a :try conditional stays inactive due to a preceding :continue, +" :break, :return, or :finish, its :finally clause should not be +" executed. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + function F() + let loops = 2 + XloopINIT! 1 256 + while loops > 0 + XloopNEXT + let loops = loops - 1 + try + if loops == 1 + Xloop 1 " X: 1 + continue + Xloop 2 " X: 0 + elseif loops == 0 + Xloop 4 " X: 4*256 + break + Xloop 8 " X: 0 + endif + + try " inactive + Xloop 16 " X: 0 + finally + Xloop 32 " X: 0 + endtry + finally + Xloop 64 " X: 64 + 64*256 + endtry + Xloop 128 " X: 0 + endwhile + + try + Xpath 65536 " X: 65536 + return + Xpath 131072 " X: 0 + try " inactive + Xpath 262144 " X: 0 + finally + Xpath 524288 " X: 0 + endtry + finally + Xpath 1048576 " X: 1048576 + endtry + Xpath 2097152 " X: 0 + endfunction + + try + Xpath 4194304 " X: 4194304 + call F() + Xpath 8388608 " X: 8388608 + finish + Xpath 16777216 " X: 0 + try " inactive + Xpath 33554432 " X: 0 + finally + Xpath 67108864 " X: 0 + endtry + finally + Xpath 134217728 " X: 134217728 + endtry + Xpath 268435456 " X: 0 +endif + +Xcheck 147932225 + + +"------------------------------------------------------------------------------- +" Test 22: :finally for a :try after an error/interrupt/:throw {{{1 +" +" If a :try conditional stays inactive due to a preceding error or +" interrupt or :throw, its :finally clause should not be executed. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + function! Error() + try + asdf " aborting error, triggering error exception + endtry + endfunction + + Xpath 1 " X: 1 + call Error() + Xpath 2 " X: 0 + + if 1 " not active due to error + try " not active since :if inactive + Xpath 4 " X: 0 + finally + Xpath 8 " X: 0 + endtry + endif + + try " not active due to error + Xpath 16 " X: 0 + finally + Xpath 32 " X: 0 + endtry +endif + +if ExtraVim() + function! Interrupt() + try + "INTERRUPT " triggering interrupt exception + endtry + endfunction + + Xpath 64 " X: 64 + call Interrupt() + Xpath 128 " X: 0 + + if 1 " not active due to interrupt + try " not active since :if inactive + Xpath 256 " X: 0 + finally + Xpath 512 " X: 0 + endtry + endif + + try " not active due to interrupt + Xpath 1024 " X: 0 + finally + Xpath 2048 " X: 0 + endtry +endif + +if ExtraVim() + function! Throw() + throw "xyz" + endfunction + + Xpath 4096 " X: 4096 + call Throw() + Xpath 8192 " X: 0 + + if 1 " not active due to :throw + try " not active since :if inactive + Xpath 16384 " X: 0 + finally + Xpath 32768 " X: 0 + endtry + endif + + try " not active due to :throw + Xpath 65536 " X: 0 + finally + Xpath 131072 " X: 0 + endtry +endif + +Xcheck 4161 + + +"------------------------------------------------------------------------------- +" Test 23: :catch clauses for a :try after a :throw {{{1 +" +" If a :try conditional stays inactive due to a preceding :throw, +" none of its :catch clauses should be executed. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + try + Xpath 1 " X: 1 + throw "xyz" + Xpath 2 " X: 0 + + if 1 " not active due to :throw + try " not active since :if inactive + Xpath 4 " X: 0 + catch /xyz/ + Xpath 8 " X: 0 + endtry + endif + catch /xyz/ + Xpath 16 " X: 16 + endtry + + Xpath 32 " X: 32 + throw "abc" + Xpath 64 " X: 0 + + try " not active due to :throw + Xpath 128 " X: 0 + catch /abc/ + Xpath 256 " X: 0 + endtry +endif + +Xcheck 49 + + +"------------------------------------------------------------------------------- +" Test 24: :endtry for a :try after a :throw {{{1 +" +" If a :try conditional stays inactive due to a preceding :throw, +" its :endtry should not rethrow the exception to the next surrounding +" active :try conditional. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + try " try 1 + try " try 2 + Xpath 1 " X: 1 + throw "xyz" " makes try 2 inactive + Xpath 2 " X: 0 + + try " try 3 + Xpath 4 " X: 0 + endtry " no rethrow to try 1 + catch /xyz/ " should catch although try 2 inactive + Xpath 8 " X: 8 + endtry + catch /xyz/ " try 1 active, but exception already caught + Xpath 16 " X: 0 + endtry + Xpath 32 " X: 32 +endif + +Xcheck 41 + + +"------------------------------------------------------------------------------- +" Test 25: Executing :finally clauses on normal control flow {{{1 +" +" Control flow in a :try conditional should always fall through to its +" :finally clause. A :finally clause of a :try conditional inside an +" inactive conditional should never be executed. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + let loops = 3 + XloopINIT 1 256 + while loops > 0 " 3: 2: 1: + Xloop 1 " X: 1 + 1*256 + 1*256*256 + if loops >= 2 + try + Xloop 2 " X: 2 + 2*256 + if loops == 2 + try + Xloop 4 " X: 4*256 + finally + Xloop 8 " X: 8*256 + endtry + endif + finally + Xloop 16 " X: 16 + 16*256 + if loops == 2 + try + Xloop 32 " X: 32*256 + finally + Xloop 64 " X: 64*256 + endtry + endif + endtry + endif + Xloop 128 " X: 128 + 128*256 + 128*256*256 + let loops = loops - 1 + XloopNEXT + endwhile + Xpath 16777216 " X: 16777216 +endfunction + +if 1 + try + Xpath 33554432 " X: 33554432 + call F() + Xpath 67108864 " X: 67108864 + finally + Xpath 134217728 " X: 134217728 + endtry +else + try + Xpath 268435456 " X: 0 + finally + Xpath 536870912 " X: 0 + endtry +endif + +delfunction F + +Xcheck 260177811 + + +"------------------------------------------------------------------------------- +" Test 26: Executing :finally clauses after :continue or :break {{{1 +" +" For a :continue or :break dynamically enclosed in a :try/:endtry +" region inside the next surrounding :while/:endwhile, if the +" :continue/:break is before the :finally, the :finally clause is +" executed first. If the :continue/:break is after the :finally, the +" :finally clause is broken (like an :if/:endif region). +"------------------------------------------------------------------------------- + +XpathINIT + +try + let loops = 3 + XloopINIT! 1 32 + while loops > 0 + XloopNEXT + try + try + if loops == 2 " 3: 2: 1: + Xloop 1 " X: 1*32 + let loops = loops - 1 + continue + elseif loops == 1 + Xloop 2 " X: 2*32*32 + break + finish + endif + Xloop 4 " X: 4 + endtry + finally + Xloop 8 " X: 8 + 8*32 + 8*32*32 + endtry + Xloop 16 " X: 16 + let loops = loops - 1 + endwhile + Xpath 32768 " X: 32768 +finally + Xpath 65536 " X: 65536 + let loops = 3 + XloopINIT 131072 16 + while loops > 0 + try + finally + try + if loops == 2 + Xloop 1 " X: 131072*16 + let loops = loops - 1 + XloopNEXT + continue + elseif loops == 1 + Xloop 2 " X: 131072*2*16*16 + break + finish + endif + endtry + Xloop 4 " X: 131072*4 + endtry + Xloop 8 " X: 131072*8 + let loops = loops - 1 + XloopNEXT + endwhile + Xpath 536870912 " X: 536870912 +endtry +Xpath 1073741824 " X: 1073741824 + +unlet loops + +Xcheck 1681500476 + + +"------------------------------------------------------------------------------- +" Test 27: Executing :finally clauses after :return {{{1 +" +" For a :return command dynamically enclosed in a :try/:endtry region, +" :finally clauses are executed and the called function is ended. +"------------------------------------------------------------------------------- + +XpathINIT + +function! F() + try + Xpath 1 " X: 1 + try + Xpath 2 " X: 2 + return + Xpath 4 " X: 0 + finally + Xpath 8 " X: 8 + endtry + Xpath 16 " X: 0 + finally + Xpath 32 " X: 32 + endtry + Xpath 64 " X: 0 +endfunction + +function! G() + try + Xpath 128 " X: 128 + return + Xpath 256 " X: 0 + finally + Xpath 512 " X: 512 + call F() + Xpath 1024 " X: 1024 + endtry + Xpath 2048 " X: 0 +endfunction + +function! H() + try + Xpath 4096 " X: 4096 + call G() + Xpath 8192 " X: 8192 + finally + Xpath 16384 " X: 16384 + return + Xpath 32768 " X: 0 + endtry + Xpath 65536 " X: 0 +endfunction + +try + Xpath 131072 " X: 131072 + call H() + Xpath 262144 " X: 262144 +finally + Xpath 524288 " X: 524288 +endtry +Xpath 1048576 " X: 1048576 + +Xcheck 1996459 + +" Leave F, G, and H for execution as scripts in the next test. + + +"------------------------------------------------------------------------------- +" Test 28: Executing :finally clauses after :finish {{{1 +" +" For a :finish command dynamically enclosed in a :try/:endtry region, +" :finally clauses are executed and the sourced file is finished. +" +" This test executes the bodies of the functions F, G, and H from the +" previous test as script files (:return replaced by :finish). +"------------------------------------------------------------------------------- + +XpathINIT + +let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32 +let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024 +let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384 + +try + Xpath 131072 " X: 131072 + exec "source" scriptH + Xpath 262144 " X: 262144 +finally + Xpath 524288 " X: 524288 +endtry +Xpath 1048576 " X: 1048576 + +call delete(scriptF) +call delete(scriptG) +call delete(scriptH) +unlet scriptF scriptG scriptH +delfunction F +delfunction G +delfunction H + +Xcheck 1996459 + + +"------------------------------------------------------------------------------- +" Test 29: Executing :finally clauses on errors {{{1 +" +" After an error in a command dynamically enclosed in a :try/:endtry +" region, :finally clauses are executed and the script processing is +" terminated. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + function! F() + while 1 + try + Xpath 1 " X: 1 + while 1 + try + Xpath 2 " X: 2 + asdf " error + Xpath 4 " X: 0 + finally + Xpath 8 " X: 8 + endtry | Xpath 16 " X: 0 + Xpath 32 " X: 0 + break + endwhile + Xpath 64 " X: 0 + finally + Xpath 128 " X: 128 + endtry | Xpath 256 " X: 0 + Xpath 512 " X: 0 + break + endwhile + Xpath 1024 " X: 0 + endfunction + + while 1 + try + Xpath 2048 " X: 2048 + while 1 + call F() + Xpath 4096 " X: 0 + break + endwhile | Xpath 8192 " X: 0 + Xpath 16384 " X: 0 + finally + Xpath 32768 " X: 32768 + endtry | Xpath 65536 " X: 0 + endwhile | Xpath 131072 " X: 0 + Xpath 262144 " X: 0 +endif + +if ExtraVim() + function! G() abort + if 1 + try + Xpath 524288 " X: 524288 + asdf " error + Xpath 1048576 " X: 0 + finally + Xpath 2097152 " X: 2097152 + endtry | Xpath 4194304 " X: 0 + endif | Xpath 8388608 " X: 0 + Xpath 16777216 " X: 0 + endfunction + + if 1 + try + Xpath 33554432 " X: 33554432 + call G() + Xpath 67108864 " X: 0 + finally + Xpath 134217728 " X: 134217728 + endtry | Xpath 268435456 " X: 0 + endif | Xpath 536870912 " X: 0 + Xpath 1073741824 " X: 0 +endif + +Xcheck 170428555 + + +"------------------------------------------------------------------------------- +" Test 30: Executing :finally clauses on interrupt {{{1 +" +" After an interrupt in a command dynamically enclosed in +" a :try/:endtry region, :finally clauses are executed and the +" script processing is terminated. +"------------------------------------------------------------------------------- + +XpathINIT + +if ExtraVim() + XloopINIT 1 16 + + function! F() + try + Xloop 1 " X: 1 + 1*16 + "INTERRUPT + Xloop 2 " X: 0 + finally + Xloop 4 " X: 4 + 4*16 + endtry + Xloop 8 " X: 0 + endfunction + + try + Xpath 256 " X: 256 + try + Xpath 512 " X: 512 + "INTERRUPT + Xpath 1024 " X: 0 + finally + Xpath 2048 " X: 2048 + try + Xpath 4096 " X: 4096 + try + Xpath 8192 " X: 8192 + finally + Xpath 16384 " X: 16