diff src/testdir/test_vimscript.vim @ 32669:448aef880252

normalize line endings
author Christian Brabandt <cb@256bit.org>
date Mon, 26 Jun 2023 09:54:34 +0200
parents f35ea6c38a20
children 695b50472e85
line wrap: on
line diff
--- a/src/testdir/test_vimscript.vim
+++ b/src/testdir/test_vimscript.vim
@@ -1,7534 +1,7534 @@
-" Test various aspects of the Vim script language.
-" Most of this was formerly in test49.vim (developed by Servatius Brandt
-" <Servatius.Brandt@fujitsu-siemens.com>)
-
-source check.vim
-source shared.vim
-source script_util.vim
-
-"-------------------------------------------------------------------------------
-" Test environment							    {{{1
-"-------------------------------------------------------------------------------
-
-" Append a message to the "messages" file
-func Xout(text)
-    split messages
-    $put =a:text
-    wq
-endfunc
-
-com! -nargs=1	     Xout     call Xout(<args>)
-
-" Create a new instance of Vim and run the commands in 'test' and then 'verify'
-" The commands in 'test' are expected to store the test results in the Xtest.out
-" file. If the test passes successfully, then Xtest.out should be empty.
-func RunInNewVim(test, verify)
-  let init =<< trim END
-    set cpo-=C            " support line-continuation in sourced script
-    source script_util.vim
-    XpathINIT
-    XloopINIT
-  END
-  let cleanup =<< trim END
-    call writefile(v:errors, 'Xtest.out')
-    qall
-  END
-  call writefile(init, 'Xtest.vim', 'D')
-  call writefile(a:test, 'Xtest.vim', 'a')
-  call writefile(a:verify, 'Xverify.vim', 'D')
-  call writefile(cleanup, 'Xverify.vim', 'a')
-  call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
-  call assert_equal([], readfile('Xtest.out'))
-  call delete('Xtest.out')
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func T1_F()
-    Xpath 'a'
-    let first = 1
-    while 1
-	Xpath 'b'
-	if first
-	    Xpath 'c'
-	    let first = 0
-	    break
-	else
-	    Xpath 'd'
-	    return
-	endif
-    endwhile
-endfunc
-
-func T1_G()
-    Xpath 'h'
-    let first = 1
-    while 1
-	Xpath 'i'
-	if first
-	    Xpath 'j'
-	    let first = 0
-	    break
-	else
-	    Xpath 'k'
-	    return
-	endif
-	if 1	" unmatched :if
-    endwhile
-endfunc
-
-func Test_endwhile_function()
-  XpathINIT
-  call T1_F()
-  Xpath 'F'
-
-  try
-    call T1_G()
-  catch
-    " Catch missing :endif
-    call assert_true(v:exception =~ 'E171:')
-    Xpath 'x'
-  endtry
-  Xpath 'G'
-
-  call assert_equal('abcFhijxG', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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 T1_F and T1_G from
-"	    the previous test as script files (:return replaced by :finish).
-"-------------------------------------------------------------------------------
-
-func Test_endwhile_script()
-  XpathINIT
-  ExecAsScript T1_F
-  Xpath 'F'
-  call DeleteTheScript()
-
-  try
-    ExecAsScript T1_G
-  catch
-    " Catch missing :endif
-    call assert_true(v:exception =~ 'E171:')
-    Xpath 'x'
-  endtry
-  Xpath 'G'
-  call DeleteTheScript()
-
-  call assert_equal('abcFhijxG', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_if_while()
-    XpathINIT
-    if 1
-	Xpath 'a'
-	let loops = 3
-	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
-	    if loops <= 0
-		let break_err = 1
-		let loops = -1
-	    else
-		Xpath 'b' . loops
-	    endif
-	    if (loops == 2)
-		while loops == 2 " dummy loop
-		    Xpath 'c' . loops
-		    let loops = loops - 1
-		    continue    " stop dummy loop
-		    Xpath 'd' . loops
-		endwhile
-		continue	    " continue main loop
-		Xpath 'e' . loops
-	    elseif (loops == 1)
-		let p = 1
-		while p	    " dummy loop
-		    Xpath 'f' . loops
-		    let p = 0
-		    break	    " break dummy loop
-		    Xpath 'g' . loops
-		endwhile
-		Xpath 'h' . loops
-		unlet p
-		break	    " break main loop
-		Xpath 'i' . loops
-	    endif
-	    if (loops > 0)
-		Xpath 'j' . loops
-	    endif
-	    while loops == 3    " dummy loop
-		let loops = loops - 1
-	    endwhile	    " end dummy loop
-	endwhile		    " end main loop
-	Xpath 'k'
-    else
-	Xpath 'l'
-    endif
-    Xpath 'm'
-    if exists("break_err")
-	Xpath 'm'
-	unlet break_err
-    endif
-
-    unlet loops
-
-    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
-endfunc
-
-" Check double quote after skipped "elseif" does not give error E15
-func Test_skipped_elseif()
-  if "foo" ==? "foo"
-      let result = "first"
-  elseif "foo" ==? "foo"
-      let result = "second"
-  endif
-  call assert_equal('first', result)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 4:   :return							    {{{1
-"-------------------------------------------------------------------------------
-
-func T4_F()
-    if 1
-	Xpath 'a'
-	let loops = 3
-	while loops > 0				"    3:  2:     1:
-	    Xpath 'b' . loops
-	    if (loops == 2)
-		Xpath 'c' . loops
-		return
-		Xpath 'd' . loops
-	    endif
-	    Xpath 'e' . loops
-	    let loops = loops - 1
-	endwhile
-	Xpath 'f'
-    else
-	Xpath 'g'
-    endif
-endfunc
-
-func Test_return()
-    XpathINIT
-    call T4_F()
-    Xpath '4'
-
-    call assert_equal('ab3e3b2c24', g:Xpath)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" Test 5:   :finish							    {{{1
-"
-"	    This test executes the body of the function T4_F from the previous
-"	    test as a script file (:return replaced by :finish).
-"-------------------------------------------------------------------------------
-
-func Test_finish()
-    XpathINIT
-    ExecAsScript T4_F
-    Xpath '5'
-    call DeleteTheScript()
-
-    call assert_equal('ab3e3b2c25', g:Xpath)
-endfunc
-
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"
-"	     The functions are defined when sourcing the script, only the
-"	     resulting path is checked in the test function.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-" 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 . <args> |
-	    \ endif
-
-let i = 0
-while i < 3
-    let i = i + 1
-    if i == 1
-	Xpath 'a'
-	function! F1(arg)
-	    CALL a:arg
-	    let outer = 1
-
-	    let j = 0
-	    while j < 1
-		Xpath 'b'
-		let j = j + 1
-		function! G1(arg)
-		    CALL a:arg
-		endfunction
-		Xpath 'c'
-	    endwhile
-	endfunction
-	Xpath 'd'
-
-	continue
-    endif
-
-    Xpath 'e' . i
-    function! F{i}(i, arg)
-	CALL a:arg
-	let outer = 1
-
-	if a:i == 3
-	    Xpath 'f'
-	endif
-	let k = 0
-	while k < 3
-	    Xpath 'g' . k
-	    let k = k + 1
-	    function! G{a:i}{k}(arg)
-		CALL a:arg
-	    endfunction
-	    Xpath 'h' . k
-	endwhile
-    endfunction
-    Xpath 'i'
-
-endwhile
-
-if exists("*G1")
-    Xpath 'j'
-endif
-if exists("*F1")
-    call F1("F1")
-    if exists("*G1")
-       call G1("G1")
-    endif
-endif
-
-if exists("G21") || exists("G22") || exists("G23")
-    Xpath 'k'
-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("G32") || exists("G33")
-    Xpath 'l'
-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 'm'
-
-let g:test6_result = g:Xpath
-let g:test6_calls = calls
-
-unlet calls
-delfunction F1
-delfunction G1
-delfunction F2
-delfunction G21
-delfunction G22
-delfunction G23
-delfunction G31
-delfunction G32
-delfunction G33
-
-func Test_defining_functions()
-    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
-    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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 'a'
-    while 1
-	Xpath 'b'
-	asdf
-	Xpath 'c'
-	break
-    endwhile | Xpath 'd'
-    Xpath 'e'
-endif | Xpath 'f'
-Xpath 'g'
-
-while 1
-    Xpath 'h'
-    if 1
-	Xpath 'i'
-	asdf
-	Xpath 'j'
-    endif | Xpath 'k'
-    Xpath 'l'
-    break
-endwhile | Xpath 'm'
-Xpath 'n'
-
-asdf
-Xpath 'o'
-
-asdf | Xpath 'p'
-Xpath 'q'
-
-let g:test7_result = g:Xpath
-
-func Test_error_in_script()
-    call assert_equal('abghinoq', g:test7_result)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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
-
-func T8_F()
-    if 1
-	Xpath 'a'
-	while 1
-	    Xpath 'b'
-	    asdf
-	    Xpath 'c'
-	    asdf | Xpath 'd'
-	    Xpath 'e'
-	    break
-	endwhile
-	Xpath 'f'
-    endif | Xpath 'g'
-    Xpath 'h'
-
-    while 1
-	Xpath 'i'
-	if 1
-	    Xpath 'j'
-	    asdf
-	    Xpath 'k'
-	    asdf | Xpath 'l'
-	    Xpath 'm'
-	endif
-	Xpath 'n'
-	break
-    endwhile | Xpath 'o'
-    Xpath 'p'
-
-    return novar		" returns (default return value 0)
-    Xpath 'q'
-    return 1			" not reached
-endfunc
-
-func T8_G() abort
-    if 1
-	Xpath 'r'
-	while 1
-	    Xpath 's'
-	    asdf		" returns -1
-	    Xpath 't'
-	    break
-	endwhile
-	Xpath 'v'
-    endif | Xpath 'w'
-    Xpath 'x'
-
-    return -4			" not reached
-endfunc
-
-func T8_H() abort
-    while 1
-	Xpath 'A'
-	if 1
-	    Xpath 'B'
-	    asdf		" returns -1
-	    Xpath 'C'
-	endif
-	Xpath 'D'
-	break
-    endwhile | Xpath 'E'
-    Xpath 'F'
-
-    return -4			" not reached
-endfunc
-
-" Aborted functions (T8_G and T8_H) return -1.
-let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
-Xpath 'X'
-let g:test8_result = g:Xpath
-
-func Test_error_in_function()
-    call assert_equal(13, g:test8_sum)
-    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
-
-    delfunction T8_F
-    delfunction T8_G
-    delfunction T8_H
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-func F() abort
-    Xpath 'a'
-    let result = G()	" not aborted
-    Xpath 'b'
-    if result != 2
-	Xpath 'c'
-    endif
-    return 1
-endfunc
-
-func G()		" no abort attribute
-    Xpath 'd'
-    if H() != -1	" aborted
-	Xpath 'e'
-    endif
-    Xpath 'f'
-    return 2
-endfunc
-
-func H() abort
-    Xpath 'g'
-    call I()		" aborted
-    Xpath 'h'
-    return 4
-endfunc
-
-func I() abort
-    Xpath 'i'
-    asdf		" error
-    Xpath 'j'
-    return 8
-endfunc
-
-if F() != 1
-    Xpath 'k'
-endif
-
-let g:test9_result = g:Xpath
-
-delfunction F
-delfunction G
-delfunction H
-delfunction I
-
-func Test_func_abort()
-    call assert_equal('adgifb', g:test9_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-func 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 = v:errmsg->escape('"')
-	    Xout "Unexpected message:" v:errmsg
-	endif
-    endif
-    return match
-endfunc
-
-if 1 || strlen("\"") | Xpath 'a'
-    Xpath 'b'
-endif
-Xpath 'c'
-
-if 0
-elseif 1 || strlen("\"") | Xpath 'd'
-    Xpath 'e'
-endif
-Xpath 'f'
-
-while 1 || strlen("\"") | Xpath 'g'
-    Xpath 'h'
-    break
-endwhile
-Xpath 'i'
-
-let v:errmsg = ""
-if 1 ||| strlen("\"") | Xpath 'j'
-    Xpath 'k'
-endif
-Xpath 'l'
-if !MSG('E15', "Invalid expression")
-    Xpath 'm'
-endif
-
-let v:errmsg = ""
-if 0
-elseif 1 ||| strlen("\"") | Xpath 'n'
-    Xpath 'o'
-endif
-Xpath 'p'
-if !MSG('E15', "Invalid expression")
-    Xpath 'q'
-endif
-
-let v:errmsg = ""
-while 1 ||| strlen("\"") | Xpath 'r'
-    Xpath 's'
-    break
-endwhile
-Xpath 't'
-if !MSG('E15', "Invalid expression")
-    Xpath 'u'
-endif
-
-let g:test10_result = g:Xpath
-delfunction MSG
-
-func Test_expr_parsing()
-    call assert_equal('abcdefghilpt', g:test10_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-func P(num)
-    let g:calls = g:calls + a:num   " side effect on call
-    return 0
-endfunc
-
-if 1
-    Xpath 'a'
-    asdf		" error
-    Xpath 'b'
-    if P(1)		" should not be called
-	Xpath 'c'
-    elseif !P(2)	" should not be called
-	Xpath 'd'
-    else
-	Xpath 'e'
-    endif
-    Xpath 'f'
-    while P(4)		" should not be called
-	Xpath 'g'
-    endwhile
-    Xpath 'h'
-endif
-Xpath 'x'
-
-let g:test11_calls = calls
-let g:test11_result = g:Xpath
-
-unlet calls
-delfunction P
-
-func Test_arg_abort()
-    call assert_equal(0, g:test11_calls)
-    call assert_equal('ax', g:test11_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-func NULL()
-    Xpath 'a'
-    return 0
-endfunc
-
-func ZERO()
-    Xpath 'b'
-    return 0
-endfunc
-
-func! F0()
-    Xpath 'c'
-endfunc
-
-func! F1(arg)
-    Xpath 'e'
-endfunc
-
-let V0 = 1
-
-Xpath 'f'
-echo 0 ? F{NULL() + V{ZERO()}}() : 1
-
-Xpath 'g'
-if 0
-    Xpath 'h'
-    call F{NULL() + V{ZERO()}}()
-endif
-
-Xpath 'i'
-if 1
-    asdf		" error
-    Xpath 'j'
-    call F1(F{NULL() + V{ZERO()}}())
-endif
-
-Xpath 'k'
-if 1
-    asdf		" error
-    Xpath 'l'
-    call F{NULL() + V{ZERO()}}()
-endif
-
-let g:test12_result = g:Xpath
-
-func Test_braces_skipped()
-    call assert_equal('fgik', g:test12_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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 'a'
-while asdf
-    Xpath 'b'
-    while 1
-	Xpath 'c'
-	break
-    endwhile
-    Xpath 'd'
-    break
-endwhile
-Xpath 'e'
-
-while asdf | Xpath 'f' | endwhile | Xpath 'g'
-Xpath 'h'
-let g:test13_result = g:Xpath
-
-func Test_while_fail()
-    call assert_equal('aeh', g:test13_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-function! F()
-    Xpath 'a'
-    let x = 0
-    if x		" false
-	Xpath 'b'
-    elseif !x		" always true
-	Xpath 'c'
-	let x = 1
-	if g:boolvar	" possibly undefined
-	    Xpath 'd'
-	else
-	    Xpath 'e'
-	endif
-	Xpath 'f'
-    elseif x		" never executed
-	Xpath 'g'
-    endif
-    Xpath 'h'
-endfunction
-
-let boolvar = 1
-call F()
-Xpath '-'
-
-unlet boolvar
-call F()
-let g:test14_result = g:Xpath
-
-delfunction F
-
-func Test_if_fail()
-    call assert_equal('acdfh-acfh', g:test14_result)
-endfunc
-
-
-"-------------------------------------------------------------------------------
-" 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
-
-function! F()
-    Xpath 'a'
-    let x = 0
-    if x		" false
-	Xpath 'b'
-    elseif !x		" always true
-	Xpath 'c'
-	let x = 1
-	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
-	Xpath 'f'
-    elseif x		" never executed
-	Xpath 'g'
-    endif
-    Xpath 'h'
-endfunction
-
-let boolvar = 1
-call F()
-Xpath '-'
-
-unlet boolvar
-call F()
-let g:test15_result = g:Xpath
-
-delfunction F
-
-func Test_if_bar_fail()
-    call assert_equal('acdfh-acfh', g:test15_result)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 16:  Double :else or :elseif after :else				    {{{1
-"
-"	    Multiple :elses or an :elseif after an :else are forbidden.
-"-------------------------------------------------------------------------------
-
-func T16_F() abort
-  if 0
-    Xpath 'a'
-  else
-    Xpath 'b'
-  else		" aborts function
-    Xpath 'c'
-  endif
-  Xpath 'd'
-endfunc
-
-func T16_G() abort
-  if 0
-    Xpath 'a'
-  else
-    Xpath 'b'
-  elseif 1		" aborts function
-    Xpath 'c'
-  else
-    Xpath 'd'
-  endif
-  Xpath 'e'
-endfunc
-
-func T16_H() abort
-  if 0
-    Xpath 'a'
-  elseif 0
-    Xpath 'b'
-  else
-    Xpath 'c'
-  else		" aborts function
-    Xpath 'd'
-  endif
-  Xpath 'e'
-endfunc
-
-func T16_I() abort
-  if 0
-    Xpath 'a'
-  elseif 0
-    Xpath 'b'
-  else
-    Xpath 'c'
-  elseif 1		" aborts function
-    Xpath 'd'
-  else
-    Xpath 'e'
-  endif
-  Xpath 'f'
-endfunc
-
-func Test_Multi_Else()
-  XpathINIT
-  try
-    call T16_F()
-  catch /E583:/
-    Xpath 'e'
-  endtry
-  call assert_equal('be', g:Xpath)
-
-  XpathINIT
-  try
-    call T16_G()
-  catch /E584:/
-    Xpath 'f'
-  endtry
-  call assert_equal('bf', g:Xpath)
-
-  XpathINIT
-  try
-    call T16_H()
-  catch /E583:/
-    Xpath 'f'
-  endtry
-  call assert_equal('cf', g:Xpath)
-
-  XpathINIT
-  try
-    call T16_I()
-  catch /E584:/
-    Xpath 'g'
-  endtry
-  call assert_equal('cg', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-" While loops inside a function are continued on error.
-func T17_F()
-  let loops = 3
-  while loops > 0
-    let loops -= 1
-    Xpath 'a' . loops
-    if (loops == 1)
-      Xpath 'b' . loops
-      continue
-    elseif (loops == 0)
-      Xpath 'c' . loops
-      break
-    elseif 1
-      Xpath 'd' . loops
-    " endif missing!
-  endwhile	" :endwhile after :if 1
-  Xpath 'e'
-endfunc
-
-func T17_G()
-  let loops = 2
-  while loops > 0
-    let loops -= 1
-    Xpath 'a' . loops
-    if 0
-      Xpath 'b' . loops
-    " endif missing
-  endwhile	" :endwhile after :if 0
-endfunc
-
-func T17_H()
-  let loops = 2
-  while loops > 0
-    let loops -= 1
-    Xpath 'a' . loops
-    " if missing!
-    endif	" :endif without :if in while
-    Xpath 'b' . loops
-  endwhile
-endfunc
-
-" Error continuation outside a function is at the outermost :endwhile or :endif.
-XpathINIT
-let v:errmsg = ''
-let loops = 2
-while loops > 0
-    let loops -= 1
-    Xpath 'a' . loops
-    if 0
-	Xpath 'b' . loops
-    " endif missing! Following :endwhile fails.
-endwhile | Xpath 'c'
-Xpath 'd'
-call assert_match('E171:', v:errmsg)
-call assert_equal('a1d', g:Xpath)
-
-func Test_unmatched_if_in_while()
-  XpathINIT
-  call assert_fails('call T17_F()', 'E171:')
-  call assert_equal('a2d2a1b1a0c0e', g:Xpath)
-
-  XpathINIT
-  call assert_fails('call T17_G()', 'E171:')
-  call assert_equal('a1a0', g:Xpath)
-
-  XpathINIT
-  call assert_fails('call T17_H()', 'E580:')
-  call assert_equal('a1b1a0b0', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
-"
-"	    On an interrupt, the script processing is terminated immediately.
-"-------------------------------------------------------------------------------
-
-func Test_interrupt_while_if()
-  let test =<< trim [CODE]
-    try
-      if 1
-        Xpath 'a'
-        while 1
-          Xpath 'b'
-          if 1
-            Xpath 'c'
-            call interrupt()
-            call assert_report('should not get here')
-            break
-            finish
-          endif | call assert_report('should not get here')
-          call assert_report('should not get here')
-        endwhile | call assert_report('should not get here')
-        call assert_report('should not get here')
-      endif | call assert_report('should not get here')
-      call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'd'
-    endtry | Xpath 'e'
-    Xpath 'f'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdef', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_interrupt_try()
-  let test =<< trim [CODE]
-    try
-      try
-        Xpath 'a'
-        call interrupt()
-        call assert_report('should not get here')
-      endtry | call assert_report('should not get here')
-      call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'b'
-    endtry | Xpath 'c'
-    Xpath 'd'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcd', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_interrupt_func_while_if()
-  let test =<< trim [CODE]
-    func F()
-      if 1
-        Xpath 'a'
-        while 1
-          Xpath 'b'
-          if 1
-            Xpath 'c'
-            call interrupt()
-            call assert_report('should not get here')
-            break
-            return
-          endif | call assert_report('should not get here')
-          call assert_report('should not get here')
-        endwhile | call assert_report('should not get here')
-        call assert_report('should not get here')
-      endif | call assert_report('should not get here')
-      call assert_report('should not get here')
-    endfunc
-
-    Xpath 'd'
-    try
-      call F() | call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'e'
-    endtry | Xpath 'f'
-    Xpath 'g'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('dabcefg', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_interrupt_func_try()
-  let test =<< trim [CODE]
-    func G()
-      try
-        Xpath 'a'
-        call interrupt()
-        call assert_report('should not get here')
-      endtry | call assert_report('should not get here')
-      call assert_report('should not get here')
-    endfunc
-
-    Xpath 'b'
-    try
-      call G() | call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'c'
-    endtry | Xpath 'd'
-    Xpath 'e'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('bacde', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_try_error_abort_1()
-  let test =<< trim [CODE]
-    func F() abort
-      Xpath 'a'
-      asdf
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'b'
-      call F()
-      call assert_report('should not get here')
-    endtry | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ba', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_try_error_abort_2()
-  let test =<< trim [CODE]
-    func G()
-      Xpath 'a'
-      asdf
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'b'
-      call G()
-      call assert_report('should not get here')
-    endtry | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ba', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_try_error_abort_3()
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      asdf
-      call assert_report('should not get here')
-    endtry | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_try_error_abort_4()
-  let test =<< trim [CODE]
-    if 1
-      try
-        Xpath 'a'
-        asdf
-        call assert_report('should not get here')
-      endtry | call assert_report('should not get here')
-    endif | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_try_error_abort_5()
-  let test =<< trim [CODE]
-    let p = 1
-    while p
-      let p = 0
-      try
-        Xpath 'a'
-        asdf
-        call assert_report('should not get here')
-      endtry | call assert_report('should not get here')
-    endwhile | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_try_error_abort_6()
-  let test =<< trim [CODE]
-    let p = 1
-    Xpath 'a'
-    while p
-      Xpath 'b'
-      let p = 0
-      try
-        Xpath 'c'
-    endwhile | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_error_after_try_1()
-  let test =<< trim [CODE]
-    let p = 1
-    while p
-      let p = 0
-      Xpath 'a'
-      try
-        Xpath 'b'
-      endtry
-      asdf
-      call assert_report('should not get here')
-    endwhile | call assert_report('should not get here')
-    Xpath 'c'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_2()
-  let test =<< trim [CODE]
-    while 1
-      try
-        Xpath 'a'
-        break
-        call assert_report('should not get here')
-      endtry
-    endwhile
-    Xpath 'b'
-    asdf
-    Xpath 'c'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_3()
-  let test =<< trim [CODE]
-    while 1
-      try
-        Xpath 'a'
-        break
-        call assert_report('should not get here')
-      finally
-        Xpath 'b'
-      endtry
-    endwhile
-    Xpath 'c'
-    asdf
-    Xpath 'd'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcd', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_4()
-  let test =<< trim [CODE]
-    while 1
-      try
-        Xpath 'a'
-      finally
-        Xpath 'b'
-        break
-        call assert_report('should not get here')
-      endtry
-    endwhile
-    Xpath 'c'
-    asdf
-    Xpath 'd'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcd', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_5()
-  let test =<< trim [CODE]
-    let p = 1
-    while p
-      let p = 0
-      try
-        Xpath 'a'
-        continue
-        call assert_report('should not get here')
-      endtry
-    endwhile
-    Xpath 'b'
-    asdf
-    Xpath 'c'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_6()
-  let test =<< trim [CODE]
-    let p = 1
-    while p
-      let p = 0
-      try
-        Xpath 'a'
-        continue
-        call assert_report('should not get here')
-      finally
-        Xpath 'b'
-      endtry
-    endwhile
-    Xpath 'c'
-    asdf
-    Xpath 'd'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcd', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_error_after_try_7()
-  let test =<< trim [CODE]
-    let p = 1
-    while p
-      let p = 0
-      try
-        Xpath 'a'
-      finally
-        Xpath 'b'
-        continue
-        call assert_report('should not get here')
-      endtry
-    endwhile
-    Xpath 'c'
-    asdf
-    Xpath 'd'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcd', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_loop_ctrl_statement()
-  let test =<< trim [CODE]
-    func F()
-      let loops = 2
-      while loops > 0
-        XloopNEXT
-        let loops = loops - 1
-        try
-          if loops == 1
-            Xloop 'a'
-            continue
-            call assert_report('should not get here')
-          elseif loops == 0
-            Xloop 'b'
-            break
-            call assert_report('should not get here')
-          endif
-
-          try		" inactive
-            call assert_report('should not get here')
-          finally
-            call assert_report('should not get here')
-          endtry
-        finally
-          Xloop 'c'
-        endtry
-        call assert_report('should not get here')
-      endwhile
-
-      try
-        Xpath 'd'
-        return
-        call assert_report('should not get here')
-        try		    " inactive
-          call assert_report('should not get here')
-        finally
-          call assert_report('should not get here')
-        endtry
-      finally
-        Xpath 'e'
-      endtry
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'f'
-      call F()
-      Xpath 'g'
-      finish
-      call assert_report('should not get here')
-      try		" inactive
-        call assert_report('should not get here')
-      finally
-        call assert_report('should not get here')
-      endtry
-    finally
-      Xpath 'h'
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('fa2c2b3c3degh', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_error_in_func()
-  let test =<< trim [CODE]
-    func Error()
-      try
-        Xpath 'b'
-        asdf    " aborting error, triggering error exception
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    endfunc
-
-    Xpath 'a'
-    call Error()
-    call assert_report('should not get here')
-
-    if 1	" not active due to error
-      try	" not active since :if inactive
-        call assert_report('should not get here')
-      finally
-        call assert_report('should not get here')
-      endtry
-    endif
-
-    try		" not active due to error
-      call assert_report('should not get here')
-    finally
-      call assert_report('should not get here')
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ab', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_finally_after_interrupt()
-  let test =<< trim [CODE]
-    func Interrupt()
-      try
-        Xpath 'a'
-        call interrupt()            " triggering interrupt exception
-        call assert_report('should not get here')
-      endtry
-    endfunc
-
-    Xpath 'b'
-    try
-      call Interrupt()
-    catch /^Vim:Interrupt$/
-      Xpath 'c'
-      finish
-    endtry
-    call assert_report('should not get here')
-
-    if 1	" not active due to interrupt
-      try	" not active since :if inactive
-        call assert_report('should not get here')
-      finally
-        call assert_report('should not get here')
-      endtry
-    endif
-
-    try		" not active due to interrupt
-      call assert_report('should not get here')
-    finally
-      call assert_report('should not get here')
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('bac', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_finally_after_throw()
-  let test =<< trim [CODE]
-    func Throw()
-      Xpath 'a'
-      throw 'xyz'
-    endfunc
-
-    Xpath 'b'
-    call Throw()
-    call assert_report('should not get here')
-
-    if 1	" not active due to :throw
-      try	" not active since :if inactive
-        call assert_report('should not get here')
-      finally
-        call assert_report('should not get here')
-      endtry
-    endif
-
-    try		" not active due to :throw
-      call assert_report('should not get here')
-    finally
-      call assert_report('should not get here')
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ba', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_catch_after_throw()
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      throw "xyz"
-      call assert_report('should not get here')
-
-      if 1	" not active due to :throw
-        try	" not active since :if inactive
-          call assert_report('should not get here')
-        catch /xyz/
-          call assert_report('should not get here')
-        endtry
-      endif
-    catch /xyz/
-      Xpath 'b'
-    endtry
-
-    Xpath 'c'
-    throw "abc"
-    call assert_report('should not get here')
-
-    try		" not active due to :throw
-      call assert_report('should not get here')
-    catch /abc/
-      call assert_report('should not get here')
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_endtry_after_throw()
-  let test =<< trim [CODE]
-    try			" try 1
-      try		" try 2
-        Xpath 'a'
-        throw "xyz"	" makes try 2 inactive
-        call assert_report('should not get here')
-
-        try		" try 3
-          call assert_report('should not get here')
-        endtry	" no rethrow to try 1
-      catch /xyz/	" should catch although try 2 inactive
-        Xpath 'b'
-      endtry
-    catch /xyz/		" try 1 active, but exception already caught
-      call assert_report('should not get here')
-    endtry
-    Xpath 'c'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func T27_F()
-  try
-    Xpath 'a'
-    try
-      Xpath 'b'
-      return
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-    endtry
-    Xpath 'd'
-  finally
-    Xpath 'e'
-  endtry
-  call assert_report('should not get here')
-endfunc
-
-func T27_G()
-  try
-    Xpath 'f'
-    return
-    call assert_report('should not get here')
-  finally
-    Xpath 'g'
-    call T27_F()
-    Xpath 'h'
-  endtry
-  call assert_report('should not get here')
-endfunc
-
-func T27_H()
-  try
-    Xpath 'i'
-    call T27_G()
-    Xpath 'j'
-  finally
-    Xpath 'k'
-    return
-    call assert_report('should not get here')
-  endtry
-  call assert_report('should not get here')
-endfunction
-
-func Test_finally_after_return()
-  XpathINIT
-  try
-      Xpath 'l'
-      call T27_H()
-      Xpath 'm'
-  finally
-      Xpath 'n'
-  endtry
-  call assert_equal('lifgabcehjkmn', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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).
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_finish()
-  XpathINIT
-
-  let scriptF = MakeScript("T27_F")
-  let scriptG = MakeScript("T27_G", scriptF)
-  let scriptH = MakeScript("T27_H", scriptG)
-
-  try
-    Xpath 'A'
-    exec "source" scriptH
-    Xpath 'B'
-  finally
-    Xpath 'C'
-  endtry
-  Xpath 'D'
-  call assert_equal('AifgabcehjkBCD', g:Xpath)
-  call delete(scriptF)
-  call delete(scriptG)
-  call delete(scriptH)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_error_1()
-  let test =<< trim [CODE]
-    func F()
-      while 1
-        try
-          Xpath 'a'
-          while 1
-            try
-              Xpath 'b'
-              asdf	    " error
-              call assert_report('should not get here')
-            finally
-              Xpath 'c'
-            endtry | call assert_report('should not get here')
-            call assert_report('should not get here')
-            break
-          endwhile
-          call assert_report('should not get here')
-        finally
-          Xpath 'd'
-        endtry | call assert_report('should not get here')
-        call assert_report('should not get here')
-        break
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    while 1
-      try
-        Xpath 'e'
-        while 1
-          call F()
-          call assert_report('should not get here')
-          break
-        endwhile  | call assert_report('should not get here')
-        call assert_report('should not get here')
-      finally
-        Xpath 'f'
-      endtry | call assert_report('should not get here')
-    endwhile | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('eabcdf', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_finally_after_error_2()
-  let test =<< trim [CODE]
-    func G() abort
-      if 1
-        try
-          Xpath 'a'
-          asdf	    " error
-          call assert_report('should not get here')
-        finally
-          Xpath 'b'
-        endtry | Xpath 'c'
-      endif | Xpath 'd'
-      call assert_report('should not get here')
-    endfunc
-
-    if 1
-      try
-        Xpath 'e'
-        call G()
-        call assert_report('should not get here')
-      finally
-        Xpath 'f'
-      endtry | call assert_report('should not get here')
-    endif | call assert_report('should not get here')
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('eabf', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-func Test_finally_on_interrupt()
-  let test =<< trim [CODE]
-    func F()
-      try
-        Xloop 'a'
-        call interrupt()
-        call assert_report('should not get here')
-      finally
-        Xloop 'b'
-      endtry
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      try
-        Xpath 'c'
-        try
-          Xpath 'd'
-          call interrupt()
-          call assert_report('should not get here')
-        finally
-          Xpath 'e'
-          try
-            Xpath 'f'
-            try
-              Xpath 'g'
-            finally
-              Xpath 'h'
-              try
-                Xpath 'i'
-                call interrupt()
-                call assert_report('should not get here')
-              endtry
-              call assert_report('should not get here')
-            endtry
-            call assert_report('should not get here')
-          endtry
-          call assert_report('should not get here')
-        endtry
-        call assert_report('should not get here')
-      finally
-        Xpath 'j'
-        try
-          Xpath 'k'
-          call F()
-          call assert_report('should not get here')
-        finally
-          Xpath 'l'
-          try
-            Xpath 'm'
-            XloopNEXT
-            ExecAsScript F
-            call assert_report('should not get here')
-          finally
-            Xpath 'n'
-          endtry
-          call assert_report('should not get here')
-        endtry
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'o'
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('cdefghijka1b1lma2b2no', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 31:  Executing :finally clauses after :throw			    {{{1
-"
-"	    After a :throw dynamically enclosed in a :try/:endtry region,
-"	    :finally clauses are executed and the script processing is
-"	    terminated.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_throw_2()
-  let test =<< trim [CODE]
-    func F()
-      try
-        Xloop 'a'
-        throw "exception"
-        call assert_report('should not get here')
-      finally
-        Xloop 'b'
-      endtry
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'c'
-      try
-        Xpath 'd'
-        throw "exception"
-        call assert_report('should not get here')
-      finally
-        Xpath 'e'
-        try
-          Xpath 'f'
-          try
-            Xpath 'g'
-          finally
-            Xpath 'h'
-            try
-              Xpath 'i'
-              throw "exception"
-              call assert_report('should not get here')
-            endtry
-            call assert_report('should not get here')
-          endtry
-          call assert_report('should not get here')
-        endtry
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    finally
-      Xpath 'j'
-      try
-        Xpath 'k'
-        call F()
-        call assert_report('should not get here')
-      finally
-        Xpath 'l'
-        try
-          Xpath 'm'
-          XloopNEXT
-          ExecAsScript F
-          call assert_report('should not get here')
-        finally
-          Xpath 'n'
-        endtry
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('cdefghijka1b1lma2b2n', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 34:  :finally reason discarded by :continue			    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by a :continue in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_continue()
-  let test =<< trim [CODE]
-    func C(jump)
-      XloopNEXT
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return" || a:jump == "finish"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            continue	" discards jump that caused the :finally
-            call assert_report('should not get here')
-          endtry
-          call assert_report('should not get here')
-        elseif loop == 2
-          Xloop 'a'
-        endif
-      endwhile
-    endfunc
-
-    call C("continue")
-    Xpath 'b'
-    call C("break")
-    Xpath 'c'
-    call C("return")
-    Xpath 'd'
-    let g:jump = "finish"
-    ExecAsScript C
-    unlet g:jump
-    Xpath 'e'
-    try
-      call C("error")
-      Xpath 'f'
-    finally
-      Xpath 'g'
-      try
-        call C("interrupt")
-        Xpath 'h'
-      finally
-        Xpath 'i'
-        call C("throw")
-        Xpath 'j'
-      endtry
-    endtry
-    Xpath 'k'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 35:  :finally reason discarded by :break				    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by a :break in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discard_by_break()
-  let test =<< trim [CODE]
-    func B(jump)
-      XloopNEXT
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return" || a:jump == "finish"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            break	" discards jump that caused the :finally
-            call assert_report('should not get here')
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      Xloop 'a'
-    endfunc
-
-    call B("continue")
-    Xpath 'b'
-    call B("break")
-    Xpath 'c'
-    call B("return")
-    Xpath 'd'
-    let g:jump = "finish"
-    ExecAsScript B
-    unlet g:jump
-    Xpath 'e'
-    try
-      call B("error")
-      Xpath 'f'
-    finally
-      Xpath 'g'
-      try
-        call B("interrupt")
-        Xpath 'h'
-      finally
-        Xpath 'i'
-        call B("throw")
-        Xpath 'j'
-      endtry
-    endtry
-    Xpath 'k'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 36:  :finally reason discarded by :return			    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by a :return in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discard_by_return()
-  let test =<< trim [CODE]
-    func R(jump, retval) abort
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            return a:retval	" discards jump that caused the :finally
-            call assert_report('should not get here')
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    let sum =  -R("continue", -8)
-    Xpath 'a'
-    let sum = sum - R("break", -16)
-    Xpath 'b'
-    let sum = sum - R("return", -32)
-    Xpath 'c'
-    try
-      let sum = sum - R("error", -64)
-      Xpath 'd'
-    finally
-      Xpath 'e'
-      try
-        let sum = sum - R("interrupt", -128)
-        Xpath 'f'
-      finally
-        Xpath 'g'
-        let sum = sum - R("throw", -256)
-        Xpath 'h'
-      endtry
-    endtry
-    Xpath 'i'
-
-    let expected = 8 + 16 + 32 + 64 + 128 + 256
-    call assert_equal(sum, expected)
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghi', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 37:  :finally reason discarded by :finish			    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by a :finish in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discard_by_finish()
-  let test =<< trim [CODE]
-    func F(jump)	" not executed as function, transformed to a script
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "finish"
-              finish
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            finish	" discards jump that caused the :finally
-            call assert_report('should not get here')
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    let scriptF = MakeScript("F")
-    delfunction F
-
-    let g:jump = "continue"
-    exec "source" scriptF
-    Xpath 'a'
-    let g:jump = "break"
-    exec "source" scriptF
-    Xpath 'b'
-    let g:jump = "finish"
-    exec "source" scriptF
-    Xpath 'c'
-    try
-      let g:jump = "error"
-      exec "source" scriptF
-      Xpath 'd'
-    finally
-      Xpath 'e'
-      try
-        let g:jump = "interrupt"
-        exec "source" scriptF
-        Xpath 'f'
-      finally
-        Xpath 'g'
-        try
-          let g:jump = "throw"
-          exec "source" scriptF
-          Xpath 'h'
-        finally
-          Xpath 'i'
-        endtry
-      endtry
-    endtry
-    unlet g:jump
-    call delete(scriptF)
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghi', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 38:  :finally reason discarded by an error			    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by an error in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discard_by_error()
-  let test =<< trim [CODE]
-    func E(jump)
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return" || a:jump == "finish"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            asdf	" error; discards jump that caused the :finally
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'a'
-      call E("continue")
-      call assert_report('should not get here')
-    finally
-      try
-        Xpath 'b'
-        call E("break")
-        call assert_report('should not get here')
-      finally
-        try
-          Xpath 'c'
-          call E("return")
-          call assert_report('should not get here')
-        finally
-          try
-            Xpath 'd'
-            let g:jump = "finish"
-            ExecAsScript E
-            call assert_report('should not get here')
-          finally
-            unlet g:jump
-            try
-              Xpath 'e'
-              call E("error")
-              call assert_report('should not get here')
-            finally
-              try
-                Xpath 'f'
-                call E("interrupt")
-                call assert_report('should not get here')
-              finally
-                try
-                  Xpath 'g'
-                  call E("throw")
-                  call assert_report('should not get here')
-                finally
-                  Xpath 'h'
-                  delfunction E
-                endtry
-              endtry
-            endtry
-          endtry
-        endtry
-      endtry
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefgh', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 39:  :finally reason discarded by an interrupt			    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by an interrupt in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discarded_by_interrupt()
-  let test =<< trim [CODE]
-    func I(jump)
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return" || a:jump == "finish"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            call interrupt()
-            let dummy = 0
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      try
-        Xpath 'a'
-        call I("continue")
-        call assert_report('should not get here')
-      finally
-        try
-          Xpath 'b'
-          call I("break")
-          call assert_report('should not get here')
-        finally
-          try
-            Xpath 'c'
-            call I("return")
-            call assert_report('should not get here')
-          finally
-            try
-              Xpath 'd'
-              let g:jump = "finish"
-              ExecAsScript I
-              call assert_report('should not get here')
-            finally
-              unlet g:jump
-              try
-                Xpath 'e'
-                call I("error")
-                call assert_report('should not get here')
-              finally
-                try
-                  Xpath 'f'
-                  call I("interrupt")
-                  call assert_report('should not get here')
-                finally
-                  try
-                    Xpath 'g'
-                    call I("throw")
-                    call assert_report('should not get here')
-                  finally
-                    Xpath 'h'
-                    delfunction I
-                  endtry
-                endtry
-              endtry
-            endtry
-          endtry
-        endtry
-      endtry
-      call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'A'
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghA', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 40:  :finally reason discarded by :throw				    {{{1
-"
-"	    When a :finally clause is executed due to a :continue, :break,
-"	    :return, :finish, error, interrupt or :throw, the jump reason is
-"	    discarded by a :throw in the finally clause.
-"-------------------------------------------------------------------------------
-
-func Test_finally_discard_by_throw()
-  let test =<< trim [CODE]
-    func T(jump)
-      let loop = 0
-      while loop < 2
-        let loop = loop + 1
-        if loop == 1
-          try
-            if a:jump == "continue"
-              continue
-            elseif a:jump == "break"
-              break
-            elseif a:jump == "return" || a:jump == "finish"
-              return
-            elseif a:jump == "error"
-              asdf
-            elseif a:jump == "interrupt"
-              call interrupt()
-              let dummy = 0
-            elseif a:jump == "throw"
-              throw "abc"
-            endif
-          finally
-            throw "xyz"	" discards jump that caused the :finally
-          endtry
-        elseif loop == 2
-          call assert_report('should not get here')
-        endif
-      endwhile
-      call assert_report('should not get here')
-    endfunc
-
-    try
-      Xpath 'a'
-      call T("continue")
-      call assert_report('should not get here')
-    finally
-      try
-        Xpath 'b'
-        call T("break")
-        call assert_report('should not get here')
-      finally
-        try
-          Xpath 'c'
-          call T("return")
-          call assert_report('should not get here')
-        finally
-          try
-            Xpath 'd'
-            let g:jump = "finish"
-            ExecAsScript T
-            call assert_report('should not get here')
-          finally
-            unlet g:jump
-            try
-              Xpath 'e'
-              call T("error")
-              call assert_report('should not get here')
-            finally
-              try
-                Xpath 'f'
-                call T("interrupt")
-                call assert_report('should not get here')
-              finally
-                try
-                  Xpath 'g'
-                  call T("throw")
-                  call assert_report('should not get here')
-                finally
-                  Xpath 'h'
-                  delfunction T
-                endtry
-              endtry
-            endtry
-          endtry
-        endtry
-      endtry
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefgh', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 49:  Throwing exceptions across functions			    {{{1
-"
-"	    When an exception is thrown but not caught inside a function, the
-"	    caller is checked for a matching :catch clause.
-"-------------------------------------------------------------------------------
-
-func T49_C()
-  try
-    Xpath 'a'
-    throw "arrgh"
-    call assert_report('should not get here')
-  catch /arrgh/
-    Xpath 'b'
-  endtry
-  Xpath 'c'
-endfunc
-
-func T49_T1()
-  XloopNEXT
-  try
-    Xloop 'd'
-    throw "arrgh"
-    call assert_report('should not get here')
-  finally
-    Xloop 'e'
-  endtry
-  Xloop 'f'
-endfunc
-
-func T49_T2()
-  try
-    Xpath 'g'
-    call T49_T1()
-    call assert_report('should not get here')
-  finally
-    Xpath 'h'
-  endtry
-  call assert_report('should not get here')
-endfunc
-
-func Test_throw_exception_across_funcs()
-  XpathINIT
-  XloopINIT
-  try
-    Xpath 'i'
-    call T49_C()            " throw and catch
-    Xpath 'j'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-
-  try
-    Xpath 'k'
-    call T49_T1()  " throw, one level
-    call assert_report('should not get here')
-  catch /arrgh/
-    Xpath 'l'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-
-  try
-    Xpath 'm'
-    call T49_T2()	" throw, two levels
-    call assert_report('should not get here')
-  catch /arrgh/
-    Xpath 'n'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-  Xpath 'o'
-
-  call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 50:  Throwing exceptions across script files			    {{{1
-"
-"	    When an exception is thrown but not caught inside a script file,
-"	    the sourcing script or function is checked for a matching :catch
-"	    clause.
-"
-"	    This test executes the bodies of the functions C, T1, and T2 from
-"	    the previous test as script files (:return replaced by :finish).
-"-------------------------------------------------------------------------------
-
-func T50_F()
-  try
-    Xpath 'A'
-    exec "source" g:scriptC
-    Xpath 'B'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-
-  try
-    Xpath 'C'
-    exec "source" g:scriptT1
-    call assert_report('should not get here')
-  catch /arrgh/
-    Xpath 'D'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-endfunc
-
-func Test_throw_across_script()
-  XpathINIT
-  XloopINIT
-  let g:scriptC = MakeScript("T49_C")
-  let g:scriptT1 = MakeScript("T49_T1")
-  let scriptT2 = MakeScript("T49_T2", g:scriptT1)
-
-  try
-    Xpath 'E'
-    call T50_F()
-    Xpath 'F'
-    exec "source" scriptT2
-    call assert_report('should not get here')
-  catch /arrgh/
-    Xpath 'G'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-  Xpath 'H'
-  call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath)
-
-  call delete(g:scriptC)
-  call delete(g:scriptT1)
-  call delete(scriptT2)
-  unlet g:scriptC g:scriptT1 scriptT2
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 52:  Uncaught exceptions						    {{{1
-"
-"	    When an exception is thrown but not caught, an error message is
-"	    displayed when the script is terminated.  In case of an interrupt
-"	    or error exception, the normal interrupt or error message(s) are
-"	    displayed.
-"-------------------------------------------------------------------------------
-
-func Test_uncaught_exception_1()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    Xpath 'a'
-    throw "arrgh"
-    call assert_report('should not get here')`
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('E605: Exception not caught: arrgh', v:errmsg)
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_2()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      throw "oops"
-      call assert_report('should not get here')`
-    catch /arrgh/
-      call assert_report('should not get here')`
-    endtry
-    call assert_report('should not get here')`
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('E605: Exception not caught: oops', v:errmsg)
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_3()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    func T()
-      Xpath 'c'
-      throw "brrr"
-      call assert_report('should not get here')`
-    endfunc
-
-    try
-      Xpath 'a'
-      throw "arrgh"
-      call assert_report('should not get here')`
-    catch /.*/
-      Xpath 'b'
-      call T()
-      call assert_report('should not get here')`
-    endtry
-    call assert_report('should not get here')`
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_4()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      throw "arrgh"
-      call assert_report('should not get here')`
-    finally
-      Xpath 'b'
-      throw "brrr"
-      call assert_report('should not get here')`
-    endtry
-    call assert_report('should not get here')`
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
-    call assert_equal('ab', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_5()
-  CheckEnglish
-
-  " Need to catch and handle interrupt, otherwise the test will wait for the
-  " user to press <Enter> to continue
-  let test =<< trim [CODE]
-    try
-      try
-        Xpath 'a'
-        call interrupt()
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    catch /^Vim:Interrupt$/
-      Xpath 'b'
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ab', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_6()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      let x = novar	" error E121; exception: E121
-    catch /E15:/	" should not catch
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-    call assert_equal('E121: Undefined variable: novar', v:errmsg)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_uncaught_exception_7()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      " error E108/E488; exception: E488
-      unlet novar #
-    catch /E108:/       " should not catch
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-    call assert_equal('E488: Trailing characters: #', v:errmsg)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 53:  Nesting errors: :endif/:else/:elseif			    {{{1
-"
-"	    For nesting errors of :if conditionals the correct error messages
-"	    should be given.
-"-------------------------------------------------------------------------------
-
-func Test_nested_if_else_errors()
-  CheckEnglish
-
-  " :endif without :if
-  let code =<< trim END
-    endif
-  END
-  call writefile(code, 'Xtest', 'D')
-  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
-
-  " :endif without :if
-  let code =<< trim END
-    while 1
-      endif
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
-
-  " :endif without :if
-  let code =<< trim END
-    try
-    finally
-      endif
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
-
-  " :endif without :if
-  let code =<< trim END
-    try
-      endif
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
-
-  " :endif without :if
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      endif
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
-
-  " :else without :if
-  let code =<< trim END
-    else
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
-
-  " :else without :if
-  let code =<< trim END
-    while 1
-      else
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
-
-  " :else without :if
-  let code =<< trim END
-    try
-    finally
-      else
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
-
-  " :else without :if
-  let code =<< trim END
-    try
-      else
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
-
-  " :else without :if
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      else
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
-
-  " :elseif without :if
-  let code =<< trim END
-    elseif 1
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
-
-  " :elseif without :if
-  let code =<< trim END
-    while 1
-      elseif 1
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
-
-  " :elseif without :if
-  let code =<< trim END
-    try
-    finally
-      elseif 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
-
-  " :elseif without :if
-  let code =<< trim END
-    try
-      elseif 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
-
-  " :elseif without :if
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      elseif 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
-
-  " multiple :else
-  let code =<< trim END
-    if 1
-    else
-    else
-    endif
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(else):E583: Multiple :else')
-
-  " :elseif after :else
-  let code =<< trim END
-    if 1
-    else
-    elseif 1
-    endif
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else')
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 54:  Nesting errors: :while/:endwhile				    {{{1
-"
-"	    For nesting errors of :while conditionals the correct error messages
-"	    should be given.
-"
-"	    This test reuses the function MESSAGES() from the previous test.
-"	    This functions checks the messages in g:msgfile.
-"-------------------------------------------------------------------------------
-
-func Test_nested_while_error()
-  CheckEnglish
-
-  " :endwhile without :while
-  let code =<< trim END
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " :endwhile without :while
-  let code =<< trim END
-    if 1
-      endwhile
-    endif
-  END
-  call writefile(code, 'Xtest', 'D')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " Missing :endif
-  let code =<< trim END
-    while 1
-      if 1
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
-
-  " :endwhile without :while
-  let code =<< trim END
-    try
-    finally
-      endwhile
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " Missing :endtry
-  let code =<< trim END
-    while 1
-      try
-      finally
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
-
-  " Missing :endtry
-  let code =<< trim END
-    while 1
-      if 1
-        try
-        finally
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
-
-  " Missing :endif
-  let code =<< trim END
-    while 1
-      try
-      finally
-        if 1
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
-
-  " :endwhile without :while
-  let code =<< trim END
-    try
-      endwhile
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " :endwhile without :while
-  let code =<< trim END
-    while 1
-      try
-        endwhile
-      endtry
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " :endwhile without :while
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      endwhile
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-
-  " :endwhile without :while
-  let code =<< trim END
-    while 1
-      try
-        throw "a"
-      catch /a/
-        endwhile
-      endtry
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 55:  Nesting errors: :continue/:break				    {{{1
-"
-"	    For nesting errors of :continue and :break commands the correct
-"	    error messages should be given.
-"
-"	    This test reuses the function MESSAGES() from the previous test.
-"	    This functions checks the messages in g:msgfile.
-"-------------------------------------------------------------------------------
-
-func Test_nested_cont_break_error()
-  CheckEnglish
-
-  " :continue without :while
-  let code =<< trim END
-    continue
-  END
-  call writefile(code, 'Xtest', 'D')
-  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
-
-  " :continue without :while
-  let code =<< trim END
-    if 1
-      continue
-    endif
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
-
-  " :continue without :while
-  let code =<< trim END
-    try
-    finally
-      continue
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
-
-  " :continue without :while
-  let code =<< trim END
-    try
-      continue
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
-
-  " :continue without :while
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      continue
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
-
-  " :break without :while
-  let code =<< trim END
-    break
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
-
-  " :break without :while
-  let code =<< trim END
-    if 1
-      break
-    endif
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
-
-  " :break without :while
-  let code =<< trim END
-    try
-    finally
-      break
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
-
-  " :break without :while
-  let code =<< trim END
-    try
-      break
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
-
-  " :break without :while
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      break
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 56:  Nesting errors: :endtry					    {{{1
-"
-"	    For nesting errors of :try conditionals the correct error messages
-"	    should be given.
-"
-"	    This test reuses the function MESSAGES() from the previous test.
-"	    This functions checks the messages in g:msgfile.
-"-------------------------------------------------------------------------------
-
-func Test_nested_endtry_error()
-  CheckEnglish
-
-  " :endtry without :try
-  let code =<< trim END
-    endtry
-  END
-  call writefile(code, 'Xtest', 'D')
-  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
-
-  " :endtry without :try
-  let code =<< trim END
-    if 1
-      endtry
-    endif
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
-
-  " :endtry without :try
-  let code =<< trim END
-    while 1
-      endtry
-    endwhile
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
-
-  " Missing :endif
-  let code =<< trim END
-    try
-        if 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
-
-  " Missing :endwhile
-  let code =<< trim END
-    try
-      while 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
-
-  " Missing :endif
-  let code =<< trim END
-    try
-    finally
-      if 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
-
-  " Missing :endwhile
-  let code =<< trim END
-    try
-    finally
-      while 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
-
-  " Missing :endif
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      if 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
-
-  " Missing :endwhile
-  let code =<< trim END
-    try
-      throw "a"
-    catch /a/
-      while 1
-    endtry
-  END
-  call writefile(code, 'Xtest')
-  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 57:  v:exception and v:throwpoint for user exceptions		    {{{1
-"
-"	    v:exception evaluates to the value of the exception that was caught
-"	    most recently and is not finished.  (A caught exception is finished
-"	    when the next ":catch", ":finally", or ":endtry" is reached.)
-"	    v:throwpoint evaluates to the script/function name and line number
-"	    where that exception has been thrown.
-"-------------------------------------------------------------------------------
-
-func Test_user_exception_info()
-  CheckEnglish
-
-  XpathINIT
-  XloopINIT
-
-  func FuncException()
-    let g:exception = v:exception
-  endfunc
-
-  func FuncThrowpoint()
-    let g:throwpoint = v:throwpoint
-  endfunc
-
-  let scriptException  = MakeScript("FuncException")
-  let scriptThrowPoint = MakeScript("FuncThrowpoint")
-
-  command! CmdException  let g:exception  = v:exception
-  command! CmdThrowpoint let g:throwpoint = v:throwpoint
-
-  func T(arg, line)
-    if a:line == 2
-      throw a:arg		" in line 2
-    elseif a:line == 4
-      throw a:arg		" in line 4
-    elseif a:line == 6
-      throw a:arg		" in line 6
-    elseif a:line == 8
-      throw a:arg		" in line 8
-    endif
-  endfunc
-
-  func G(arg, line)
-    call T(a:arg, a:line)
-  endfunc
-
-  func F(arg, line)
-    call G(a:arg, a:line)
-  endfunc
-
-  let scriptT = MakeScript("T")
-  let scriptG = MakeScript("G", scriptT)
-  let scriptF = MakeScript("F", scriptG)
-
-  try
-    Xpath 'a'
-    call F("oops", 2)
-  catch /.*/
-    Xpath 'b'
-    let exception  = v:exception
-    let throwpoint = v:throwpoint
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-
-    exec "let exception  = v:exception"
-    exec "let throwpoint = v:throwpoint"
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-
-    CmdException
-    CmdThrowpoint
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-
-    call FuncException()
-    call FuncThrowpoint()
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-
-    exec "source" scriptException
-    exec "source" scriptThrowPoint
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-
-    try
-      Xpath 'c'
-      call G("arrgh", 4)
-    catch /.*/
-      Xpath 'd'
-      let exception  = v:exception
-      let throwpoint = v:throwpoint
-      call assert_equal("arrgh", v:exception)
-      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
-      call assert_match('\<4\>', v:throwpoint)
-
-      try
-        Xpath 'e'
-        let g:arg = "autsch"
-        let g:line = 6
-        exec "source" scriptF
-      catch /.*/
-        Xpath 'f'
-        let exception  = v:exception
-        let throwpoint = v:throwpoint
-        call assert_equal("autsch", v:exception)
-        call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
-        call assert_match('\<6\>', v:throwpoint)
-      finally
-        Xpath 'g'
-        let exception  = v:exception
-        let throwpoint = v:throwpoint
-        call assert_equal("arrgh", v:exception)
-        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
-        call assert_match('\<4\>', v:throwpoint)
-        try
-          Xpath 'h'
-          let g:arg = "brrrr"
-          let g:line = 8
-          exec "source" scriptG
-        catch /.*/
-          Xpath 'i'
-          let exception  = v:exception
-          let throwpoint = v:throwpoint
-          " Resolve scriptT for matching it against v:throwpoint.
-          call assert_equal("brrrr", v:exception)
-          call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
-          call assert_match('\<8\>', v:throwpoint)
-        finally
-          Xpath 'j'
-          let exception  = v:exception
-          let throwpoint = v:throwpoint
-          call assert_equal("arrgh", v:exception)
-          call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
-          call assert_match('\<4\>', v:throwpoint)
-        endtry
-        Xpath 'k'
-        let exception  = v:exception
-        let throwpoint = v:throwpoint
-        call assert_equal("arrgh", v:exception)
-        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
-        call assert_match('\<4\>', v:throwpoint)
-      endtry
-      Xpath 'l'
-      let exception  = v:exception
-      let throwpoint = v:throwpoint
-      call assert_equal("arrgh", v:exception)
-      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
-      call assert_match('\<4\>', v:throwpoint)
-    finally
-      Xpath 'm'
-      let exception  = v:exception
-      let throwpoint = v:throwpoint
-      call assert_equal("oops", v:exception)
-      call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-      call assert_match('\<2\>', v:throwpoint)
-    endtry
-    Xpath 'n'
-    let exception  = v:exception
-    let throwpoint = v:throwpoint
-    call assert_equal("oops", v:exception)
-    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
-    call assert_match('\<2\>', v:throwpoint)
-  finally
-    Xpath 'o'
-    let exception  = v:exception
-    let throwpoint = v:throwpoint
-    call assert_equal("", v:exception)
-    call assert_match('^$', v:throwpoint)
-    call assert_match('^$', v:throwpoint)
-  endtry
-
-  call assert_equal('abcdefghijklmno', g:Xpath)
-
-  unlet exception throwpoint
-  delfunction FuncException
-  delfunction FuncThrowpoint
-  call delete(scriptException)
-  call delete(scriptThrowPoint)
-  unlet scriptException scriptThrowPoint
-  delcommand CmdException
-  delcommand CmdThrowpoint
-  delfunction T
-  delfunction G
-  delfunction F
-  call delete(scriptT)
-  call delete(scriptG)
-  call delete(scriptF)
-  unlet scriptT scriptG scriptF
-endfunc
-
-"-------------------------------------------------------------------------------
-"
-" Test 58:  v:exception and v:throwpoint for error/interrupt exceptions	    {{{1
-"
-"	    v:exception and v:throwpoint work also for error and interrupt
-"	    exceptions.
-"-------------------------------------------------------------------------------
-
-func Test_exception_info_for_error()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    func T(line)
-      if a:line == 2
-        delfunction T		" error (function in use) in line 2
-      elseif a:line == 4
-        call interrupt()
-      endif
-    endfunc
-
-    while 1
-      try
-        Xpath 'a'
-        call T(2)
-        call assert_report('should not get here')
-      catch /.*/
-        Xpath 'b'
-        if v:exception !~ 'Vim(delfunction):'
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint !~ '\<T\>'
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint !~ '\<2\>'
-          call assert_report('should not get here')
-        endif
-      finally
-        Xpath 'c'
-        if v:exception != ""
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint != ""
-          call assert_report('should not get here')
-        endif
-        break
-      endtry
-    endwhile
-
-    Xpath 'd'
-    if v:exception != ""
-      call assert_report('should not get here')
-    endif
-    if v:throwpoint != ""
-      call assert_report('should not get here')
-    endif
-
-    while 1
-      try
-        Xpath 'e'
-        call T(4)
-        call assert_report('should not get here')
-      catch /.*/
-        Xpath 'f'
-        if v:exception != 'Vim:Interrupt'
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint !~ 'function T'
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint !~ '\<4\>'
-          call assert_report('should not get here')
-        endif
-      finally
-        Xpath 'g'
-        if v:exception != ""
-          call assert_report('should not get here')
-        endif
-        if v:throwpoint != ""
-          call assert_report('should not get here')
-        endif
-        break
-      endtry
-    endwhile
-
-    Xpath 'h'
-    if v:exception != ""
-      call assert_report('should not get here')
-    endif
-    if v:throwpoint != ""
-      call assert_report('should not get here')
-    endif
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefgh', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-"
-" Test 59:  v:exception and v:throwpoint when discarding exceptions	    {{{1
-"
-"	    When a :catch clause is left by a ":break" etc or an error or
-"	    interrupt exception, v:exception and v:throwpoint are reset.  They
-"	    are not affected by an exception that is discarded before being
-"	    caught.
-"-------------------------------------------------------------------------------
-func Test_exception_info_on_discard()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    let sfile = expand("<sfile>")
-
-    while 1
-      try
-        throw "x1"
-      catch /.*/
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    while 1
-      try
-        throw "x2"
-      catch /.*/
-        break
-      finally
-        call assert_equal('', v:exception)
-        call assert_equal('', v:throwpoint)
-      endtry
-      break
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    while 1
-      try
-        let errcaught = 0
-        try
-          try
-            throw "x3"
-          catch /.*/
-            let lnum = expand("<sflnum>")
-            asdf
-          endtry
-        catch /.*/
-          let errcaught = 1
-          call assert_match('Vim:E492: Not an editor command:', v:exception)
-          call assert_match('line ' .. (lnum + 1), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, errcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'a'
-
-    while 1
-      try
-        let intcaught = 0
-        try
-          try
-            throw "x4"
-          catch /.*/
-            let lnum = expand("<sflnum>")
-            call interrupt()
-          endtry
-        catch /.*/
-          let intcaught = 1
-          call assert_match('Vim:Interrupt', v:exception)
-          call assert_match('line ' .. (lnum + 1), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, intcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'b'
-
-    while 1
-      try
-        let errcaught = 0
-        try
-          try
-            if 1
-              let lnum = expand("<sflnum>")
-              throw "x5"
-            " missing endif
-          catch /.*/
-            call assert_report('should not get here')
-          endtry
-        catch /.*/
-          let errcaught = 1
-          call assert_match('Vim(catch):E171: Missing :endif:', v:exception)
-          call assert_match('line ' .. (lnum + 3), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, errcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'c'
-
-    try
-      while 1
-        try
-          throw "x6"
-        finally
-          break
-        endtry
-        break
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    try
-      while 1
-        try
-          throw "x7"
-        finally
-          break
-        endtry
-        break
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      call assert_equal('', v:exception)
-      call assert_equal('', v:throwpoint)
-    endtry
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    while 1
-      try
-        let errcaught = 0
-        try
-          try
-            throw "x8"
-          finally
-            let lnum = expand("<sflnum>")
-            asdf
-          endtry
-        catch /.*/
-          let errcaught = 1
-          call assert_match('Vim:E492: Not an editor command:', v:exception)
-          call assert_match('line ' .. (lnum + 1), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, errcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'd'
-
-    while 1
-      try
-        let intcaught = 0
-        try
-          try
-            throw "x9"
-          finally
-            let lnum = expand("<sflnum>")
-            call interrupt()
-          endtry
-        catch /.*/
-          let intcaught = 1
-          call assert_match('Vim:Interrupt', v:exception)
-          call assert_match('line ' .. (lnum + 1), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, intcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'e'
-
-    while 1
-      try
-        let errcaught = 0
-        try
-          try
-            if 1
-              let lnum = expand("<sflnum>")
-              throw "x10"
-            " missing endif
-          finally
-            call assert_equal('', v:exception)
-            call assert_equal('', v:throwpoint)
-          endtry
-        catch /.*/
-          let errcaught = 1
-          call assert_match('Vim(finally):E171: Missing :endif:', v:exception)
-          call assert_match('line ' .. (lnum + 3), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, errcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'f'
-
-    while 1
-      try
-        let errcaught = 0
-        try
-          try
-            if 1
-              let lnum = expand("<sflnum>")
-              throw "x11"
-            " missing endif
-          endtry
-        catch /.*/
-          let errcaught = 1
-          call assert_match('Vim(endtry):E171: Missing :endif:', v:exception)
-          call assert_match('line ' .. (lnum + 3), v:throwpoint)
-        endtry
-      finally
-        call assert_equal(1, errcaught)
-        break
-      endtry
-    endwhile
-    call assert_equal('', v:exception)
-    call assert_equal('', v:throwpoint)
-
-    Xpath 'g'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefg', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-"
-" Test 60:  (Re)throwing v:exception; :echoerr.				    {{{1
-"
-"	    A user exception can be rethrown after catching by throwing
-"	    v:exception.  An error or interrupt exception cannot be rethrown
-"	    because Vim exceptions cannot be faked.  A Vim exception using the
-"	    value of v:exception can, however, be triggered by the :echoerr
-"	    command.
-"-------------------------------------------------------------------------------
-
-func Test_rethrow_exception_1()
-  XpathINIT
-  try
-    try
-      Xpath 'a'
-      throw "oops"
-    catch /oops/
-      Xpath 'b'
-      throw v:exception	" rethrow user exception
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-  catch /^oops$/			" catches rethrown user exception
-    Xpath 'c'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_rethrow_exception_2()
-  XpathINIT
-  try
-    let caught = 0
-    try
-      Xpath 'a'
-      write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
-      call assert_report('should not get here')
-    catch /^Vim(write):/
-      let caught = 1
-      throw v:exception	" throw error: cannot fake Vim exception
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'b'
-      call assert_equal(1, caught)
-    endtry
-  catch /^Vim(throw):/	" catches throw error
-    let caught = caught + 1
-  catch /.*/
-    call assert_report('should not get here')
-  finally
-    Xpath 'c'
-    call assert_equal(2, caught)
-  endtry
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_rethrow_exception_3()
-  XpathINIT
-  try
-    let caught = 0
-    try
-      Xpath 'a'
-      asdf
-    catch /^Vim/		" catch error exception
-      let caught = 1
-      " Trigger Vim error exception with value specified after :echoerr
-      let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
-      echoerr value
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'b'
-      call assert_equal(1, caught)
-    endtry
-  catch /^Vim(echoerr):/
-    let caught = caught + 1
-    call assert_match(value, v:exception)
-  catch /.*/
-    call assert_report('should not get here')
-  finally
-    Xpath 'c'
-    call assert_equal(2, caught)
-  endtry
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_rethrow_exception_3()
-  XpathINIT
-  try
-    let errcaught = 0
-    try
-      Xpath 'a'
-      let intcaught = 0
-      call interrupt()
-    catch /^Vim:/		" catch interrupt exception
-      let intcaught = 1
-      " Trigger Vim error exception with value specified after :echoerr
-      echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'b'
-      call assert_equal(1, intcaught)
-    endtry
-  catch /^Vim(echoerr):/
-    let errcaught = 1
-    call assert_match('Interrupt', v:exception)
-  finally
-    Xpath 'c'
-    call assert_equal(1, errcaught)
-  endtry
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 61:  Catching interrupt exceptions				    {{{1
-"
-"	    When an interrupt occurs inside a :try/:endtry region, an
-"	    interrupt exception is thrown and can be caught.  Its value is
-"	    "Vim:Interrupt".  If the interrupt occurs after an error or a :throw
-"	    but before a matching :catch is reached, all following :catches of
-"	    that try block are ignored, but the interrupt exception can be
-"	    caught by the next surrounding try conditional.  An interrupt is
-"	    ignored when there is a previous interrupt that has not been caught
-"	    or causes a :finally clause to be executed.
-"-------------------------------------------------------------------------------
-
-func Test_catch_intr_exception()
-  let test =<< trim [CODE]
-    while 1
-      try
-        try
-          Xpath 'a'
-          call interrupt()
-          call assert_report('should not get here')
-        catch /^Vim:Interrupt$/
-          Xpath 'b'
-        finally
-          Xpath 'c'
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'd'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          try
-            Xpath 'e'
-            asdf
-            call assert_report('should not get here')
-          catch /do_not_catch/
-            call assert_report('should not get here')
-          catch /.*/
-            Xpath 'f'
-            call interrupt()
-            call assert_report('should not get here')
-          catch /.*/
-            call assert_report('should not get here')
-          finally
-            Xpath 'g'
-            call interrupt()
-            call assert_report('should not get here')
-          endtry
-        catch /^Vim:Interrupt$/
-          Xpath 'h'
-        finally
-          Xpath 'i'
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'j'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          try
-            Xpath 'k'
-            throw "x"
-            call assert_report('should not get here')
-          catch /do_not_catch/
-            call assert_report('should not get here')
-          catch /x/
-            Xpath 'l'
-            call interrupt()
-            call assert_report('should not get here')
-          catch /.*/
-            call assert_report('should not get here')
-          endtry
-        catch /^Vim:Interrupt$/
-          Xpath 'm'
-        finally
-          Xpath 'n'
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'o'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          Xpath 'p'
-          call interrupt()
-          call assert_report('should not get here')
-        catch /do_not_catch/
-          call interrupt()
-          call assert_report('should not get here')
-        catch /^Vim:Interrupt$/
-          Xpath 'q'
-        finally
-          Xpath 'r'
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 's'
-        break
-      endtry
-    endwhile
-
-    Xpath 't'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghijklmnopqrst', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 62:  Catching error exceptions					    {{{1
-"
-"	    An error inside a :try/:endtry region is converted to an exception
-"	    and can be caught.  The error exception has a "Vim(cmdname):" prefix
-"	    where cmdname is the name of the failing command, or a "Vim:" prefix
-"	    if no command name is known.  The "Vim" prefixes cannot be faked.
-"-------------------------------------------------------------------------------
-
-func Test_catch_err_exception_1()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        unlet novar
-      catch /^Vim(unlet):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match('E108: No such variable: "novar"', v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_catch_err_exception_2()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        throw novar			" error in :throw
-      catch /^Vim(throw):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match('E121: Undefined variable: novar', v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_catch_err_exception_3()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        throw "Vim:faked"		" error: cannot fake Vim exception
-      catch /^Vim(throw):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix",
-              \ v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-endfunc
-
-func Test_catch_err_exception_4()
-  XpathINIT
-  func F()
-    while 1
-    " Missing :endwhile
-  endfunc
-
-  while 1
-    try
-      try
-        let caught = 0
-        call F()
-      catch /^Vim(endfunction):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match("E170: Missing :endwhile", v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-  delfunc F
-endfunc
-
-func Test_catch_err_exception_5()
-  XpathINIT
-  func F()
-    while 1
-    " Missing :endwhile
-  endfunc
-
-  while 1
-    try
-      try
-        let caught = 0
-        ExecAsScript F
-      catch /^Vim:/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim:', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match("E170: Missing :endwhile", v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-  delfunc F
-endfunc
-
-func Test_catch_err_exception_6()
-  XpathINIT
-  func G()
-    call G()
-  endfunc
-
-  while 1
-    try
-      let mfd_save = &mfd
-      set mfd=3
-      try
-        let caught = 0
-        call G()
-      catch /^Vim(call):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      let &mfd = mfd_save
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abc', g:Xpath)
-  delfunc G
-endfunc
-
-func Test_catch_err_exception_7()
-  XpathINIT
-  func H()
-    return H()
-  endfunc
-
-  while 1
-    try
-      let mfd_save = &mfd
-      set mfd=3
-      try
-        let caught = 0
-        call H()
-      catch /^Vim(return):/
-        Xpath 'a'
-        let caught = 1
-        let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
-      finally
-        Xpath 'b'
-        call assert_equal(1, caught)
-        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'c'
-      let &mfd = mfd_save
-      break		" discard error for $VIMNOERRTHROW
-    endtry
-    call assert_report('should not get here')
-  endwhile
-
-  call assert_equal('abc', g:Xpath)
-  delfunc H
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 63:  Suppressing error exceptions by :silent!.			    {{{1
-"
-"	    A :silent! command inside a :try/:endtry region suppresses the
-"	    conversion of errors to an exception and the immediate abortion on
-"	    error.  When the commands executed by the :silent! themselves open
-"	    a new :try/:endtry region, conversion of errors to exception and
-"	    immediate abortion is switched on again - until the next :silent!
-"	    etc.  The :silent! has the effect of setting v:errmsg to the error
-"	    message text (without displaying it) and continuing with the next
-"	    script line.
-"
-"	    When a command triggering autocommands is executed by :silent!
-"	    inside a :try/:endtry, the autocommand execution is not suppressed
-"	    on error.
-"
-"	    This test reuses the function MSG() from the previous test.
-"-------------------------------------------------------------------------------
-
-func Test_silent_exception()
-  XpathINIT
-  XloopINIT
-  let g:taken = ""
-
-  func S(n) abort
-    XloopNEXT
-    let g:taken = g:taken . "E" . a:n
-    let v:errmsg = ""
-    exec "asdf" . a:n
-
-    " Check that ":silent!" continues:
-    Xloop 'a'
-
-    " Check that ":silent!" sets "v:errmsg":
-    call assert_match("E492: Not an editor command", v:errmsg)
-  endfunc
-
-  func Foo()
-    while 1
-      try
-        try
-          let caught = 0
-          " This is not silent:
-          call S(3)
-        catch /^Vim:/
-          Xpath 'b'
-          let caught = 1
-          let errmsg3 = substitute(v:exception, '^Vim:', '', "")
-          silent! call S(4)
-        finally
-          call assert_equal(1, caught)
-          Xpath 'c'
-          call assert_match("E492: Not an editor command", errmsg3)
-          silent! call S(5)
-          " Break out of try conditionals that cover ":silent!".  This also
-          " discards the aborting error when $VIMNOERRTHROW is non-zero.
-          break
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      endtry
-    endwhile
-    " This is a double ":silent!" (see caller).
-    silent! call S(6)
-  endfunc
-
-  func Bar()
-    try
-      silent! call S(2)
-      silent! execute "call Foo() | call S(7)"
-      silent! call S(8)
-    endtry	" normal end of try cond that covers ":silent!"
-    " This has a ":silent!" from the caller:
-    call S(9)
-  endfunc
-
-  silent! call S(1)
-  silent! call Bar()
-  silent! call S(10)
-
-  call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken)
-
-  augroup TMP
-    au!
-    autocmd BufWritePost * Xpath 'd'
-  augroup END
-
-  Xpath 'e'
-  silent! write /i/m/p/o/s/s/i/b/l/e
-  Xpath 'f'
-
-  call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath)
-
-  augroup TMP
-    au!
-  augroup END
-  augroup! TMP
-  delfunction S
-  delfunction Foo
-  delfunction Bar
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 64:  Error exceptions after error, interrupt or :throw		    {{{1
-"
-"	    When an error occurs after an interrupt or a :throw but before
-"	    a matching :catch is reached, all following :catches of that try
-"	    block are ignored, but the error exception can be caught by the next
-"	    surrounding try conditional.  Any previous error exception is
-"	    discarded.  An error is ignored when there is a previous error that
-"	    has not been caught.
-"-------------------------------------------------------------------------------
-
-func Test_exception_after_error_1()
-  XpathINIT
-  while 1
-    try
-      try
-        Xpath 'a'
-        let caught = 0
-        while 1
-          if 1
-          " Missing :endif
-        endwhile	" throw error exception
-      catch /^Vim(/
-        Xpath 'b'
-        let caught = 1
-      finally
-        Xpath 'c'
-        call assert_equal(1, caught)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'd'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abcd', g:Xpath)
-endfunc
-
-func Test_exception_after_error_2()
-  XpathINIT
-  while 1
-    try
-      try
-        Xpath 'a'
-        let caught = 0
-        try
-          if 1
-          " Missing :endif
-        catch /.*/	" throw error exception
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        endtry
-      catch /^Vim(/
-        Xpath 'b'
-        let caught = 1
-      finally
-        Xpath 'c'
-        call assert_equal(1, caught)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'd'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abcd', g:Xpath)
-endfunc
-
-func Test_exception_after_error_3()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        try
-          Xpath 'a'
-          call interrupt()
-        catch /do_not_catch/
-          call assert_report('should not get here')
-          if 1
-          " Missing :endif
-        catch /.*/	" throw error exception
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        endtry
-      catch /^Vim(/
-        Xpath 'b'
-        let caught = 1
-      finally
-        Xpath 'c'
-        call assert_equal(1, caught)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'd'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abcd', g:Xpath)
-endfunc
-
-func Test_exception_after_error_4()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        try
-          Xpath 'a'
-          throw "x"
-        catch /do_not_catch/
-          call assert_report('should not get here')
-          if 1
-          " Missing :endif
-        catch /x/	" throw error exception
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        endtry
-      catch /^Vim(/
-        Xpath 'b'
-        let caught = 1
-      finally
-        Xpath 'c'
-        call assert_equal(1, caught)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'd'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abcd', g:Xpath)
-endfunc
-
-func Test_exception_after_error_5()
-  XpathINIT
-  while 1
-    try
-      try
-        let caught = 0
-        Xpath 'a'
-        endif		" :endif without :if; throw error exception
-        if 1
-        " Missing :endif
-      catch /do_not_catch/ " ignore new error
-        call assert_report('should not get here')
-      catch /^Vim(endif):/
-        Xpath 'b'
-        let caught = 1
-      catch /^Vim(/
-        call assert_report('should not get here')
-      finally
-        Xpath 'c'
-        call assert_equal(1, caught)
-      endtry
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      Xpath 'd'
-      break
-    endtry
-    call assert_report('should not get here')
-  endwhile
-  call assert_equal('abcd', g:Xpath)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 65:  Errors in the /pattern/ argument of a :catch		    {{{1
-"
-"	    On an error in the /pattern/ argument of a :catch, the :catch does
-"	    not match.  Any following :catches of the same :try/:endtry don't
-"	    match either.  Finally clauses are executed.
-"-------------------------------------------------------------------------------
-
-func Test_catch_pattern_error()
-  CheckEnglish
-  XpathINIT
-
-  try
-    try
-      Xpath 'a'
-      throw "oops"
-    catch /^oops$/
-      Xpath 'b'
-    catch /\)/		" not checked; exception has already been caught
-      call assert_report('should not get here')
-    endtry
-    Xpath 'c'
-  catch /.*/
-    call assert_report('should not get here')
-  endtry
-  call assert_equal('abc', g:Xpath)
-
-  XpathINIT
-  func F()
-    try
-      try
-        try
-          Xpath 'a'
-          throw "ab"
-        catch /abc/	" does not catch
-          call assert_report('should not get here')
-        catch /\)/	" error; discards exception
-          call assert_report('should not get here')
-        catch /.*/	" not checked
-          call assert_report('should not get here')
-        finally
-          Xpath 'b'
-        endtry
-        call assert_report('should not get here')
-      catch /^ab$/	" checked, but original exception is discarded
-        call assert_report('should not get here')
-      catch /^Vim(catch):/
-        Xpath 'c'
-        call assert_match('Vim(catch):E475: Invalid argument:', v:exception)
-      finally
-        Xpath 'd'
-      endtry
-      Xpath 'e'
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-    Xpath 'f'
-  endfunc
-
-  call F()
-  call assert_equal('abcdef', g:Xpath)
-
-  delfunc F
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 66:  Stop range :call on error, interrupt, or :throw		    {{{1
-"
-"	    When a function which is multiply called for a range since it
-"	    doesn't handle the range itself has an error in a command
-"	    dynamically enclosed by :try/:endtry or gets an interrupt or
-"	    executes a :throw, no more calls for the remaining lines in the
-"	    range are made.  On an error in a command not dynamically enclosed
-"	    by :try/:endtry, the function is executed again for the remaining
-"	    lines in the range.
-"-------------------------------------------------------------------------------
-
-func Test_stop_range_on_error()
-  let test =<< trim [CODE]
-    let file = tempname()
-    exec "edit" file
-    call setline(1, ['line 1', 'line 2', 'line 3'])
-    let taken = ""
-    let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
-
-    func F(reason, n) abort
-      let g:taken = g:taken .. "F" .. a:n ..
-                          \ substitute(a:reason, '\(\l\).*', '\u\1', "") ..
-                          \ "(" .. line(".") .. ")"
-
-      if a:reason == "error"
-        asdf
-      elseif a:reason == "interrupt"
-        call interrupt()
-      elseif a:reason == "throw"
-        throw "xyz"
-      elseif a:reason == "aborting error"
-        XloopNEXT
-        call assert_equal(g:taken, g:expected)
-        try
-          bwipeout!
-          call delete(g:file)
-          asdf
-        endtry
-      endif
-    endfunc
-
-    func G(reason, n)
-      let g:taken = g:taken .. "G" .. a:n ..
-                              \ substitute(a:reason, '\(\l\).*', '\u\1', "")
-      1,3call F(a:reason, a:n)
-    endfunc
-
-    Xpath 'a'
-    call G("error", 1)
-    try
-      Xpath 'b'
-      try
-        call G("error", 2)
-        call assert_report('should not get here')
-      finally
-        Xpath 'c'
-        try
-          call G("interrupt", 3)
-          call assert_report('should not get here')
-        finally
-          Xpath 'd'
-          try
-            call G("throw", 4)
-            call assert_report('should not get here')
-          endtry
-        endtry
-      endtry
-    catch /xyz/
-      Xpath 'e'
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-    Xpath 'f'
-    call G("aborting error", 5)
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdef', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 67:  :throw across :call command					    {{{1
-"
-"	    On a call command, an exception might be thrown when evaluating the
-"	    function name, during evaluation of the arguments, or when the
-"	    function is being executed.  The exception can be caught by the
-"	    caller.
-"-------------------------------------------------------------------------------
-
-func THROW(x, n)
-  if a:n == 1
-    Xpath 'A'
-  elseif a:n == 2
-    Xpath 'B'
-  elseif a:n == 3
-    Xpath 'C'
-  endif
-  throw a:x
-endfunc
-
-func NAME(x, n)
-  if a:n == 1
-    call assert_report('should not get here')
-  elseif a:n == 2
-    Xpath 'D'
-  elseif a:n == 3
-    Xpath 'E'
-  elseif a:n == 4
-    Xpath 'F'
-  endif
-  return a:x
-endfunc
-
-func ARG(x, n)
-  if a:n == 1
-    call assert_report('should not get here')
-  elseif a:n == 2
-    call assert_report('should not get here')
-  elseif a:n == 3
-    Xpath 'G'
-  elseif a:n == 4
-    Xpath 'I'
-  endif
-  return a:x
-endfunc
-
-func Test_throw_across_call_cmd()
-  XpathINIT
-
-  func F(x, n)
-    if a:n == 2
-      call assert_report('should not get here')
-    elseif a:n == 4
-      Xpath 'a'
-    endif
-  endfunc
-
-  while 1
-    try
-      let v:errmsg = ""
-
-      while 1
-        try
-          Xpath 'b'
-          call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
-          call assert_report('should not get here')
-        catch /^name$/
-          Xpath 'c'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-
-      while 1
-        try
-          Xpath 'd'
-          call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
-          call assert_report('should not get here')
-        catch /^arg$/
-          Xpath 'e'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-
-      while 1
-        try
-          Xpath 'f'
-          call {NAME("THROW", 3)}(ARG("call", 3), 3)
-          call assert_report('should not get here')
-        catch /^call$/
-          Xpath 'g'
-        catch /^0$/	    " default return value
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-
-      while 1
-        try
-          Xpath 'h'
-          call {NAME("F", 4)}(ARG(4711, 4), 4)
-          Xpath 'i'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-
-    catch /^0$/	    " default return value
-      call assert_report('should not get here')
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      call assert_equal("", v:errmsg)
-      let v:errmsg = ""
-      break
-    endtry
-  endwhile
-
-  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
-  delfunction F
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 68:  :throw across function calls in expressions			    {{{1
-"
-"	    On a function call within an expression, an exception might be
-"	    thrown when evaluating the function name, during evaluation of the
-"	    arguments, or when the function is being executed.  The exception
-"	    can be caught by the caller.
-"
-"	    This test reuses the functions THROW(), NAME(), and ARG() from the
-"	    previous test.
-"-------------------------------------------------------------------------------
-
-func Test_throw_across_call_expr()
-  XpathINIT
-
-  func F(x, n)
-    if a:n == 2
-      call assert_report('should not get here')
-    elseif a:n == 4
-      Xpath 'a'
-    endif
-    return a:x
-  endfunction
-
-  while 1
-    try
-      let error = 0
-      let v:errmsg = ""
-
-      while 1
-        try
-          Xpath 'b'
-          let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
-          call assert_report('should not get here')
-        catch /^name$/
-          Xpath 'c'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-      call assert_true(!exists('var1'))
-
-      while 1
-        try
-          Xpath 'd'
-          let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
-          call assert_report('should not get here')
-        catch /^arg$/
-          Xpath 'e'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-      call assert_true(!exists('var2'))
-
-      while 1
-        try
-          Xpath 'f'
-          let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
-          call assert_report('should not get here')
-        catch /^call$/
-          Xpath 'g'
-        catch /^0$/	    " default return value
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-      call assert_true(!exists('var3'))
-
-      while 1
-        try
-          Xpath 'h'
-          let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
-          Xpath 'i'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          call assert_equal("", v:errmsg)
-          let v:errmsg = ""
-          break
-        endtry
-      endwhile
-      call assert_true(exists('var4') && var4 == 4711)
-
-    catch /^0$/	    " default return value
-      call assert_report('should not get here')
-    catch /.*/
-      call assert_report('should not get here')
-    finally
-      call assert_equal("", v:errmsg)
-      break
-    endtry
-  endwhile
-
-  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
-  delfunc F
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 76:  Errors, interrupts, :throw during expression evaluation	    {{{1
-"
-"	    When a function call made during expression evaluation is aborted
-"	    due to an error inside a :try/:endtry region or due to an interrupt
-"	    or a :throw, the expression evaluation is aborted as well.	No
-"	    message is displayed for the cancelled expression evaluation.  On an
-"	    error not inside :try/:endtry, the expression evaluation continues.
-"-------------------------------------------------------------------------------
-
-func Test_expr_eval_error()
-  let test =<< trim [CODE]
-    let taken = ""
-
-    func ERR(n)
-      let g:taken = g:taken .. "E" .. a:n
-      asdf
-    endfunc
-
-    func ERRabort(n) abort
-      let g:taken = g:taken .. "A" .. a:n
-      asdf
-    endfunc	" returns -1; may cause follow-up msg for illegal var/func name
-
-    func WRAP(n, arg)
-      let g:taken = g:taken .. "W" .. a:n
-      let g:saved_errmsg = v:errmsg
-      return arg
-    endfunc
-
-    func INT(n)
-      let g:taken = g:taken .. "I" .. a:n
-      call interrupt()
-    endfunc
-
-    func THR(n)
-      let g:taken = g:taken .. "T" .. a:n
-      throw "should not be caught"
-    endfunc
-
-    func CONT(n)
-      let g:taken = g:taken .. "C" .. a:n
-    endfunc
-
-    func MSG(n)
-      let g:taken = g:taken .. "M" .. a:n
-      let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
-      let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
-      call assert_match(msgptn, errmsg)
-      let v:errmsg = ""
-      let g:saved_errmsg = ""
-    endfunc
-
-    let v:errmsg = ""
-
-    try
-      let t = 1
-      while t <= 9
-        Xloop 'a'
-        try
-          if t == 1
-            let v{ERR(t) + CONT(t)} = 0
-          elseif t == 2
-            let v{ERR(t) + CONT(t)}
-          elseif t == 3
-            let var = exists('v{ERR(t) + CONT(t)}')
-          elseif t == 4
-            unlet v{ERR(t) + CONT(t)}
-          elseif t == 5
-            function F{ERR(t) + CONT(t)}()
-            endfunction
-          elseif t == 6
-            function F{ERR(t) + CONT(t)}
-          elseif t == 7
-            let var = exists('*F{ERR(t) + CONT(t)}')
-          elseif t == 8
-            delfunction F{ERR(t) + CONT(t)}
-          elseif t == 9
-            let var = ERR(t) + CONT(t)
-          endif
-        catch /asdf/
-          " v:errmsg is not set when the error message is converted to an
-          " exception.  Set it to the original error message.
-          let v:errmsg = substitute(v:exception, '^Vim:', '', "")
-        catch /^Vim\((\a\+)\)\=:/
-          " An error exception has been thrown after the original error.
-          let v:errmsg = ""
-        finally
-          call MSG(t)
-          let t = t + 1
-          XloopNEXT
-          continue	" discard an aborting error
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-
-    try
-      let t = 10
-      while t <= 18
-        Xloop 'b'
-        try
-          if t == 10
-            let v{INT(t) + CONT(t)} = 0
-          elseif t == 11
-            let v{INT(t) + CONT(t)}
-          elseif t == 12
-            let var = exists('v{INT(t) + CONT(t)}')
-          elseif t == 13
-            unlet v{INT(t) + CONT(t)}
-          elseif t == 14
-            function F{INT(t) + CONT(t)}()
-            endfunction
-          elseif t == 15
-            function F{INT(t) + CONT(t)}
-          elseif t == 16
-            let var = exists('*F{INT(t) + CONT(t)}')
-          elseif t == 17
-            delfunction F{INT(t) + CONT(t)}
-          elseif t == 18
-            let var = INT(t) + CONT(t)
-          endif
-        catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
-          " An error exception has been triggered after the interrupt.
-          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
-        finally
-          call MSG(t)
-          let t = t + 1
-          XloopNEXT
-          continue	" discard interrupt
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-
-    try
-      let t = 19
-      while t <= 27
-        Xloop 'c'
-        try
-          if t == 19
-            let v{THR(t) + CONT(t)} = 0
-          elseif t == 20
-            let v{THR(t) + CONT(t)}
-          elseif t == 21
-            let var = exists('v{THR(t) + CONT(t)}')
-          elseif t == 22
-            unlet v{THR(t) + CONT(t)}
-          elseif t == 23
-            function F{THR(t) + CONT(t)}()
-            endfunction
-          elseif t == 24
-            function F{THR(t) + CONT(t)}
-          elseif t == 25
-            let var = exists('*F{THR(t) + CONT(t)}')
-          elseif t == 26
-            delfunction F{THR(t) + CONT(t)}
-          elseif t == 27
-            let var = THR(t) + CONT(t)
-          endif
-        catch /^Vim\((\a\+)\)\=:/
-          " An error exception has been triggered after the :throw.
-          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
-        finally
-          call MSG(t)
-          let t = t + 1
-          XloopNEXT
-          continue	" discard exception
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-
-    let v{ERR(28) + CONT(28)} = 0
-    call MSG(28)
-    let v{ERR(29) + CONT(29)}
-    call MSG(29)
-    let var = exists('v{ERR(30) + CONT(30)}')
-    call MSG(30)
-    unlet v{ERR(31) + CONT(31)}
-    call MSG(31)
-    function F{ERR(32) + CONT(32)}()
-    endfunction
-    call MSG(32)
-    function F{ERR(33) + CONT(33)}
-    call MSG(33)
-    let var = exists('*F{ERR(34) + CONT(34)}')
-    call MSG(34)
-    delfunction F{ERR(35) + CONT(35)}
-    call MSG(35)
-    let var = ERR(36) + CONT(36)
-    call MSG(36)
-
-    let saved_errmsg = ""
-
-    let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
-    call MSG(37)
-    let v{WRAP(38, ERRabort(38)) + CONT(38)}
-    call MSG(38)
-    let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
-    call MSG(39)
-    unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
-    call MSG(40)
-    function F{WRAP(41, ERRabort(41)) + CONT(41)}()
-    endfunction
-    call MSG(41)
-    function F{WRAP(42, ERRabort(42)) + CONT(42)}
-    call MSG(42)
-    let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
-    call MSG(43)
-    delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
-    call MSG(44)
-    let var = ERRabort(45) + CONT(45)
-    call MSG(45)
-    Xpath 'd'
-
-    let expected = ""
-          \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
-          \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
-          \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
-          \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
-          \ .. "E34C34M34E35C35M35E36C36M36"
-          \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
-          \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
-    call assert_equal(expected, taken)
-  [CODE]
-  let verify =<< trim [CODE]
-    let expected = "a1a2a3a4a5a6a7a8a9"
-                      \ .. "b10b11b12b13b14b15b16b17b18"
-                      \ .. "c19c20c21c22c23c24c25c26c27d"
-    call assert_equal(expected, g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 77:  Errors, interrupts, :throw in name{brace-expression}	    {{{1
-"
-"	    When a function call made during evaluation of an expression in
-"	    braces as part of a function name after ":function" is aborted due
-"	    to an error inside a :try/:endtry region or due to an interrupt or
-"	    a :throw, the expression evaluation is aborted as well, and the
-"	    function definition is ignored, skipping all commands to the
-"	    ":endfunction".  On an error not inside :try/:endtry, the expression
-"	    evaluation continues and the function gets defined, and can be
-"	    called and deleted.
-"-------------------------------------------------------------------------------
-func Test_brace_expr_error()
-  let test =<< trim [CODE]
-    func ERR() abort
-      Xloop 'a'
-      asdf
-    endfunc					" returns -1
-
-    func OK()
-      Xloop 'b'
-      let v:errmsg = ""
-      return 0
-    endfunc
-
-    let v:errmsg = ""
-
-    Xpath 'c'
-    func F{1 + ERR() + OK()}(arg)
-      " F0 should be defined.
-      if exists("a:arg") && a:arg == "calling"
-        Xpath 'd'
-      else
-        call assert_report('should not get here')
-      endif
-    endfunction
-    call assert_equal("", v:errmsg)
-    XloopNEXT
-
-    Xpath 'e'
-    call F{1 + ERR() + OK()}("calling")
-    call assert_equal("", v:errmsg)
-    XloopNEXT
-
-    Xpath 'f'
-    delfunction F{1 + ERR() + OK()}
-    call assert_equal("", v:errmsg)
-    XloopNEXT
-
-    try
-      while 1
-        try
-          Xpath 'g'
-          func G{1 + ERR() + OK()}(arg)
-            " G0 should not be defined, and the function body should be
-            " skipped.
-            call assert_report('should not get here')
-            " Use an unmatched ":finally" to check whether the body is
-            " skipped when an error occurs in ERR().  This works whether or
-            " not the exception is converted to an exception.
-            finally
-              call assert_report('should not get here')
-            endtry
-          try
-            call assert_report('should not get here')
-          endfunction
-
-          call assert_report('should not get here')
-        catch /asdf/
-          " Jumped to when the function is not defined and the body is
-          " skipped.
-          Xpath 'h'
-        catch /.*/
-          call assert_report('should not get here')
-        finally
-          Xpath 'i'
-          break
-        endtry			" jumped to when the body is not skipped
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 78:  Messages on parsing errors in expression evaluation		    {{{1
-"
-"	    When an expression evaluation detects a parsing error, an error
-"	    message is given and converted to an exception, and the expression
-"	    evaluation is aborted.
-"-------------------------------------------------------------------------------
-func Test_expr_eval_error_msg()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    let taken = ""
-
-    func F(n)
-      let g:taken = g:taken . "F" . a:n
-    endfunc
-
-    func MSG(n, enr, emsg)
-      let g:taken = g:taken . "M" . a:n
-      call assert_match('^' .. a:enr .. ':', v:errmsg)
-      call assert_match(a:emsg, v:errmsg)
-    endfunc
-
-    func CONT(n)
-      let g:taken = g:taken . "C" . a:n
-    endfunc
-
-    let v:errmsg = ""
-    try
-      let t = 1
-      while t <= 14
-        let g:taken = g:taken . "T" . t
-        let v:errmsg = ""
-        try
-          if t == 1
-            let v{novar + CONT(t)} = 0
-          elseif t == 2
-            let v{novar + CONT(t)}
-          elseif t == 3
-            let var = exists('v{novar + CONT(t)}')
-          elseif t == 4
-            unlet v{novar + CONT(t)}
-          elseif t == 5
-            function F{novar + CONT(t)}()
-            endfunction
-          elseif t == 6
-            function F{novar + CONT(t)}
-          elseif t == 7
-            let var = exists('*F{novar + CONT(t)}')
-          elseif t == 8
-            delfunction F{novar + CONT(t)}
-          elseif t == 9
-            echo novar + CONT(t)
-          elseif t == 10
-            echo v{novar + CONT(t)}
-          elseif t == 11
-            echo F{novar + CONT(t)}
-          elseif t == 12
-            let var = novar + CONT(t)
-          elseif t == 13
-            let var = v{novar + CONT(t)}
-          elseif t == 14
-            let var = F{novar + CONT(t)}()
-          endif
-        catch /^Vim\((\a\+)\)\=:/
-          Xloop 'a'
-          " v:errmsg is not set when the error message is converted to an
-          " exception.  Set it to the original error message.
-          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
-        finally
-          Xloop 'b'
-          if t <= 8 && t != 3 && t != 7
-            call MSG(t, 'E475', 'Invalid argument\>')
-          else
-            call MSG(t, 'E121', "Undefined variable")
-          endif
-          let t = t + 1
-          XloopNEXT
-          continue	" discard an aborting error
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-
-    func T(n, expr, enr, emsg)
-      try
-        let g:taken = g:taken . "T" . a:n
-        let v:errmsg = ""
-        try
-          execute "let var = " . a:expr
-        catch /^Vim\((\a\+)\)\=:/
-          Xloop 'c'
-          " v:errmsg is not set when the error message is converted to an
-          " exception.  Set it to the original error message.
-          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
-        finally
-          Xloop 'd'
-          call MSG(a:n, a:enr, a:emsg)
-          XloopNEXT
-          " Discard an aborting error:
-          return
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      endtry
-    endfunc
-
-    call T(15, 'Nofunc() + CONT(15)',	'E117',	"Unknown function")
-    call T(16, 'F(1 2 + CONT(16))',	'E116',	"Invalid arguments")
-    call T(17, 'F(1, 2) + CONT(17)',	'E118',	"Too many arguments")
-    call T(18, 'F() + CONT(18)',	'E119',	"Not enough arguments")
-    call T(19, '{(1} + CONT(19)',	'E110',	"Missing ')'")
-    call T(20, '("abc"[1) + CONT(20)',	'E111',	"Missing ']'")
-    call T(21, '(1 +) + CONT(21)',	'E15',	"Invalid expression")
-    call T(22, '1 2 + CONT(22)',	'E488',	"Trailing characters: 2 +")
-    call T(23, '(1 ? 2) + CONT(23)',	'E109',	"Missing ':' after '?'")
-    call T(24, '("abc) + CONT(24)',	'E114',	"Missing double quote")
-    call T(25, "('abc) + CONT(25)",	'E115',	"Missing single quote")
-    call T(26, '& + CONT(26)',		'E112', "Option name missing")
-    call T(27, '&asdf + CONT(27)',	'E113', "Unknown option")
-
-    let expected = ""
-      \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
-      \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
-      \ .. "T26M26T27M27"
-
-    call assert_equal(expected, taken)
-  [CODE]
-  let verify =<< trim [CODE]
-    let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12"
-                  \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20"
-                  \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27"
-    call assert_equal(expected, g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 79:  Throwing one of several errors for the same command		    {{{1
-"
-"	    When several errors appear in a row (for instance during expression
-"	    evaluation), the first as the most specific one is used when
-"	    throwing an error exception.  If, however, a syntax error is
-"	    detected afterwards, this one is used for the error exception.
-"	    On a syntax error, the next command is not executed, on a normal
-"	    error, however, it is (relevant only in a function without the
-"	    "abort" flag).  v:errmsg is not set.
-"
-"	    If throwing error exceptions is configured off, v:errmsg is always
-"	    set to the latest error message, that is, to the more general
-"	    message or the syntax error, respectively.
-"-------------------------------------------------------------------------------
-func Test_throw_multi_error()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    func NEXT(cmd)
-      exec a:cmd . " | Xloop 'a'"
-    endfun
-
-    call NEXT('echo novar')			" (checks nextcmd)
-    XloopNEXT
-    call NEXT('let novar #')			" (skips nextcmd)
-    XloopNEXT
-    call NEXT('unlet novar #')			" (skips nextcmd)
-    XloopNEXT
-    call NEXT('let {novar}')			" (skips nextcmd)
-    XloopNEXT
-    call NEXT('unlet{ novar}')			" (skips nextcmd)
-
-    call assert_equal('a1', g:Xpath)
-    XpathINIT
-    XloopINIT
-
-    func EXEC(cmd)
-      exec a:cmd
-    endfunc
-
-    try
-      while 1				" dummy loop
-        try
-          let v:errmsg = ""
-          call EXEC('echo novar')	" normal error
-        catch /^Vim\((\a\+)\)\=:/
-          Xpath 'b'
-          call assert_match('E121: Undefined variable: novar', v:exception)
-        finally
-          Xpath 'c'
-          call assert_equal("", v:errmsg)
-          break
-        endtry
-      endwhile
-
-      Xpath 'd'
-      let cmd = "let"
-      while cmd != ""
-        try
-          let v:errmsg = ""
-          call EXEC(cmd . ' novar #')		" normal plus syntax error
-        catch /^Vim\((\a\+)\)\=:/
-          Xloop 'e'
-          if cmd =~ 'unlet'
-            " TODO: should get error for 'novar'
-            call assert_match('E488: Trailing characters', v:exception)
-          else
-            call assert_match('E121: Undefined variable: novar', v:exception)
-          endif
-        finally
-          Xloop 'f'
-          call assert_equal("", v:errmsg)
-          if cmd == "let"
-            let cmd = "unlet"
-          else
-            let cmd = ""
-          endif
-          XloopNEXT
-          continue
-        endtry
-      endwhile
-
-      Xpath 'g'
-      let cmd = "let"
-      while cmd != ""
-        try
-          let v:errmsg = ""
-          call EXEC(cmd . ' {novar}')		" normal plus syntax error
-        catch /^Vim\((\a\+)\)\=:/
-          Xloop 'h'
-          call assert_match('E475: Invalid argument: {novar}', v:exception)
-        finally
-          Xloop 'i'
-          call assert_equal("", v:errmsg)
-          if cmd == "let"
-            let cmd = "unlet"
-          else
-            let cmd = ""
-          endif
-          XloopNEXT
-          continue
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-    Xpath 'j'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 80:  Syntax error in expression for illegal :elseif		    {{{1
-"
-"	    If there is a syntax error in the expression after an illegal
-"	    :elseif, an error message is given (or an error exception thrown)
-"	    for the illegal :elseif rather than the expression error.
-"-------------------------------------------------------------------------------
-func Test_if_syntax_error()
-  CheckEnglish
-
-  let test =<< trim [CODE]
-    let v:errmsg = ""
-    if 0
-    else
-    elseif 1 ||| 2
-    endif
-    Xpath 'a'
-    call assert_match('E584: :elseif after :else', v:errmsg)
-
-    let v:errmsg = ""
-    if 1
-    else
-    elseif 1 ||| 2
-    endif
-    Xpath 'b'
-    call assert_match('E584: :elseif after :else', v:errmsg)
-
-    let v:errmsg = ""
-    elseif 1 ||| 2
-    Xpath 'c'
-    call assert_match('E582: :elseif without :if', v:errmsg)
-
-    let v:errmsg = ""
-    while 1
-      elseif 1 ||| 2
-    endwhile
-    Xpath 'd'
-    call assert_match('E582: :elseif without :if', v:errmsg)
-
-    while 1
-      try
-        try
-          let v:errmsg = ""
-          if 0
-          else
-          elseif 1 ||| 2
-          endif
-        catch /^Vim\((\a\+)\)\=:/
-          Xpath 'e'
-          call assert_match('E584: :elseif after :else', v:exception)
-        finally
-          Xpath 'f'
-          call assert_equal("", v:errmsg)
-        endtry
-      catch /.*/
-      call assert_report('should not get here')
-      finally
-        Xpath 'g'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          let v:errmsg = ""
-          if 1
-          else
-          elseif 1 ||| 2
-          endif
-        catch /^Vim\((\a\+)\)\=:/
-          Xpath 'h'
-          call assert_match('E584: :elseif after :else', v:exception)
-        finally
-          Xpath 'i'
-          call assert_equal("", v:errmsg)
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'j'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          let v:errmsg = ""
-          elseif 1 ||| 2
-        catch /^Vim\((\a\+)\)\=:/
-          Xpath 'k'
-          call assert_match('E582: :elseif without :if', v:exception)
-        finally
-          Xpath 'l'
-          call assert_equal("", v:errmsg)
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'm'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          let v:errmsg = ""
-          while 1
-              elseif 1 ||| 2
-          endwhile
-        catch /^Vim\((\a\+)\)\=:/
-          Xpath 'n'
-          call assert_match('E582: :elseif without :if', v:exception)
-        finally
-          Xpath 'o'
-          call assert_equal("", v:errmsg)
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'p'
-        break
-      endtry
-    endwhile
-    Xpath 'q'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghijklmnopq', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 81:  Discarding exceptions after an error or interrupt		    {{{1
-"
-"	    When an exception is thrown from inside a :try conditional without
-"	    :catch and :finally clauses and an error or interrupt occurs before
-"	    the :endtry is reached, the exception is discarded.
-"-------------------------------------------------------------------------------
-
-func Test_discard_exception_after_error_1()
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      try
-        Xpath 'b'
-        throw "arrgh"
-        call assert_report('should not get here')
-        if 1
-        call assert_report('should not get here')
-        " error after :throw: missing :endif
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('ab', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-" interrupt the code before the endtry is invoked
-func Test_discard_exception_after_error_2()
-  XpathINIT
-  let lines =<< trim [CODE]
-    try
-      Xpath 'a'
-      try
-        Xpath 'b'
-        throw "arrgh"
-        call assert_report('should not get here')
-      endtry                      " interrupt here
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  call writefile(lines, 'Xscript', 'D')
-
-  breakadd file 7 Xscript
-  try
-    let caught_intr = 0
-    debuggreedy
-    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
-  catch /^Vim:Interrupt$/
-    call assert_match('Xscript, line 7', v:throwpoint)
-    let caught_intr = 1
-  endtry
-  0debuggreedy
-  call assert_equal(1, caught_intr)
-  call assert_equal('ab', g:Xpath)
-  breakdel *
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 82:  Ignoring :catch clauses after an error or interrupt		    {{{1
-"
-"	    When an exception is thrown and an error or interrupt occurs before
-"	    the matching :catch clause is reached, the exception is discarded
-"	    and the :catch clause is ignored (also for the error or interrupt
-"	    exception being thrown then).
-"-------------------------------------------------------------------------------
-
-func Test_ignore_catch_after_error_1()
-  let test =<< trim [CODE]
-    try
-      try
-        Xpath 'a'
-        throw "arrgh"
-        call assert_report('should not get here')
-        if 1
-        call assert_report('should not get here')
-        " error after :throw: missing :endif
-      catch /.*/
-        call assert_report('should not get here')
-      catch /.*/
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-func Test_ignore_catch_after_error_2()
-  let test =<< trim [CODE]
-    func E()
-      try
-        try
-          Xpath 'a'
-          throw "arrgh"
-          call assert_report('should not get here')
-          if 1
-          call assert_report('should not get here')
-          " error after :throw: missing :endif
-        catch /.*/
-          call assert_report('should not get here')
-        catch /.*/
-          call assert_report('should not get here')
-        endtry
-        call assert_report('should not get here')
-      catch /arrgh/
-        call assert_report('should not get here')
-      endtry
-    endfunc
-
-    call E()
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('a', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-" interrupt right before a catch is invoked in a script
-func Test_ignore_catch_after_intr_1()
-  " for unknown reasons this test sometimes fails on MS-Windows.
-  let g:test_is_flaky = 1
-
-  XpathINIT
-  let lines =<< trim [CODE]
-    try
-      try
-        Xpath 'a'
-        throw "arrgh"
-        call assert_report('should not get here')
-      catch /.*/              " interrupt here
-        call assert_report('should not get here')
-      catch /.*/
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  call writefile(lines, 'Xscript', 'D')
-
-  breakadd file 6 Xscript
-  try
-    let caught_intr = 0
-    debuggreedy
-    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
-  catch /^Vim:Interrupt$/
-    call assert_match('Xscript, line 6', v:throwpoint)
-    let caught_intr = 1
-  endtry
-  0debuggreedy
-  call assert_equal(1, caught_intr)
-  call assert_equal('a', g:Xpath)
-  breakdel *
-endfunc
-
-" interrupt right before a catch is invoked inside a function.
-func Test_ignore_catch_after_intr_2()
-  " for unknown reasons this test sometimes fails on MS-Windows.
-  let g:test_is_flaky = 1
-
-  XpathINIT
-  func F()
-    try
-      try
-        Xpath 'a'
-        throw "arrgh"
-        call assert_report('should not get here')
-      catch /.*/              " interrupt here
-        call assert_report('should not get here')
-      catch /.*/
-        call assert_report('should not get here')
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  endfunc
-
-  breakadd func 6 F
-  try
-    let caught_intr = 0
-    debuggreedy
-    call feedkeys(":call F()\<CR>quit\<CR>", "xt")
-  catch /^Vim:Interrupt$/
-    call assert_match('\.F, line 6', v:throwpoint)
-    let caught_intr = 1
-  endtry
-  0debuggreedy
-  call assert_equal(1, caught_intr)
-  call assert_equal('a', g:Xpath)
-  breakdel *
-  delfunc F
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 83:  Executing :finally clauses after an error or interrupt	    {{{1
-"
-"	    When an exception is thrown and an error or interrupt occurs before
-"	    the :finally of the innermost :try is reached, the exception is
-"	    discarded and the :finally clause is executed.
-"-------------------------------------------------------------------------------
-
-func Test_finally_after_error()
-  let test =<< trim [CODE]
-    try
-      Xpath 'a'
-      try
-        Xpath 'b'
-        throw "arrgh"
-        call assert_report('should not get here')
-        if 1
-        call assert_report('should not get here')
-        " error after :throw: missing :endif
-      finally
-        Xpath 'c'
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abc', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-" interrupt the code right before the finally is invoked
-func Test_finally_after_intr()
-  XpathINIT
-  let lines =<< trim [CODE]
-    try
-      Xpath 'a'
-      try
-        Xpath 'b'
-        throw "arrgh"
-        call assert_report('should not get here')
-      finally		" interrupt here
-        Xpath 'c'
-      endtry
-      call assert_report('should not get here')
-    catch /arrgh/
-      call assert_report('should not get here')
-    endtry
-    call assert_report('should not get here')
-  [CODE]
-  call writefile(lines, 'Xscript', 'D')
-
-  breakadd file 7 Xscript
-  try
-    let caught_intr = 0
-    debuggreedy
-    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
-  catch /^Vim:Interrupt$/
-    call assert_match('Xscript, line 7', v:throwpoint)
-    let caught_intr = 1
-  endtry
-  0debuggreedy
-  call assert_equal(1, caught_intr)
-  call assert_equal('abc', g:Xpath)
-  breakdel *
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 84:  Exceptions in autocommand sequences.			    {{{1
-"
-"	    When an exception occurs in a sequence of autocommands for
-"	    a specific event, the rest of the sequence is not executed.  The
-"	    command that triggered the autocommand execution aborts, and the
-"	    exception is propagated to the caller.
-"
-"	    For the FuncUndefined event under a function call expression or
-"	    :call command, the function is not executed, even when it has
-"	    been defined by the autocommands before the exception occurred.
-"-------------------------------------------------------------------------------
-
-func Test_autocmd_exception()
-  let test =<< trim [CODE]
-    func INT()
-      call interrupt()
-    endfunc
-
-    aug TMP
-      autocmd!
-
-      autocmd User x1 Xpath 'a'
-      autocmd User x1 throw "x1"
-      autocmd User x1 call assert_report('should not get here')
-
-      autocmd User x2 Xpath 'b'
-      autocmd User x2 asdf
-      autocmd User x2 call assert_report('should not get here')
-
-      autocmd User x3 Xpath 'c'
-      autocmd User x3 call INT()
-      autocmd User x3 call assert_report('should not get here')
-
-      autocmd FuncUndefined U1 func U1()
-      autocmd FuncUndefined U1   call assert_report('should not get here')
-      autocmd FuncUndefined U1 endfunc
-      autocmd FuncUndefined U1 Xpath 'd'
-      autocmd FuncUndefined U1 throw "U1"
-      autocmd FuncUndefined U1 call assert_report('should not get here')
-
-      autocmd FuncUndefined U2 func U2()
-      autocmd FuncUndefined U2   call assert_report('should not get here')
-      autocmd FuncUndefined U2 endfunc
-      autocmd FuncUndefined U2 Xpath 'e'
-      autocmd FuncUndefined U2 ASDF
-      autocmd FuncUndefined U2 call assert_report('should not get here')
-
-      autocmd FuncUndefined U3 func U3()
-      autocmd FuncUndefined U3   call assert_report('should not get here')
-      autocmd FuncUndefined U3 endfunc
-      autocmd FuncUndefined U3 Xpath 'f'
-      autocmd FuncUndefined U3 call INT()
-      autocmd FuncUndefined U3 call assert_report('should not get here')
-    aug END
-
-    try
-      try
-        Xpath 'g'
-        doautocmd User x1
-      catch /x1/
-        Xpath 'h'
-      endtry
-
-      while 1
-        try
-          Xpath 'i'
-          doautocmd User x2
-        catch /asdf/
-          Xpath 'j'
-        finally
-          Xpath 'k'
-          break
-        endtry
-      endwhile
-
-      while 1
-        try
-          Xpath 'l'
-          doautocmd User x3
-        catch /Vim:Interrupt/
-          Xpath 'm'
-        finally
-          Xpath 'n'
-          " ... but break loop for caught interrupt exception,
-          " or discard interrupt and break loop if $VIMNOINTTHROW
-          break
-        endtry
-      endwhile
-
-      if exists("*U1") | delfunction U1 | endif
-      if exists("*U2") | delfunction U2 | endif
-      if exists("*U3") | delfunction U3 | endif
-
-      try
-        Xpath 'o'
-        call U1()
-      catch /U1/
-        Xpath 'p'
-      endtry
-
-      while 1
-        try
-          Xpath 'q'
-          call U2()
-        catch /ASDF/
-          Xpath 'r'
-        finally
-          Xpath 's'
-          " ... but break loop for caught error exception,
-          " or discard error and break loop if $VIMNOERRTHROW
-          break
-        endtry
-      endwhile
-
-      while 1
-        try
-          Xpath 't'
-          call U3()
-        catch /Vim:Interrupt/
-          Xpath 'u'
-        finally
-          Xpath 'v'
-          " ... but break loop for caught interrupt exception,
-          " or discard interrupt and break loop if $VIMNOINTTHROW
-          break
-        endtry
-      endwhile
-    catch /.*/
-      call assert_report('should not get here')
-    endtry
-    Xpath 'w'
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 85:  Error exceptions in autocommands for I/O command events	    {{{1
-"
-"	    When an I/O command is inside :try/:endtry, autocommands to be
-"	    executed after it should be skipped on an error (exception) in the
-"	    command itself or in autocommands to be executed before the command.
-"	    In the latter case, the I/O command should not be executed either.
-"	    Example 1: BufWritePre, :write, BufWritePost
-"	    Example 2: FileReadPre, :read, FileReadPost.
-"-------------------------------------------------------------------------------
-
-func Test_autocmd_error_io_exception()
-  let test =<< trim [CODE]
-    " Remove the autocommands for the events specified as arguments in all used
-    " autogroups.
-    func Delete_autocommands(...)
-      let augfile = tempname()
-      while 1
-        try
-          exec "redir >" . augfile
-          aug
-          redir END
-          exec "edit" augfile
-          g/^$/d
-          norm G$
-          let wrap = "w"
-          while search('\%(  \|^\)\@<=.\{-}\%(  \)\@=', wrap) > 0
-            let wrap = "W"
-            exec "norm y/  \n"
-            let argno = 1
-            while argno <= a:0
-              exec "au!" escape(@", " ") a:{argno}
-              let argno = argno + 1
-            endwhile
-          endwhile
-        catch /.*/
-        finally
-          bwipeout!
-          call delete(augfile)
-          break
-        endtry
-      endwhile
-    endfunc
-
-    call Delete_autocommands("BufWritePre", "BufWritePost")
-
-    while 1
-      try
-        try
-          let post = 0
-          aug TMP
-            au! BufWritePost * let post = 1
-          aug END
-          write /n/o/n/e/x/i/s/t/e/n/t
-        catch /^Vim(write):/
-          Xpath 'a'
-          call assert_match("E212: Can't open file for writing", v:exception)
-        finally
-          Xpath 'b'
-          call assert_equal(0, post)
-          au! TMP
-          aug! TMP
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'c'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        try
-          let post = 0
-          aug TMP
-            au! BufWritePre  * asdf
-            au! BufWritePost * let post = 1
-          aug END
-          let tmpfile = tempname()
-          exec "write" tmpfile
-        catch /^Vim\((write)\)\=:/
-          Xpath 'd'
-          call assert_match('E492: Not an editor command', v:exception)
-        finally
-          Xpath 'e'
-          if filereadable(tmpfile)
-            call assert_report('should not get here')
-          endif
-          call assert_equal(0, post)
-          au! TMP
-          aug! TMP
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'f'
-        break
-      endtry
-    endwhile
-
-    call delete(tmpfile)
-
-    call Delete_autocommands("BufWritePre", "BufWritePost",
-          \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
-
-    while 1
-      try
-        try
-          let post = 0
-          aug TMP
-            au! FileReadPost * let post = 1
-          aug END
-          let caught = 0
-          read /n/o/n/e/x/i/s/t/e/n/t
-        catch /^Vim(read):/
-          Xpath 'g'
-          call assert_match("E484: Can't open file", v:exception)
-        finally
-          Xpath 'h'
-          call assert_equal(0, post)
-          au! TMP
-          aug! TMP
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'i'
-        break
-      endtry
-    endwhile
-
-    while 1
-      try
-        let infile = tempname()
-        let tmpfile = tempname()
-        call writefile(["XYZ"], infile)
-        exec "edit" tmpfile
-        try
-          Xpath 'j'
-          try
-            let post = 0
-            aug TMP
-              au! FileReadPre  * asdf
-              au! FileReadPost * let post = 1
-            aug END
-            exec "0read" infile
-          catch /^Vim\((read)\)\=:/
-            Xpath 'k'
-            call assert_match('E492: Not an editor command', v:exception)
-          finally
-            Xpath 'l'
-            if getline("1") == "XYZ"
-              call assert_report('should not get here')
-            endif
-            call assert_equal(0, post)
-            au! TMP
-            aug! TMP
-          endtry
-        finally
-          Xpath 'm'
-          bwipeout!
-        endtry
-      catch /.*/
-        call assert_report('should not get here')
-      finally
-        Xpath 'n'
-        break
-      endtry
-    endwhile
-
-    call delete(infile)
-    call delete(tmpfile)
-  [CODE]
-  let verify =<< trim [CODE]
-    call assert_equal('abcdefghijklmn', g:Xpath)
-  [CODE]
-  call RunInNewVim(test, verify)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 87   using (expr) ? funcref : funcref				    {{{1
-"
-"	    Vim needs to correctly parse the funcref and even when it does
-"	    not execute the funcref, it needs to consume the trailing ()
-"-------------------------------------------------------------------------------
-
-func Add2(x1, x2)
-  return a:x1 + a:x2
-endfu
-
-func GetStr()
-  return "abcdefghijklmnopqrstuvwxyp"
-endfu
-
-func Test_funcref_with_condexpr()
-  call assert_equal(5, function('Add2')(2,3))
-
-  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
-  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
-  " Make sure, GetStr() still works.
-  call assert_equal('abcdefghijk', GetStr()[0:10])
-endfunc
-
-" Test 90:  Recognizing {} in variable name.			    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_curlies()
-    let s:var = 66
-    let ns = 's'
-    call assert_equal(66, {ns}:var)
-
-    let g:a = {}
-    let g:b = 't'
-    let g:a[g:b] = 77
-    call assert_equal(77, g:a['t'])
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 91:  using type().					    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_type()
-    call assert_equal(0, type(0))
-    call assert_equal(1, type(""))
-    call assert_equal(2, type(function("tr")))
-    call assert_equal(2, type(function("tr", [8])))
-    call assert_equal(3, type([]))
-    call assert_equal(4, type({}))
-    call assert_equal(5, type(0.0))
-    call assert_equal(6, type(v:false))
-    call assert_equal(6, type(v:true))
-    call assert_equal(7, type(v:none))
-    call assert_equal(7, type(v:null))
-    call assert_equal(8, v:t_job)
-    call assert_equal(9, v:t_channel)
-    call assert_equal(v:t_number, type(0))
-    call assert_equal(v:t_string, type(""))
-    call assert_equal(v:t_func, type(function("tr")))
-    call assert_equal(v:t_func, type(function("tr", [8])))
-    call assert_equal(v:t_list, type([]))
-    call assert_equal(v:t_dict, type({}))
-    call assert_equal(v:t_float, type(0.0))
-    call assert_equal(v:t_bool, type(v:false))
-    call assert_equal(v:t_bool, type(v:true))
-    call assert_equal(v:t_none, type(v:none))
-    call assert_equal(v:t_none, type(v:null))
-    call assert_equal(v:t_string, type(test_null_string()))
-    call assert_equal(v:t_func, type(test_null_function()))
-    call assert_equal(v:t_func, type(test_null_partial()))
-    call assert_equal(v:t_list, type(test_null_list()))
-    call assert_equal(v:t_dict, type(test_null_dict()))
-    if has('job')
-      call assert_equal(v:t_job, type(test_null_job()))
-    endif
-    if has('channel')
-      call assert_equal(v:t_channel, type(test_null_channel()))
-    endif
-    call assert_equal(v:t_blob, type(test_null_blob()))
-
-    call assert_fails("call type(test_void())", ['E340:', 'E685:'])
-    call assert_fails("call type(test_unknown())", ['E340:', 'E685:'])
-
-    call assert_equal(0, 0 + v:false)
-    call assert_equal(1, 0 + v:true)
-    call assert_equal(0, 0 + v:none)
-    call assert_equal(0, 0 + v:null)
-
-    call assert_equal('v:false', '' . v:false)
-    call assert_equal('v:true', '' . v:true)
-    call assert_equal('v:none', '' . v:none)
-    call assert_equal('v:null', '' . v:null)
-
-    call assert_true(v:false == 0)
-    call assert_false(v:false != 0)
-    call assert_true(v:true == 1)
-    call assert_false(v:true != 1)
-    call assert_false(v:true == v:false)
-    call assert_true(v:true != v:false)
-
-    call assert_true(v:null == 0)
-    call assert_false(v:null == 1)
-    call assert_false(v:null != 0)
-    call assert_true(v:none == 0)
-    call assert_false(v:none == 1)
-    call assert_false(v:none != 0)
-    call assert_true(v:null == 0.0)
-    call assert_false(v:null == 0.1)
-    call assert_false(v:null != 0.0)
-
-    call assert_true(v:false is v:false)
-    call assert_true(v:true is v:true)
-    call assert_true(v:none is v:none)
-    call assert_true(v:null is v:null)
-
-    call assert_false(v:false isnot v:false)
-    call assert_false(v:true isnot v:true)
-    call assert_false(v:none isnot v:none)
-    call assert_false(v:null isnot v:null)
-
-    call assert_false(v:false is 0)
-    call assert_false(v:true is 1)
-    call assert_false(v:true is v:false)
-    call assert_false(v:none is 0)
-    call assert_false(v:none is [])
-    call assert_false(v:none is {})
-    call assert_false(v:none is 'text')
-    call assert_false(v:null is 0)
-    call assert_false(v:null is v:none)
-
-    call assert_true(v:false isnot 0)
-    call assert_true(v:true isnot 1)
-    call assert_true(v:true isnot v:false)
-    call assert_true(v:none isnot 0)
-    call assert_true(v:null isnot 0)
-    call assert_true(v:null isnot v:none)
-
-    call assert_equal(v:false, eval(string(v:false)))
-    call assert_equal(v:true, eval(string(v:true)))
-    call assert_equal(v:none, eval(string(v:none)))
-    call assert_equal(v:null, eval(string(v:null)))
-
-    call assert_equal(v:false, copy(v:false))
-    call assert_equal(v:true, copy(v:true))
-    call assert_equal(v:none, copy(v:none))
-    call assert_equal(v:null, copy(v:null))
-
-    call assert_equal([v:false], deepcopy([v:false]))
-    call assert_equal([v:true], deepcopy([v:true]))
-    call assert_equal([v:none], deepcopy([v:none]))
-    call assert_equal([v:null], deepcopy([v:null]))
-
-    call assert_true(empty(v:false))
-    call assert_false(empty(v:true))
-    call assert_true(empty(v:null))
-    call assert_true(empty(v:none))
-
-    func ChangeYourMind()
-	try
-	    return v:true
-	finally
-	    return 'something else'
-	endtry
-    endfunc
-
-    call ChangeYourMind()
-endfunc
-
-func Test_typename()
-  call assert_equal('number', typename(123))
-  call assert_equal('string', typename('x'))
-  call assert_equal('list<number>', typename([123]))
-  call assert_equal('dict<number>', typename(#{key: 123}))
-  call assert_equal('list<dict<number>>', typename([#{key: 123}]))
-
-  let l = []
-  let d = #{a: 0}
-  let l = [d]
-  let l[0].e = #{b: l}
-  call assert_equal('list<dict<any>>', typename(l))
-  call assert_equal('dict<any>', typename(d))
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 92:  skipping code					    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_skip()
-    let Fn = function('Test_type')
-    call assert_false(0 && Fn[1])
-    call assert_false(0 && string(Fn))
-    call assert_false(0 && len(Fn))
-    let l = []
-    call assert_false(0 && l[1])
-    call assert_false(0 && string(l))
-    call assert_false(0 && len(l))
-    let f = 1.0
-    call assert_false(0 && f[1])
-    call assert_false(0 && string(f))
-    call assert_false(0 && len(f))
-    let sp = v:null
-    call assert_false(0 && sp[1])
-    call assert_false(0 && string(sp))
-    call assert_false(0 && len(sp))
-
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 93:  :echo and string()					    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_echo_and_string()
-    " String
-    let a = 'foo bar'
-    redir => result
-    echo a
-    echo string(a)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["foo bar",
-		     \ "'foo bar'"], l)
-
-    " Float
-    let a = -1.2e0
-    redir => result
-    echo a
-    echo string(a)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["-1.2",
-                     \ "-1.2"], l)
-
-    " Funcref
-    redir => result
-    echo function('string')
-    echo string(function('string'))
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["string",
-		     \ "function('string')"], l)
-
-    " Recursive dictionary
-    let a = {}
-    let a["a"] = a
-    redir => result
-    echo a
-    echo string(a)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["{'a': {...}}",
-		     \ "{'a': {...}}"], l)
-
-    " Recursive list
-    let a = [0]
-    let a[0] = a
-    redir => result
-    echo a
-    echo string(a)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["[[...]]",
-		     \ "[[...]]"], l)
-
-    " Empty dictionaries in a list
-    let a = {}
-    redir => result
-    echo [a, a, a]
-    echo string([a, a, a])
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["[{}, {}, {}]",
-		     \ "[{}, {}, {}]"], l)
-
-    " Empty dictionaries in a dictionary
-    let a = {}
-    let b = {"a": a, "b": a}
-    redir => result
-    echo b
-    echo string(b)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["{'a': {}, 'b': {}}",
-		     \ "{'a': {}, 'b': {}}"], l)
-
-    " Empty lists in a list
-    let a = []
-    redir => result
-    echo [a, a, a]
-    echo string([a, a, a])
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["[[], [], []]",
-		     \ "[[], [], []]"], l)
-
-    " Empty lists in a dictionary
-    let a = []
-    let b = {"a": a, "b": a}
-    redir => result
-    echo b
-    echo string(b)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["{'a': [], 'b': []}",
-		     \ "{'a': [], 'b': []}"], l)
-
-    " Dictionaries in a list
-    let a = {"one": "yes", "two": "yes", "three": "yes"}
-    redir => result
-    echo [a, a, a]
-    echo string([a, a, a])
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
-		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
-
-    " Dictionaries in a dictionary
-    let a = {"one": "yes", "two": "yes", "three": "yes"}
-    let b = {"a": a, "b": a}
-    redir => result
-    echo b
-    echo string(b)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
-		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
-
-    " Lists in a list
-    let a = [1, 2, 3]
-    redir => result
-    echo [a, a, a]
-    echo string([a, a, a])
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["[[1, 2, 3], [...], [...]]",
-		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
-
-    " Lists in a dictionary
-    let a = [1, 2, 3]
-    let b = {"a": a, "b": a}
-    redir => result
-    echo b
-    echo string(b)
-    redir END
-    let l = split(result, "\n")
-    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
-		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
-
-    call assert_fails('echo &:', 'E112:')
-    call assert_fails('echo &g:', 'E112:')
-    call assert_fails('echo &l:', 'E112:')
-
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 94:  64-bit Numbers					    {{{1
-"-------------------------------------------------------------------------------
-
-func Test_num64()
-    call assert_notequal( 4294967296, 0)
-    call assert_notequal(-4294967296, 0)
-    call assert_equal( 4294967296,  0xFFFFffff + 1)
-    call assert_equal(-4294967296, -0xFFFFffff - 1)
-
-    call assert_equal( 9223372036854775807,  1 / 0)
-    call assert_equal(-9223372036854775807, -1 / 0)
-    call assert_equal(-9223372036854775807 - 1,  0 / 0)
-
-    call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
-    call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
-
-    let rng = range(0xFFFFffff, 0x100000001)
-    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
-    call assert_equal(0x100000001, max(rng))
-    call assert_equal(0xFFFFffff, min(rng))
-    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 95:  lines of :append, :change, :insert			    {{{1
-"-------------------------------------------------------------------------------
-
-func DefineFunction(name, body)
-    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
-    exec func
-endfunc
-
-func Test_script_lines()
-    " :append
-    try
-	call DefineFunction('T_Append', [
-		    \ 'append',
-		    \ 'py <<EOS',
-		    \ '.',
-		    \ ])
-    catch
-	call assert_report("Can't define function")
-    endtry
-    try
-	call DefineFunction('T_Append', [
-		    \ 'append',
-		    \ 'abc',
-		    \ ])
-	call assert_report("Shouldn't be able to define function")
-    catch
-	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
-    endtry
-
-    " :change
-    try
-	call DefineFunction('T_Change', [
-		    \ 'change',
-		    \ 'py <<EOS',
-		    \ '.',
-		    \ ])
-    catch
-	call assert_report("Can't define function")
-    endtry
-    try
-	call DefineFunction('T_Change', [
-		    \ 'change',
-		    \ 'abc',
-		    \ ])
-	call assert_report("Shouldn't be able to define function")
-    catch
-	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
-    endtry
-
-    " :insert
-    try
-	call DefineFunction('T_Insert', [
-		    \ 'insert',
-		    \ 'py <<EOS',
-		    \ '.',
-		    \ ])
-    catch
-	call assert_report("Can't define function")
-    endtry
-    try
-	call DefineFunction('T_Insert', [
-		    \ 'insert',
-		    \ 'abc',
-		    \ ])
-	call assert_report("Shouldn't be able to define function")
-    catch
-	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
-    endtry
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 96:  line continuation						    {{{1
-"
-"	    Undefined behavior was detected by ubsan with line continuation
-"	    after an empty line.
-"-------------------------------------------------------------------------------
-func Test_script_empty_line_continuation()
-
-    \
-endfunc
-
-"-------------------------------------------------------------------------------
-" Test 97:  bitwise functions						    {{{1
-"-------------------------------------------------------------------------------
-func Test_bitwise_functions()
-    " and
-    call assert_equal(127, and(127, 127))
-    call assert_equal(16, and(127, 16))
-    eval 127->and(16)->assert_equal(16)
-    call assert_equal(0, and(127, 128))
-    call assert_fails("call and([], 1)", 'E745:')
-    call assert_fails("call and({}, 1)", 'E728:')
-    call assert_fails("call and(1.0, 1)", 'E805:')
-    call assert_fails("call and(1, 1.0)", 'E805:')
-    call assert_fails("call and(1, [])", 'E745:')
-    call assert_fails("call and(1, {})", 'E728:')
-    " or
-    call assert_equal(23, or(16, 7))
-    call assert_equal(15, or(8, 7))
-    eval 8->or(7)->assert_equal(15)
-    call assert_equal(123, or(0, 123))
-    call assert_fails("call or([], 1)", 'E745:')
-    call assert_fails("call or({}, 1)", 'E728:')
-    call assert_fails("call or(1.0, 1)", 'E805:')
-    call assert_fails("call or(1, 1.0)", 'E805:')
-    call assert_fails("call or(1, [])", 'E745:')
-    call assert_fails("call or(1, {})", 'E728:')
-    " xor
-    call assert_equal(0, xor(127, 127))
-    call assert_equal(111, xor(127, 16))
-    eval 127->xor(16)->assert_equal(111)
-    call assert_equal(255, xor(127, 128))
-    call assert_fails("call xor(1.0, 1)", 'E805:')
-    call assert_fails("call xor(1, 1.0)", 'E805:')
-    call assert_fails("call xor([], 1)", 'E745:')
-    call assert_fails("call xor({}, 1)", 'E728:')
-    call assert_fails("call xor(1, [])", 'E745:')
-    call assert_fails("call xor(1, {})", 'E728:')
-    " invert
-    call assert_equal(65408, and(invert(127), 65535))
-    eval 127->invert()->and(65535)->assert_equal(65408)
-    call assert_equal(65519, and(invert(16), 65535))
-    call assert_equal(65407, and(invert(128), 65535))
-    call assert_fails("call invert(1.0)", 'E805:')
-    call assert_fails("call invert([])", 'E745:')
-    call assert_fails("call invert({})", 'E728:')
-endfunc
-
-" Test using bang after user command				    {{{1
-func Test_user_command_with_bang()
-    command -bang Nieuw let nieuw = 1
-    Ni!
-    call assert_equal(1, nieuw)
-    unlet nieuw
-    delcommand Nieuw
-endfunc
-
-func Test_script_expand_sfile()
-  let lines =<< trim END
-    func s:snr()
-      return expand('<sfile>')
-    endfunc
-    let g:result = s:snr()
-  END
-  call writefile(lines, 'Xexpand', 'D')
-  source Xexpand
-  call assert_match('<SNR>\d\+_snr', g:result)
-  source Xexpand
-  call assert_match('<SNR>\d\+_snr', g:result)
-
-  unlet g:result
-endfunc
-
-func Test_compound_assignment_operators()
-    " Test for number
-    let x = 1
-    let x += 10
-    call assert_equal(11, x)
-    let x -= 5
-    call assert_equal(6, x)
-    let x *= 4
-    call assert_equal(24, x)
-    let x /= 3
-    call assert_equal(8, x)
-    let x %= 3
-    call assert_equal(2, x)
-    let x .= 'n'
-    call assert_equal('2n', x)
-
-    " Test special cases: division or modulus with 0.
-    let x = 1
-    let x /= 0
-    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
-
-    let x = -1
-    let x /= 0
-    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
-
-    let x = 0
-    let x /= 0
-    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
-
-    let x = 1
-    let x %= 0
-    call assert_equal(0, x)
-
-    let x = -1
-    let x %= 0
-    call assert_equal(0, x)
-
-    let x = 0
-    let x %= 0
-    call assert_equal(0, x)
-
-    " Test for string
-    let x = 'str'
-    let x .= 'ing'
-    call assert_equal('string', x)
-    let x += 1
-    call assert_equal(1, x)
-
-    " Test for float
-    let x -= 1.5
-    call assert_equal(-0.5, x)
-    let x = 0.5
-    let x += 4.5
-    call assert_equal(5.0, x)
-    let x -= 1.5
-    call assert_equal(3.5, x)
-    let x *= 3.0
-    call assert_equal(10.5, x)
-    let x /= 2.5
-    call assert_equal(4.2, x)
-    call assert_fails('let x %= 0.5', 'E734:')
-    call assert_fails('let x .= "f"', 'E734:')
-    let x = !3.14
-    call assert_equal(0.0, x)
-
-    " integer and float operations
-    let x = 1
-    let x *= 2.1
-    call assert_equal(2.1, x)
-    let x = 1
-    let x /= 0.25
-    call assert_equal(4.0, x)
-    let x = 1
-    call assert_fails('let x %= 0.25', 'E734:')
-    let x = 1
-    call assert_fails('let x .= 0.25', 'E734:')
-    let x = 1.0
-    call assert_fails('let x += [1.1]', 'E734:')
-
-    " Test for environment variable
-    let $FOO = 1
-    call assert_fails('let $FOO += 1', 'E734:')
-    call assert_fails('let $FOO -= 1', 'E734:')
-    call assert_fails('let $FOO *= 1', 'E734:')
-    call assert_fails('let $FOO /= 1', 'E734:')
-    call assert_fails('let $FOO %= 1', 'E734:')
-    let $FOO .= 's'
-    call assert_equal('1s', $FOO)
-    unlet $FOO
-
-    " Test for option variable (type: number)
-    let &scrolljump = 1
-    let &scrolljump += 5
-    call assert_equal(6, &scrolljump)
-    let &scrolljump -= 2
-    call assert_equal(4, &scrolljump)
-    let &scrolljump *= 3
-    call assert_equal(12, &scrolljump)
-    let &scrolljump /= 2
-    call assert_equal(6, &scrolljump)
-    let &scrolljump %= 5
-    call assert_equal(1, &scrolljump)
-    call assert_fails('let &scrolljump .= "j"', ['E734:', 'E734:'])
-    set scrolljump&vim
-
-    let &foldlevelstart = 2
-    let &foldlevelstart -= 1
-    call assert_equal(1, &foldlevelstart)
-    let &foldlevelstart -= 1
-    call assert_equal(0, &foldlevelstart)
-    let &foldlevelstart = 2
-    let &foldlevelstart -= 2
-    call assert_equal(0, &foldlevelstart)
-
-    " Test for register
-    let @/ = 1
-    call assert_fails('let @/ += 1', 'E734:')
-    call assert_fails('let @/ -= 1', 'E734:')
-    call assert_fails('let @/ *= 1', 'E734:')
-    call assert_fails('let @/ /= 1', 'E734:')
-    call assert_fails('let @/ %= 1', 'E734:')
-    let @/ .= 's'
-    call assert_equal('1s', @/)
-    let @/ = ''
-endfunc
-
-func Test_unlet_env()
-  let $TESTVAR = 'yes'
-  call assert_equal('yes', $TESTVAR)
-  call assert_fails('lockvar $TESTVAR', 'E940:')
-  call assert_fails('unlockvar $TESTVAR', 'E940:')
-  call assert_equal('yes', $TESTVAR)
-  if 0
-    unlet $TESTVAR
-  endif
-  call assert_equal('yes', $TESTVAR)
-  unlet $TESTVAR
-  call assert_equal('', $TESTVAR)
-endfunc
-
-func Test_refcount()
-    " Immediate values
-    call assert_equal(-1, test_refcount(1))
-    call assert_equal(-1, test_refcount('s'))
-    call assert_equal(-1, test_refcount(v:true))
-    call assert_equal(0, test_refcount([]))
-    call assert_equal(0, test_refcount({}))
-    call assert_equal(0, test_refcount(0zff))
-    call assert_equal(0, test_refcount({-> line('.')}))
-    call assert_equal(-1, test_refcount(0.1))
-    if has('job')
-        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
-    endif
-
-    " No refcount types
-    let x = 1
-    call assert_equal(-1, test_refcount(x))
-    let x = 's'
-    call assert_equal(-1, test_refcount(x))
-    let x = v:true
-    call assert_equal(-1, test_refcount(x))
-    let x = 0.1
-    call assert_equal(-1, test_refcount(x))
-
-    " Check refcount
-    let x = []
-    call assert_equal(1, test_refcount(x))
-
-    let x = {}
-    call assert_equal(1, x->test_refcount())
-
-    let x = 0zff
-    call assert_equal(1, test_refcount(x))
-
-    let X = {-> line('.')}
-    call assert_equal(1, test_refcount(X))
-    let Y = X
-    call assert_equal(2, test_refcount(X))
-
-    if has('job')
-        let job = job_start([&shell, &shellcmdflag, 'echo .'])
-        call assert_equal(1, test_refcount(job))
-        call assert_equal(1, test_refcount(job_getchannel(job)))
-        call assert_equal(1, test_refcount(job))
-    endif
-
-    " Function arguments, copying and unassigning
-    func ExprCheck(x, i)
-        let i = a:i + 1
-        call assert_equal(i, test_refcount(a:x))
-        let Y = a:x
-        call assert_equal(i + 1, test_refcount(a:x))
-        call assert_equal(test_refcount(a:x), test_refcount(Y))
-        let Y = 0
-        call assert_equal(i, test_refcount(a:x))
-    endfunc
-    call ExprCheck([], 0)
-    call ExprCheck({}, 0)
-    call ExprCheck(0zff, 0)
-    call ExprCheck({-> line('.')}, 0)
-    if has('job')
-	call ExprCheck(job, 1)
-	call ExprCheck(job_getchannel(job), 1)
-	call job_stop(job)
-    endif
-    delfunc ExprCheck
-
-    " Regarding function
-    func Func(x) abort
-        call assert_equal(2, test_refcount(function('Func')))
-        call assert_equal(0, test_refcount(funcref('Func')))
-    endfunc
-    call assert_equal(1, test_refcount(function('Func')))
-    call assert_equal(0, test_refcount(function('Func', [1])))
-    call assert_equal(0, test_refcount(funcref('Func')))
-    call assert_equal(0, test_refcount(funcref('Func', [1])))
-    let X = function('Func')
-    let Y = X
-    call assert_equal(1, test_refcount(X))
-    let X = function('Func', [1])
-    let Y = X
-    call assert_equal(2, test_refcount(X))
-    let X = funcref('Func')
-    let Y = X
-    call assert_equal(2, test_refcount(X))
-    let X = funcref('Func', [1])
-    let Y = X
-    call assert_equal(2, test_refcount(X))
-    unlet X
-    unlet Y
-    call Func(1)
-    delfunc Func
-
-    " Function with dict
-    func DictFunc() dict
-        call assert_equal(3, test_refcount(self))
-    endfunc
-    let d = {'Func': function('DictFunc')}
-    call assert_equal(1, test_refcount(d))
-    call assert_equal(0, test_refcount(d.Func))
-    call d.Func()
-    unlet d
-    delfunc DictFunc
-
-    if has('channel')
-      call assert_equal(-1, test_refcount(test_null_job()))
-      call assert_equal(-1, test_refcount(test_null_channel()))
-    endif
-    call assert_equal(-1, test_refcount(test_null_function()))
-    call assert_equal(-1, test_refcount(test_null_partial()))
-    call assert_equal(-1, test_refcount(test_null_blob()))
-    call assert_equal(-1, test_refcount(test_null_list()))
-    call assert_equal(-1, test_refcount(test_null_dict()))
-endfunc
-
-" Test for missing :endif, :endfor, :endwhile and :endtry           {{{1
-func Test_missing_end()
-  call writefile(['if 2 > 1', 'echo ">"'], 'Xscript', 'D')
-  call assert_fails('source Xscript', 'E171:')
-  call writefile(['for i in range(5)', 'echo i'], 'Xscript')
-  call assert_fails('source Xscript', 'E170:')
-  call writefile(['while v:true', 'echo "."'], 'Xscript')
-  call assert_fails('source Xscript', 'E170:')
-  call writefile(['try', 'echo "."'], 'Xscript')
-  call assert_fails('source Xscript', 'E600:')
-
-  " Using endfor with :while
-  let caught_e732 = 0
-  try
-    while v:true
-    endfor
-  catch /E732:/
-    let caught_e732 = 1
-  endtry
-  call assert_equal(1, caught_e732)
-
-  " Using endwhile with :for
-  let caught_e733 = 0
-  try
-    for i in range(1)
-    endwhile
-  catch /E733:/
-    let caught_e733 = 1
-  endtry
-  call assert_equal(1, caught_e733)
-
-  " Using endfunc with :if
-  call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
-
-  " Missing 'in' in a :for statement
-  call assert_fails('for i range(1) | endfor', 'E690:')
-
-  " Incorrect number of variables in for
-  call assert_fails('for [i,] in range(3) | endfor', 'E475:')
-endfunc
-
-" Test for deep nesting of if/for/while/try statements              {{{1
-func Test_deep_nest()
-  CheckRunVimInTerminal
-
-  let lines =<< trim [SCRIPT]
-    " Deep nesting of if ... endif
-    func Test1()
-      let @a = join(repeat(['if v:true'], 51), "\n")
-      let @a ..= "\n"
-      let @a ..= join(repeat(['endif'], 51), "\n")
-      @a
-      let @a = ''
-    endfunc
-
-    " Deep nesting of for ... endfor
-    func Test2()
-      let @a = join(repeat(['for i in [1]'], 51), "\n")
-      let @a ..= "\n"
-      let @a ..= join(repeat(['endfor'], 51), "\n")
-      @a
-      let @a = ''
-    endfunc
-
-    " Deep nesting of while ... endwhile
-    func Test3()
-      let @a = join(repeat(['while v:true'], 51), "\n")
-      let @a ..= "\n"
-      let @a ..= join(repeat(['endwhile'], 51), "\n")
-      @a
-      let @a = ''
-    endfunc
-
-    " Deep nesting of try ... endtry
-    func Test4()
-      let @a = join(repeat(['try'], 51), "\n")
-      let @a ..= "\necho v:true\n"
-      let @a ..= join(repeat(['endtry'], 51), "\n")
-      @a
-      let @a = ''
-    endfunc
-
-    " Deep nesting of function ... endfunction
-    func Test5()
-      let @a = join(repeat(['function X()'], 51), "\n")
-      let @a ..= "\necho v:true\n"
-      let @a ..= join(repeat(['endfunction'], 51), "\n")
-      @a
-      let @a = ''
-    endfunc
-  [SCRIPT]
-  call writefile(lines, 'Xscript', 'D')
-
-  let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
-
-  " Deep nesting of if ... endif
-  call term_sendkeys(buf, ":call Test1()\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
-
-  " Deep nesting of for ... endfor
-  call term_sendkeys(buf, ":call Test2()\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
-
-  " Deep nesting of while ... endwhile
-  call term_sendkeys(buf, ":call Test3()\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
-
-  " Deep nesting of try ... endtry
-  call term_sendkeys(buf, ":call Test4()\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
-
-  " Deep nesting of function ... endfunction
-  call term_sendkeys(buf, ":call Test5()\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
-  call term_sendkeys(buf, "\<C-C>\n")
-  call TermWait(buf)
-
-  "let l = ''
-  "for i in range(1, 6)
-  "  let l ..= term_getline(buf, i) . "\n"
-  "endfor
-  "call assert_report(l)
-
-  call StopVimInTerminal(buf)
-endfunc
-
-" Test for errors in converting to float from various types         {{{1
-func Test_float_conversion_errors()
-  call assert_fails('let x = 4.0 % 2.0', 'E804:')
-  call assert_fails('echo 1.1[0]', 'E806:')
-  call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
-  call assert_fails('echo 3.2 == "vim"', 'E892:')
-  call assert_fails('echo sort([[], 1], "f")', 'E893:')
-  call assert_fails('echo sort([{}, 1], "f")', 'E894:')
-  call assert_fails('echo 3.2 == v:true', 'E362:')
-  call assert_fails('echo 3.2 == v:none', 'E907:')
-endfunc
-
-" invalid function names               {{{1
-func Test_invalid_function_names()
-  " function name not starting with capital
-  let caught_e128 = 0
-  try
-    func! g:test()
-      echo "test"
-    endfunc
-  catch /E128:/
-    let caught_e128 = 1
-  endtry
-  call assert_equal(1, caught_e128)
-
-  " function name includes a colon
-  let caught_e884 = 0
-  try
-    func! b:test()
-      echo "test"
-    endfunc
-  catch /E884:/
-    let caught_e884 = 1
-  endtry
-  call assert_equal(1, caught_e884)
-
-  " function name followed by #
-  let caught_e128 = 0
-  try
-    func! test2() "#
-      echo "test2"
-    endfunc
-  catch /E128:/
-    let caught_e128 = 1
-  endtry
-  call assert_equal(1, caught_e128)
-
-  " function name starting with/without "g:", buffer-local funcref.
-  function! g:Foo(n)
-    return 'called Foo(' . a:n . ')'
-  endfunction
-  let b:my_func = function('Foo')
-  call assert_equal('called Foo(1)', b:my_func(1))
-  call assert_equal('called Foo(2)', g:Foo(2))
-  call assert_equal('called Foo(3)', Foo(3))
-  delfunc g:Foo
-
-  " script-local function used in Funcref must exist.
-  let lines =<< trim END
-    func s:Testje()
-      return "foo"
-    endfunc
-    let Bar = function('s:Testje')
-    call assert_equal(0, exists('s:Testje'))
-    call assert_equal(1, exists('*s:Testje'))
-    call assert_equal(1, exists('Bar'))
-    call assert_equal(1, exists('*Bar'))
-  END
-  call writefile(lines, 'Xscript', 'D')
-  source Xscript
-endfunc
-
-" substring and variable name              {{{1
-func Test_substring_var()
-  let str = 'abcdef'
-  let n = 3
-  call assert_equal('def', str[n:])
-  call assert_equal('abcd', str[:n])
-  call assert_equal('d', str[n:n])
-  unlet n
-  let nn = 3
-  call assert_equal('def', str[nn:])
-  call assert_equal('abcd', str[:nn])
-  call assert_equal('d', str[nn:nn])
-  unlet nn
-  let b:nn = 4
-  call assert_equal('ef', str[b:nn:])
-  call assert_equal('abcde', str[:b:nn])
-  call assert_equal('e', str[b:nn:b:nn])
-  unlet b:nn
-endfunc
-
-" Test using s: with a typed command              {{{1
-func Test_typed_script_var()
-  CheckRunVimInTerminal
-
-  let buf = RunVimInTerminal('', {'rows': 6})
-
-  " Deep nesting of if ... endif
-  call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
-  call TermWait(buf)
-  call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
-
-  call StopVimInTerminal(buf)
-endfunc
-
-" Test for issue6776              {{{1
-func Test_ternary_expression()
-  try
-    call eval('0 ? 0')
-  catch
-  endtry
-  " previous failure should not cause next expression to fail
-  call assert_equal(v:false, eval(string(v:false)))
-
-  try
-    call eval('0 ? "burp')
-  catch
-  endtry
-  " previous failure should not cause next expression to fail
-  call assert_equal(v:false, eval(string(v:false)))
-
-  try
-    call eval('1 ? 0 : "burp')
-  catch
-  endtry
-  " previous failure should not cause next expression to fail
-  call assert_equal(v:false, eval(string(v:false)))
-endfunction
-
-func Test_for_over_string()
-  let res = ''
-  for c in 'aéc̀d'
-    let res ..= c .. '-'
-  endfor
-  call assert_equal('a-é-c̀-d-', res)
-
-  let res = ''
-  for c in ''
-    let res ..= c .. '-'
-  endfor
-  call assert_equal('', res)
-
-  let res = ''
-  for c in test_null_string()
-    let res ..= c .. '-'
-  endfor
-  call assert_equal('', res)
-endfunc
-
-" Test for deeply nested :source command  {{{1
-func Test_deeply_nested_source()
-  let lines =<< trim END
-
-      so
-      sil 0scr
-      delete
-      so
-      0
-  END
-  call writefile(["vim9 silent! @0 \n/"] + lines, 'Xnested.vim', 'D')
-
-  " this must not crash
-  let cmd = GetVimCommand() .. " -e -s -S Xnested.vim -c qa!"
-  call system(cmd)
-endfunc
-
-"-------------------------------------------------------------------------------
-" Modelines								    {{{1
-" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
-"-------------------------------------------------------------------------------
+" Test various aspects of the Vim script language.
+" Most of this was formerly in test49.vim (developed by Servatius Brandt
+" <Servatius.Brandt@fujitsu-siemens.com>)
+
+source check.vim
+source shared.vim
+source script_util.vim
+
+"-------------------------------------------------------------------------------
+" Test environment							    {{{1
+"-------------------------------------------------------------------------------
+
+" Append a message to the "messages" file
+func Xout(text)
+    split messages
+    $put =a:text
+    wq
+endfunc
+
+com! -nargs=1	     Xout     call Xout(<args>)
+
+" Create a new instance of Vim and run the commands in 'test' and then 'verify'
+" The commands in 'test' are expected to store the test results in the Xtest.out
+" file. If the test passes successfully, then Xtest.out should be empty.
+func RunInNewVim(test, verify)
+  let init =<< trim END
+    set cpo-=C            " support line-continuation in sourced script
+    source script_util.vim
+    XpathINIT
+    XloopINIT
+  END
+  let cleanup =<< trim END
+    call writefile(v:errors, 'Xtest.out')
+    qall
+  END
+  call writefile(init, 'Xtest.vim', 'D')
+  call writefile(a:test, 'Xtest.vim', 'a')
+  call writefile(a:verify, 'Xverify.vim', 'D')
+  call writefile(cleanup, 'Xverify.vim', 'a')
+  call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
+  call assert_equal([], readfile('Xtest.out'))
+  call delete('Xtest.out')
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func T1_F()
+    Xpath 'a'
+    let first = 1
+    while 1
+	Xpath 'b'
+	if first
+	    Xpath 'c'
+	    let first = 0
+	    break
+	else
+	    Xpath 'd'
+	    return
+	endif
+    endwhile
+endfunc
+
+func T1_G()
+    Xpath 'h'
+    let first = 1
+    while 1
+	Xpath 'i'
+	if first
+	    Xpath 'j'
+	    let first = 0
+	    break
+	else
+	    Xpath 'k'
+	    return
+	endif
+	if 1	" unmatched :if
+    endwhile
+endfunc
+
+func Test_endwhile_function()
+  XpathINIT
+  call T1_F()
+  Xpath 'F'
+
+  try
+    call T1_G()
+  catch
+    " Catch missing :endif
+    call assert_true(v:exception =~ 'E171:')
+    Xpath 'x'
+  endtry
+  Xpath 'G'
+
+  call assert_equal('abcFhijxG', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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 T1_F and T1_G from
+"	    the previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+func Test_endwhile_script()
+  XpathINIT
+  ExecAsScript T1_F
+  Xpath 'F'
+  call DeleteTheScript()
+
+  try
+    ExecAsScript T1_G
+  catch
+    " Catch missing :endif
+    call assert_true(v:exception =~ 'E171:')
+    Xpath 'x'
+  endtry
+  Xpath 'G'
+  call DeleteTheScript()
+
+  call assert_equal('abcFhijxG', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_if_while()
+    XpathINIT
+    if 1
+	Xpath 'a'
+	let loops = 3
+	while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
+	    if loops <= 0
+		let break_err = 1
+		let loops = -1
+	    else
+		Xpath 'b' . loops
+	    endif
+	    if (loops == 2)
+		while loops == 2 " dummy loop
+		    Xpath 'c' . loops
+		    let loops = loops - 1
+		    continue    " stop dummy loop
+		    Xpath 'd' . loops
+		endwhile
+		continue	    " continue main loop
+		Xpath 'e' . loops
+	    elseif (loops == 1)
+		let p = 1
+		while p	    " dummy loop
+		    Xpath 'f' . loops
+		    let p = 0
+		    break	    " break dummy loop
+		    Xpath 'g' . loops
+		endwhile
+		Xpath 'h' . loops
+		unlet p
+		break	    " break main loop
+		Xpath 'i' . loops
+	    endif
+	    if (loops > 0)
+		Xpath 'j' . loops
+	    endif
+	    while loops == 3    " dummy loop
+		let loops = loops - 1
+	    endwhile	    " end dummy loop
+	endwhile		    " end main loop
+	Xpath 'k'
+    else
+	Xpath 'l'
+    endif
+    Xpath 'm'
+    if exists("break_err")
+	Xpath 'm'
+	unlet break_err
+    endif
+
+    unlet loops
+
+    call assert_equal('ab3j3b2c2b1f1h1km', g:Xpath)
+endfunc
+
+" Check double quote after skipped "elseif" does not give error E15
+func Test_skipped_elseif()
+  if "foo" ==? "foo"
+      let result = "first"
+  elseif "foo" ==? "foo"
+      let result = "second"
+  endif
+  call assert_equal('first', result)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 4:   :return							    {{{1
+"-------------------------------------------------------------------------------
+
+func T4_F()
+    if 1
+	Xpath 'a'
+	let loops = 3
+	while loops > 0				"    3:  2:     1:
+	    Xpath 'b' . loops
+	    if (loops == 2)
+		Xpath 'c' . loops
+		return
+		Xpath 'd' . loops
+	    endif
+	    Xpath 'e' . loops
+	    let loops = loops - 1
+	endwhile
+	Xpath 'f'
+    else
+	Xpath 'g'
+    endif
+endfunc
+
+func Test_return()
+    XpathINIT
+    call T4_F()
+    Xpath '4'
+
+    call assert_equal('ab3e3b2c24', g:Xpath)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" Test 5:   :finish							    {{{1
+"
+"	    This test executes the body of the function T4_F from the previous
+"	    test as a script file (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+func Test_finish()
+    XpathINIT
+    ExecAsScript T4_F
+    Xpath '5'
+    call DeleteTheScript()
+
+    call assert_equal('ab3e3b2c25', g:Xpath)
+endfunc
+
+
+
+"-------------------------------------------------------------------------------
+" 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.
+"
+"	     The functions are defined when sourcing the script, only the
+"	     resulting path is checked in the test function.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+" 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 . <args> |
+	    \ endif
+
+let i = 0
+while i < 3
+    let i = i + 1
+    if i == 1
+	Xpath 'a'
+	function! F1(arg)
+	    CALL a:arg
+	    let outer = 1
+
+	    let j = 0
+	    while j < 1
+		Xpath 'b'
+		let j = j + 1
+		function! G1(arg)
+		    CALL a:arg
+		endfunction
+		Xpath 'c'
+	    endwhile
+	endfunction
+	Xpath 'd'
+
+	continue
+    endif
+
+    Xpath 'e' . i
+    function! F{i}(i, arg)
+	CALL a:arg
+	let outer = 1
+
+	if a:i == 3
+	    Xpath 'f'
+	endif
+	let k = 0
+	while k < 3
+	    Xpath 'g' . k
+	    let k = k + 1
+	    function! G{a:i}{k}(arg)
+		CALL a:arg
+	    endfunction
+	    Xpath 'h' . k
+	endwhile
+    endfunction
+    Xpath 'i'
+
+endwhile
+
+if exists("*G1")
+    Xpath 'j'
+endif
+if exists("*F1")
+    call F1("F1")
+    if exists("*G1")
+       call G1("G1")
+    endif
+endif
+
+if exists("G21") || exists("G22") || exists("G23")
+    Xpath 'k'
+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("G32") || exists("G33")
+    Xpath 'l'
+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 'm'
+
+let g:test6_result = g:Xpath
+let g:test6_calls = calls
+
+unlet calls
+delfunction F1
+delfunction G1
+delfunction F2
+delfunction G21
+delfunction G22
+delfunction G23
+delfunction G31
+delfunction G32
+delfunction G33
+
+func Test_defining_functions()
+    call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
+    call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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 'a'
+    while 1
+	Xpath 'b'
+	asdf
+	Xpath 'c'
+	break
+    endwhile | Xpath 'd'
+    Xpath 'e'
+endif | Xpath 'f'
+Xpath 'g'
+
+while 1
+    Xpath 'h'
+    if 1
+	Xpath 'i'
+	asdf
+	Xpath 'j'
+    endif | Xpath 'k'
+    Xpath 'l'
+    break
+endwhile | Xpath 'm'
+Xpath 'n'
+
+asdf
+Xpath 'o'
+
+asdf | Xpath 'p'
+Xpath 'q'
+
+let g:test7_result = g:Xpath
+
+func Test_error_in_script()
+    call assert_equal('abghinoq', g:test7_result)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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
+
+func T8_F()
+    if 1
+	Xpath 'a'
+	while 1
+	    Xpath 'b'
+	    asdf
+	    Xpath 'c'
+	    asdf | Xpath 'd'
+	    Xpath 'e'
+	    break
+	endwhile
+	Xpath 'f'
+    endif | Xpath 'g'
+    Xpath 'h'
+
+    while 1
+	Xpath 'i'
+	if 1
+	    Xpath 'j'
+	    asdf
+	    Xpath 'k'
+	    asdf | Xpath 'l'
+	    Xpath 'm'
+	endif
+	Xpath 'n'
+	break
+    endwhile | Xpath 'o'
+    Xpath 'p'
+
+    return novar		" returns (default return value 0)
+    Xpath 'q'
+    return 1			" not reached
+endfunc
+
+func T8_G() abort
+    if 1
+	Xpath 'r'
+	while 1
+	    Xpath 's'
+	    asdf		" returns -1
+	    Xpath 't'
+	    break
+	endwhile
+	Xpath 'v'
+    endif | Xpath 'w'
+    Xpath 'x'
+
+    return -4			" not reached
+endfunc
+
+func T8_H() abort
+    while 1
+	Xpath 'A'
+	if 1
+	    Xpath 'B'
+	    asdf		" returns -1
+	    Xpath 'C'
+	endif
+	Xpath 'D'
+	break
+    endwhile | Xpath 'E'
+    Xpath 'F'
+
+    return -4			" not reached
+endfunc
+
+" Aborted functions (T8_G and T8_H) return -1.
+let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
+Xpath 'X'
+let g:test8_result = g:Xpath
+
+func Test_error_in_function()
+    call assert_equal(13, g:test8_sum)
+    call assert_equal('abcefghijkmnoprsABX', g:test8_result)
+
+    delfunction T8_F
+    delfunction T8_G
+    delfunction T8_H
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+func F() abort
+    Xpath 'a'
+    let result = G()	" not aborted
+    Xpath 'b'
+    if result != 2
+	Xpath 'c'
+    endif
+    return 1
+endfunc
+
+func G()		" no abort attribute
+    Xpath 'd'
+    if H() != -1	" aborted
+	Xpath 'e'
+    endif
+    Xpath 'f'
+    return 2
+endfunc
+
+func H() abort
+    Xpath 'g'
+    call I()		" aborted
+    Xpath 'h'
+    return 4
+endfunc
+
+func I() abort
+    Xpath 'i'
+    asdf		" error
+    Xpath 'j'
+    return 8
+endfunc
+
+if F() != 1
+    Xpath 'k'
+endif
+
+let g:test9_result = g:Xpath
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+func Test_func_abort()
+    call assert_equal('adgifb', g:test9_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+func 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 = v:errmsg->escape('"')
+	    Xout "Unexpected message:" v:errmsg
+	endif
+    endif
+    return match
+endfunc
+
+if 1 || strlen("\"") | Xpath 'a'
+    Xpath 'b'
+endif
+Xpath 'c'
+
+if 0
+elseif 1 || strlen("\"") | Xpath 'd'
+    Xpath 'e'
+endif
+Xpath 'f'
+
+while 1 || strlen("\"") | Xpath 'g'
+    Xpath 'h'
+    break
+endwhile
+Xpath 'i'
+
+let v:errmsg = ""
+if 1 ||| strlen("\"") | Xpath 'j'
+    Xpath 'k'
+endif
+Xpath 'l'
+if !MSG('E15', "Invalid expression")
+    Xpath 'm'
+endif
+
+let v:errmsg = ""
+if 0
+elseif 1 ||| strlen("\"") | Xpath 'n'
+    Xpath 'o'
+endif
+Xpath 'p'
+if !MSG('E15', "Invalid expression")
+    Xpath 'q'
+endif
+
+let v:errmsg = ""
+while 1 ||| strlen("\"") | Xpath 'r'
+    Xpath 's'
+    break
+endwhile
+Xpath 't'
+if !MSG('E15', "Invalid expression")
+    Xpath 'u'
+endif
+
+let g:test10_result = g:Xpath
+delfunction MSG
+
+func Test_expr_parsing()
+    call assert_equal('abcdefghilpt', g:test10_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+func P(num)
+    let g:calls = g:calls + a:num   " side effect on call
+    return 0
+endfunc
+
+if 1
+    Xpath 'a'
+    asdf		" error
+    Xpath 'b'
+    if P(1)		" should not be called
+	Xpath 'c'
+    elseif !P(2)	" should not be called
+	Xpath 'd'
+    else
+	Xpath 'e'
+    endif
+    Xpath 'f'
+    while P(4)		" should not be called
+	Xpath 'g'
+    endwhile
+    Xpath 'h'
+endif
+Xpath 'x'
+
+let g:test11_calls = calls
+let g:test11_result = g:Xpath
+
+unlet calls
+delfunction P
+
+func Test_arg_abort()
+    call assert_equal(0, g:test11_calls)
+    call assert_equal('ax', g:test11_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+func NULL()
+    Xpath 'a'
+    return 0
+endfunc
+
+func ZERO()
+    Xpath 'b'
+    return 0
+endfunc
+
+func! F0()
+    Xpath 'c'
+endfunc
+
+func! F1(arg)
+    Xpath 'e'
+endfunc
+
+let V0 = 1
+
+Xpath 'f'
+echo 0 ? F{NULL() + V{ZERO()}}() : 1
+
+Xpath 'g'
+if 0
+    Xpath 'h'
+    call F{NULL() + V{ZERO()}}()
+endif
+
+Xpath 'i'
+if 1
+    asdf		" error
+    Xpath 'j'
+    call F1(F{NULL() + V{ZERO()}}())
+endif
+
+Xpath 'k'
+if 1
+    asdf		" error
+    Xpath 'l'
+    call F{NULL() + V{ZERO()}}()
+endif
+
+let g:test12_result = g:Xpath
+
+func Test_braces_skipped()
+    call assert_equal('fgik', g:test12_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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 'a'
+while asdf
+    Xpath 'b'
+    while 1
+	Xpath 'c'
+	break
+    endwhile
+    Xpath 'd'
+    break
+endwhile
+Xpath 'e'
+
+while asdf | Xpath 'f' | endwhile | Xpath 'g'
+Xpath 'h'
+let g:test13_result = g:Xpath
+
+func Test_while_fail()
+    call assert_equal('aeh', g:test13_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+function! F()
+    Xpath 'a'
+    let x = 0
+    if x		" false
+	Xpath 'b'
+    elseif !x		" always true
+	Xpath 'c'
+	let x = 1
+	if g:boolvar	" possibly undefined
+	    Xpath 'd'
+	else
+	    Xpath 'e'
+	endif
+	Xpath 'f'
+    elseif x		" never executed
+	Xpath 'g'
+    endif
+    Xpath 'h'
+endfunction
+
+let boolvar = 1
+call F()
+Xpath '-'
+
+unlet boolvar
+call F()
+let g:test14_result = g:Xpath
+
+delfunction F
+
+func Test_if_fail()
+    call assert_equal('acdfh-acfh', g:test14_result)
+endfunc
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+function! F()
+    Xpath 'a'
+    let x = 0
+    if x		" false
+	Xpath 'b'
+    elseif !x		" always true
+	Xpath 'c'
+	let x = 1
+	if g:boolvar | Xpath 'd' | else | Xpath 'e' | endif
+	Xpath 'f'
+    elseif x		" never executed
+	Xpath 'g'
+    endif
+    Xpath 'h'
+endfunction
+
+let boolvar = 1
+call F()
+Xpath '-'
+
+unlet boolvar
+call F()
+let g:test15_result = g:Xpath
+
+delfunction F
+
+func Test_if_bar_fail()
+    call assert_equal('acdfh-acfh', g:test15_result)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 16:  Double :else or :elseif after :else				    {{{1
+"
+"	    Multiple :elses or an :elseif after an :else are forbidden.
+"-------------------------------------------------------------------------------
+
+func T16_F() abort
+  if 0
+    Xpath 'a'
+  else
+    Xpath 'b'
+  else		" aborts function
+    Xpath 'c'
+  endif
+  Xpath 'd'
+endfunc
+
+func T16_G() abort
+  if 0
+    Xpath 'a'
+  else
+    Xpath 'b'
+  elseif 1		" aborts function
+    Xpath 'c'
+  else
+    Xpath 'd'
+  endif
+  Xpath 'e'
+endfunc
+
+func T16_H() abort
+  if 0
+    Xpath 'a'
+  elseif 0
+    Xpath 'b'
+  else
+    Xpath 'c'
+  else		" aborts function
+    Xpath 'd'
+  endif
+  Xpath 'e'
+endfunc
+
+func T16_I() abort
+  if 0
+    Xpath 'a'
+  elseif 0
+    Xpath 'b'
+  else
+    Xpath 'c'
+  elseif 1		" aborts function
+    Xpath 'd'
+  else
+    Xpath 'e'
+  endif
+  Xpath 'f'
+endfunc
+
+func Test_Multi_Else()
+  XpathINIT
+  try
+    call T16_F()
+  catch /E583:/
+    Xpath 'e'
+  endtry
+  call assert_equal('be', g:Xpath)
+
+  XpathINIT
+  try
+    call T16_G()
+  catch /E584:/
+    Xpath 'f'
+  endtry
+  call assert_equal('bf', g:Xpath)
+
+  XpathINIT
+  try
+    call T16_H()
+  catch /E583:/
+    Xpath 'f'
+  endtry
+  call assert_equal('cf', g:Xpath)
+
+  XpathINIT
+  try
+    call T16_I()
+  catch /E584:/
+    Xpath 'g'
+  endtry
+  call assert_equal('cg', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+" While loops inside a function are continued on error.
+func T17_F()
+  let loops = 3
+  while loops > 0
+    let loops -= 1
+    Xpath 'a' . loops
+    if (loops == 1)
+      Xpath 'b' . loops
+      continue
+    elseif (loops == 0)
+      Xpath 'c' . loops
+      break
+    elseif 1
+      Xpath 'd' . loops
+    " endif missing!
+  endwhile	" :endwhile after :if 1
+  Xpath 'e'
+endfunc
+
+func T17_G()
+  let loops = 2
+  while loops > 0
+    let loops -= 1
+    Xpath 'a' . loops
+    if 0
+      Xpath 'b' . loops
+    " endif missing
+  endwhile	" :endwhile after :if 0
+endfunc
+
+func T17_H()
+  let loops = 2
+  while loops > 0
+    let loops -= 1
+    Xpath 'a' . loops
+    " if missing!
+    endif	" :endif without :if in while
+    Xpath 'b' . loops
+  endwhile
+endfunc
+
+" Error continuation outside a function is at the outermost :endwhile or :endif.
+XpathINIT
+let v:errmsg = ''
+let loops = 2
+while loops > 0
+    let loops -= 1
+    Xpath 'a' . loops
+    if 0
+	Xpath 'b' . loops
+    " endif missing! Following :endwhile fails.
+endwhile | Xpath 'c'
+Xpath 'd'
+call assert_match('E171:', v:errmsg)
+call assert_equal('a1d', g:Xpath)
+
+func Test_unmatched_if_in_while()
+  XpathINIT
+  call assert_fails('call T17_F()', 'E171:')
+  call assert_equal('a2d2a1b1a0c0e', g:Xpath)
+
+  XpathINIT
+  call assert_fails('call T17_G()', 'E171:')
+  call assert_equal('a1a0', g:Xpath)
+
+  XpathINIT
+  call assert_fails('call T17_H()', 'E580:')
+  call assert_equal('a1b1a0b0', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
+"
+"	    On an interrupt, the script processing is terminated immediately.
+"-------------------------------------------------------------------------------
+
+func Test_interrupt_while_if()
+  let test =<< trim [CODE]
+    try
+      if 1
+        Xpath 'a'
+        while 1
+          Xpath 'b'
+          if 1
+            Xpath 'c'
+            call interrupt()
+            call assert_report('should not get here')
+            break
+            finish
+          endif | call assert_report('should not get here')
+          call assert_report('should not get here')
+        endwhile | call assert_report('should not get here')
+        call assert_report('should not get here')
+      endif | call assert_report('should not get here')
+      call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'd'
+    endtry | Xpath 'e'
+    Xpath 'f'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdef', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_interrupt_try()
+  let test =<< trim [CODE]
+    try
+      try
+        Xpath 'a'
+        call interrupt()
+        call assert_report('should not get here')
+      endtry | call assert_report('should not get here')
+      call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'b'
+    endtry | Xpath 'c'
+    Xpath 'd'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcd', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_interrupt_func_while_if()
+  let test =<< trim [CODE]
+    func F()
+      if 1
+        Xpath 'a'
+        while 1
+          Xpath 'b'
+          if 1
+            Xpath 'c'
+            call interrupt()
+            call assert_report('should not get here')
+            break
+            return
+          endif | call assert_report('should not get here')
+          call assert_report('should not get here')
+        endwhile | call assert_report('should not get here')
+        call assert_report('should not get here')
+      endif | call assert_report('should not get here')
+      call assert_report('should not get here')
+    endfunc
+
+    Xpath 'd'
+    try
+      call F() | call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'e'
+    endtry | Xpath 'f'
+    Xpath 'g'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('dabcefg', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_interrupt_func_try()
+  let test =<< trim [CODE]
+    func G()
+      try
+        Xpath 'a'
+        call interrupt()
+        call assert_report('should not get here')
+      endtry | call assert_report('should not get here')
+      call assert_report('should not get here')
+    endfunc
+
+    Xpath 'b'
+    try
+      call G() | call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'c'
+    endtry | Xpath 'd'
+    Xpath 'e'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('bacde', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_try_error_abort_1()
+  let test =<< trim [CODE]
+    func F() abort
+      Xpath 'a'
+      asdf
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'b'
+      call F()
+      call assert_report('should not get here')
+    endtry | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ba', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_try_error_abort_2()
+  let test =<< trim [CODE]
+    func G()
+      Xpath 'a'
+      asdf
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'b'
+      call G()
+      call assert_report('should not get here')
+    endtry | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ba', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_try_error_abort_3()
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      asdf
+      call assert_report('should not get here')
+    endtry | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_try_error_abort_4()
+  let test =<< trim [CODE]
+    if 1
+      try
+        Xpath 'a'
+        asdf
+        call assert_report('should not get here')
+      endtry | call assert_report('should not get here')
+    endif | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_try_error_abort_5()
+  let test =<< trim [CODE]
+    let p = 1
+    while p
+      let p = 0
+      try
+        Xpath 'a'
+        asdf
+        call assert_report('should not get here')
+      endtry | call assert_report('should not get here')
+    endwhile | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_try_error_abort_6()
+  let test =<< trim [CODE]
+    let p = 1
+    Xpath 'a'
+    while p
+      Xpath 'b'
+      let p = 0
+      try
+        Xpath 'c'
+    endwhile | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_error_after_try_1()
+  let test =<< trim [CODE]
+    let p = 1
+    while p
+      let p = 0
+      Xpath 'a'
+      try
+        Xpath 'b'
+      endtry
+      asdf
+      call assert_report('should not get here')
+    endwhile | call assert_report('should not get here')
+    Xpath 'c'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_2()
+  let test =<< trim [CODE]
+    while 1
+      try
+        Xpath 'a'
+        break
+        call assert_report('should not get here')
+      endtry
+    endwhile
+    Xpath 'b'
+    asdf
+    Xpath 'c'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_3()
+  let test =<< trim [CODE]
+    while 1
+      try
+        Xpath 'a'
+        break
+        call assert_report('should not get here')
+      finally
+        Xpath 'b'
+      endtry
+    endwhile
+    Xpath 'c'
+    asdf
+    Xpath 'd'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcd', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_4()
+  let test =<< trim [CODE]
+    while 1
+      try
+        Xpath 'a'
+      finally
+        Xpath 'b'
+        break
+        call assert_report('should not get here')
+      endtry
+    endwhile
+    Xpath 'c'
+    asdf
+    Xpath 'd'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcd', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_5()
+  let test =<< trim [CODE]
+    let p = 1
+    while p
+      let p = 0
+      try
+        Xpath 'a'
+        continue
+        call assert_report('should not get here')
+      endtry
+    endwhile
+    Xpath 'b'
+    asdf
+    Xpath 'c'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_6()
+  let test =<< trim [CODE]
+    let p = 1
+    while p
+      let p = 0
+      try
+        Xpath 'a'
+        continue
+        call assert_report('should not get here')
+      finally
+        Xpath 'b'
+      endtry
+    endwhile
+    Xpath 'c'
+    asdf
+    Xpath 'd'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcd', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_error_after_try_7()
+  let test =<< trim [CODE]
+    let p = 1
+    while p
+      let p = 0
+      try
+        Xpath 'a'
+      finally
+        Xpath 'b'
+        continue
+        call assert_report('should not get here')
+      endtry
+    endwhile
+    Xpath 'c'
+    asdf
+    Xpath 'd'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcd', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_loop_ctrl_statement()
+  let test =<< trim [CODE]
+    func F()
+      let loops = 2
+      while loops > 0
+        XloopNEXT
+        let loops = loops - 1
+        try
+          if loops == 1
+            Xloop 'a'
+            continue
+            call assert_report('should not get here')
+          elseif loops == 0
+            Xloop 'b'
+            break
+            call assert_report('should not get here')
+          endif
+
+          try		" inactive
+            call assert_report('should not get here')
+          finally
+            call assert_report('should not get here')
+          endtry
+        finally
+          Xloop 'c'
+        endtry
+        call assert_report('should not get here')
+      endwhile
+
+      try
+        Xpath 'd'
+        return
+        call assert_report('should not get here')
+        try		    " inactive
+          call assert_report('should not get here')
+        finally
+          call assert_report('should not get here')
+        endtry
+      finally
+        Xpath 'e'
+      endtry
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'f'
+      call F()
+      Xpath 'g'
+      finish
+      call assert_report('should not get here')
+      try		" inactive
+        call assert_report('should not get here')
+      finally
+        call assert_report('should not get here')
+      endtry
+    finally
+      Xpath 'h'
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('fa2c2b3c3degh', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_error_in_func()
+  let test =<< trim [CODE]
+    func Error()
+      try
+        Xpath 'b'
+        asdf    " aborting error, triggering error exception
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    endfunc
+
+    Xpath 'a'
+    call Error()
+    call assert_report('should not get here')
+
+    if 1	" not active due to error
+      try	" not active since :if inactive
+        call assert_report('should not get here')
+      finally
+        call assert_report('should not get here')
+      endtry
+    endif
+
+    try		" not active due to error
+      call assert_report('should not get here')
+    finally
+      call assert_report('should not get here')
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ab', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_finally_after_interrupt()
+  let test =<< trim [CODE]
+    func Interrupt()
+      try
+        Xpath 'a'
+        call interrupt()            " triggering interrupt exception
+        call assert_report('should not get here')
+      endtry
+    endfunc
+
+    Xpath 'b'
+    try
+      call Interrupt()
+    catch /^Vim:Interrupt$/
+      Xpath 'c'
+      finish
+    endtry
+    call assert_report('should not get here')
+
+    if 1	" not active due to interrupt
+      try	" not active since :if inactive
+        call assert_report('should not get here')
+      finally
+        call assert_report('should not get here')
+      endtry
+    endif
+
+    try		" not active due to interrupt
+      call assert_report('should not get here')
+    finally
+      call assert_report('should not get here')
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('bac', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_finally_after_throw()
+  let test =<< trim [CODE]
+    func Throw()
+      Xpath 'a'
+      throw 'xyz'
+    endfunc
+
+    Xpath 'b'
+    call Throw()
+    call assert_report('should not get here')
+
+    if 1	" not active due to :throw
+      try	" not active since :if inactive
+        call assert_report('should not get here')
+      finally
+        call assert_report('should not get here')
+      endtry
+    endif
+
+    try		" not active due to :throw
+      call assert_report('should not get here')
+    finally
+      call assert_report('should not get here')
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ba', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_catch_after_throw()
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      throw "xyz"
+      call assert_report('should not get here')
+
+      if 1	" not active due to :throw
+        try	" not active since :if inactive
+          call assert_report('should not get here')
+        catch /xyz/
+          call assert_report('should not get here')
+        endtry
+      endif
+    catch /xyz/
+      Xpath 'b'
+    endtry
+
+    Xpath 'c'
+    throw "abc"
+    call assert_report('should not get here')
+
+    try		" not active due to :throw
+      call assert_report('should not get here')
+    catch /abc/
+      call assert_report('should not get here')
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_endtry_after_throw()
+  let test =<< trim [CODE]
+    try			" try 1
+      try		" try 2
+        Xpath 'a'
+        throw "xyz"	" makes try 2 inactive
+        call assert_report('should not get here')
+
+        try		" try 3
+          call assert_report('should not get here')
+        endtry	" no rethrow to try 1
+      catch /xyz/	" should catch although try 2 inactive
+        Xpath 'b'
+      endtry
+    catch /xyz/		" try 1 active, but exception already caught
+      call assert_report('should not get here')
+    endtry
+    Xpath 'c'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func T27_F()
+  try
+    Xpath 'a'
+    try
+      Xpath 'b'
+      return
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+    endtry
+    Xpath 'd'
+  finally
+    Xpath 'e'
+  endtry
+  call assert_report('should not get here')
+endfunc
+
+func T27_G()
+  try
+    Xpath 'f'
+    return
+    call assert_report('should not get here')
+  finally
+    Xpath 'g'
+    call T27_F()
+    Xpath 'h'
+  endtry
+  call assert_report('should not get here')
+endfunc
+
+func T27_H()
+  try
+    Xpath 'i'
+    call T27_G()
+    Xpath 'j'
+  finally
+    Xpath 'k'
+    return
+    call assert_report('should not get here')
+  endtry
+  call assert_report('should not get here')
+endfunction
+
+func Test_finally_after_return()
+  XpathINIT
+  try
+      Xpath 'l'
+      call T27_H()
+      Xpath 'm'
+  finally
+      Xpath 'n'
+  endtry
+  call assert_equal('lifgabcehjkmn', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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).
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_finish()
+  XpathINIT
+
+  let scriptF = MakeScript("T27_F")
+  let scriptG = MakeScript("T27_G", scriptF)
+  let scriptH = MakeScript("T27_H", scriptG)
+
+  try
+    Xpath 'A'
+    exec "source" scriptH
+    Xpath 'B'
+  finally
+    Xpath 'C'
+  endtry
+  Xpath 'D'
+  call assert_equal('AifgabcehjkBCD', g:Xpath)
+  call delete(scriptF)
+  call delete(scriptG)
+  call delete(scriptH)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_error_1()
+  let test =<< trim [CODE]
+    func F()
+      while 1
+        try
+          Xpath 'a'
+          while 1
+            try
+              Xpath 'b'
+              asdf	    " error
+              call assert_report('should not get here')
+            finally
+              Xpath 'c'
+            endtry | call assert_report('should not get here')
+            call assert_report('should not get here')
+            break
+          endwhile
+          call assert_report('should not get here')
+        finally
+          Xpath 'd'
+        endtry | call assert_report('should not get here')
+        call assert_report('should not get here')
+        break
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    while 1
+      try
+        Xpath 'e'
+        while 1
+          call F()
+          call assert_report('should not get here')
+          break
+        endwhile  | call assert_report('should not get here')
+        call assert_report('should not get here')
+      finally
+        Xpath 'f'
+      endtry | call assert_report('should not get here')
+    endwhile | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('eabcdf', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_finally_after_error_2()
+  let test =<< trim [CODE]
+    func G() abort
+      if 1
+        try
+          Xpath 'a'
+          asdf	    " error
+          call assert_report('should not get here')
+        finally
+          Xpath 'b'
+        endtry | Xpath 'c'
+      endif | Xpath 'd'
+      call assert_report('should not get here')
+    endfunc
+
+    if 1
+      try
+        Xpath 'e'
+        call G()
+        call assert_report('should not get here')
+      finally
+        Xpath 'f'
+      endtry | call assert_report('should not get here')
+    endif | call assert_report('should not get here')
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('eabf', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" 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.
+"-------------------------------------------------------------------------------
+
+func Test_finally_on_interrupt()
+  let test =<< trim [CODE]
+    func F()
+      try
+        Xloop 'a'
+        call interrupt()
+        call assert_report('should not get here')
+      finally
+        Xloop 'b'
+      endtry
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      try
+        Xpath 'c'
+        try
+          Xpath 'd'
+          call interrupt()
+          call assert_report('should not get here')
+        finally
+          Xpath 'e'
+          try
+            Xpath 'f'
+            try
+              Xpath 'g'
+            finally
+              Xpath 'h'
+              try
+                Xpath 'i'
+                call interrupt()
+                call assert_report('should not get here')
+              endtry
+              call assert_report('should not get here')
+            endtry
+            call assert_report('should not get here')
+          endtry
+          call assert_report('should not get here')
+        endtry
+        call assert_report('should not get here')
+      finally
+        Xpath 'j'
+        try
+          Xpath 'k'
+          call F()
+          call assert_report('should not get here')
+        finally
+          Xpath 'l'
+          try
+            Xpath 'm'
+            XloopNEXT
+            ExecAsScript F
+            call assert_report('should not get here')
+          finally
+            Xpath 'n'
+          endtry
+          call assert_report('should not get here')
+        endtry
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'o'
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('cdefghijka1b1lma2b2no', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 31:  Executing :finally clauses after :throw			    {{{1
+"
+"	    After a :throw dynamically enclosed in a :try/:endtry region,
+"	    :finally clauses are executed and the script processing is
+"	    terminated.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_throw_2()
+  let test =<< trim [CODE]
+    func F()
+      try
+        Xloop 'a'
+        throw "exception"
+        call assert_report('should not get here')
+      finally
+        Xloop 'b'
+      endtry
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'c'
+      try
+        Xpath 'd'
+        throw "exception"
+        call assert_report('should not get here')
+      finally
+        Xpath 'e'
+        try
+          Xpath 'f'
+          try
+            Xpath 'g'
+          finally
+            Xpath 'h'
+            try
+              Xpath 'i'
+              throw "exception"
+              call assert_report('should not get here')
+            endtry
+            call assert_report('should not get here')
+          endtry
+          call assert_report('should not get here')
+        endtry
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    finally
+      Xpath 'j'
+      try
+        Xpath 'k'
+        call F()
+        call assert_report('should not get here')
+      finally
+        Xpath 'l'
+        try
+          Xpath 'm'
+          XloopNEXT
+          ExecAsScript F
+          call assert_report('should not get here')
+        finally
+          Xpath 'n'
+        endtry
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('cdefghijka1b1lma2b2n', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 34:  :finally reason discarded by :continue			    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by a :continue in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_continue()
+  let test =<< trim [CODE]
+    func C(jump)
+      XloopNEXT
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return" || a:jump == "finish"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            continue	" discards jump that caused the :finally
+            call assert_report('should not get here')
+          endtry
+          call assert_report('should not get here')
+        elseif loop == 2
+          Xloop 'a'
+        endif
+      endwhile
+    endfunc
+
+    call C("continue")
+    Xpath 'b'
+    call C("break")
+    Xpath 'c'
+    call C("return")
+    Xpath 'd'
+    let g:jump = "finish"
+    ExecAsScript C
+    unlet g:jump
+    Xpath 'e'
+    try
+      call C("error")
+      Xpath 'f'
+    finally
+      Xpath 'g'
+      try
+        call C("interrupt")
+        Xpath 'h'
+      finally
+        Xpath 'i'
+        call C("throw")
+        Xpath 'j'
+      endtry
+    endtry
+    Xpath 'k'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 35:  :finally reason discarded by :break				    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by a :break in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discard_by_break()
+  let test =<< trim [CODE]
+    func B(jump)
+      XloopNEXT
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return" || a:jump == "finish"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            break	" discards jump that caused the :finally
+            call assert_report('should not get here')
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      Xloop 'a'
+    endfunc
+
+    call B("continue")
+    Xpath 'b'
+    call B("break")
+    Xpath 'c'
+    call B("return")
+    Xpath 'd'
+    let g:jump = "finish"
+    ExecAsScript B
+    unlet g:jump
+    Xpath 'e'
+    try
+      call B("error")
+      Xpath 'f'
+    finally
+      Xpath 'g'
+      try
+        call B("interrupt")
+        Xpath 'h'
+      finally
+        Xpath 'i'
+        call B("throw")
+        Xpath 'j'
+      endtry
+    endtry
+    Xpath 'k'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a2ba3ca4da5ea6fga7hia8jk', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 36:  :finally reason discarded by :return			    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by a :return in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discard_by_return()
+  let test =<< trim [CODE]
+    func R(jump, retval) abort
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            return a:retval	" discards jump that caused the :finally
+            call assert_report('should not get here')
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    let sum =  -R("continue", -8)
+    Xpath 'a'
+    let sum = sum - R("break", -16)
+    Xpath 'b'
+    let sum = sum - R("return", -32)
+    Xpath 'c'
+    try
+      let sum = sum - R("error", -64)
+      Xpath 'd'
+    finally
+      Xpath 'e'
+      try
+        let sum = sum - R("interrupt", -128)
+        Xpath 'f'
+      finally
+        Xpath 'g'
+        let sum = sum - R("throw", -256)
+        Xpath 'h'
+      endtry
+    endtry
+    Xpath 'i'
+
+    let expected = 8 + 16 + 32 + 64 + 128 + 256
+    call assert_equal(sum, expected)
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghi', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 37:  :finally reason discarded by :finish			    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by a :finish in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discard_by_finish()
+  let test =<< trim [CODE]
+    func F(jump)	" not executed as function, transformed to a script
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "finish"
+              finish
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            finish	" discards jump that caused the :finally
+            call assert_report('should not get here')
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    let scriptF = MakeScript("F")
+    delfunction F
+
+    let g:jump = "continue"
+    exec "source" scriptF
+    Xpath 'a'
+    let g:jump = "break"
+    exec "source" scriptF
+    Xpath 'b'
+    let g:jump = "finish"
+    exec "source" scriptF
+    Xpath 'c'
+    try
+      let g:jump = "error"
+      exec "source" scriptF
+      Xpath 'd'
+    finally
+      Xpath 'e'
+      try
+        let g:jump = "interrupt"
+        exec "source" scriptF
+        Xpath 'f'
+      finally
+        Xpath 'g'
+        try
+          let g:jump = "throw"
+          exec "source" scriptF
+          Xpath 'h'
+        finally
+          Xpath 'i'
+        endtry
+      endtry
+    endtry
+    unlet g:jump
+    call delete(scriptF)
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghi', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 38:  :finally reason discarded by an error			    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by an error in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discard_by_error()
+  let test =<< trim [CODE]
+    func E(jump)
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return" || a:jump == "finish"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            asdf	" error; discards jump that caused the :finally
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'a'
+      call E("continue")
+      call assert_report('should not get here')
+    finally
+      try
+        Xpath 'b'
+        call E("break")
+        call assert_report('should not get here')
+      finally
+        try
+          Xpath 'c'
+          call E("return")
+          call assert_report('should not get here')
+        finally
+          try
+            Xpath 'd'
+            let g:jump = "finish"
+            ExecAsScript E
+            call assert_report('should not get here')
+          finally
+            unlet g:jump
+            try
+              Xpath 'e'
+              call E("error")
+              call assert_report('should not get here')
+            finally
+              try
+                Xpath 'f'
+                call E("interrupt")
+                call assert_report('should not get here')
+              finally
+                try
+                  Xpath 'g'
+                  call E("throw")
+                  call assert_report('should not get here')
+                finally
+                  Xpath 'h'
+                  delfunction E
+                endtry
+              endtry
+            endtry
+          endtry
+        endtry
+      endtry
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefgh', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 39:  :finally reason discarded by an interrupt			    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by an interrupt in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discarded_by_interrupt()
+  let test =<< trim [CODE]
+    func I(jump)
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return" || a:jump == "finish"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            call interrupt()
+            let dummy = 0
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      try
+        Xpath 'a'
+        call I("continue")
+        call assert_report('should not get here')
+      finally
+        try
+          Xpath 'b'
+          call I("break")
+          call assert_report('should not get here')
+        finally
+          try
+            Xpath 'c'
+            call I("return")
+            call assert_report('should not get here')
+          finally
+            try
+              Xpath 'd'
+              let g:jump = "finish"
+              ExecAsScript I
+              call assert_report('should not get here')
+            finally
+              unlet g:jump
+              try
+                Xpath 'e'
+                call I("error")
+                call assert_report('should not get here')
+              finally
+                try
+                  Xpath 'f'
+                  call I("interrupt")
+                  call assert_report('should not get here')
+                finally
+                  try
+                    Xpath 'g'
+                    call I("throw")
+                    call assert_report('should not get here')
+                  finally
+                    Xpath 'h'
+                    delfunction I
+                  endtry
+                endtry
+              endtry
+            endtry
+          endtry
+        endtry
+      endtry
+      call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'A'
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghA', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 40:  :finally reason discarded by :throw				    {{{1
+"
+"	    When a :finally clause is executed due to a :continue, :break,
+"	    :return, :finish, error, interrupt or :throw, the jump reason is
+"	    discarded by a :throw in the finally clause.
+"-------------------------------------------------------------------------------
+
+func Test_finally_discard_by_throw()
+  let test =<< trim [CODE]
+    func T(jump)
+      let loop = 0
+      while loop < 2
+        let loop = loop + 1
+        if loop == 1
+          try
+            if a:jump == "continue"
+              continue
+            elseif a:jump == "break"
+              break
+            elseif a:jump == "return" || a:jump == "finish"
+              return
+            elseif a:jump == "error"
+              asdf
+            elseif a:jump == "interrupt"
+              call interrupt()
+              let dummy = 0
+            elseif a:jump == "throw"
+              throw "abc"
+            endif
+          finally
+            throw "xyz"	" discards jump that caused the :finally
+          endtry
+        elseif loop == 2
+          call assert_report('should not get here')
+        endif
+      endwhile
+      call assert_report('should not get here')
+    endfunc
+
+    try
+      Xpath 'a'
+      call T("continue")
+      call assert_report('should not get here')
+    finally
+      try
+        Xpath 'b'
+        call T("break")
+        call assert_report('should not get here')
+      finally
+        try
+          Xpath 'c'
+          call T("return")
+          call assert_report('should not get here')
+        finally
+          try
+            Xpath 'd'
+            let g:jump = "finish"
+            ExecAsScript T
+            call assert_report('should not get here')
+          finally
+            unlet g:jump
+            try
+              Xpath 'e'
+              call T("error")
+              call assert_report('should not get here')
+            finally
+              try
+                Xpath 'f'
+                call T("interrupt")
+                call assert_report('should not get here')
+              finally
+                try
+                  Xpath 'g'
+                  call T("throw")
+                  call assert_report('should not get here')
+                finally
+                  Xpath 'h'
+                  delfunction T
+                endtry
+              endtry
+            endtry
+          endtry
+        endtry
+      endtry
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefgh', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 49:  Throwing exceptions across functions			    {{{1
+"
+"	    When an exception is thrown but not caught inside a function, the
+"	    caller is checked for a matching :catch clause.
+"-------------------------------------------------------------------------------
+
+func T49_C()
+  try
+    Xpath 'a'
+    throw "arrgh"
+    call assert_report('should not get here')
+  catch /arrgh/
+    Xpath 'b'
+  endtry
+  Xpath 'c'
+endfunc
+
+func T49_T1()
+  XloopNEXT
+  try
+    Xloop 'd'
+    throw "arrgh"
+    call assert_report('should not get here')
+  finally
+    Xloop 'e'
+  endtry
+  Xloop 'f'
+endfunc
+
+func T49_T2()
+  try
+    Xpath 'g'
+    call T49_T1()
+    call assert_report('should not get here')
+  finally
+    Xpath 'h'
+  endtry
+  call assert_report('should not get here')
+endfunc
+
+func Test_throw_exception_across_funcs()
+  XpathINIT
+  XloopINIT
+  try
+    Xpath 'i'
+    call T49_C()            " throw and catch
+    Xpath 'j'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+
+  try
+    Xpath 'k'
+    call T49_T1()  " throw, one level
+    call assert_report('should not get here')
+  catch /arrgh/
+    Xpath 'l'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+
+  try
+    Xpath 'm'
+    call T49_T2()	" throw, two levels
+    call assert_report('should not get here')
+  catch /arrgh/
+    Xpath 'n'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+  Xpath 'o'
+
+  call assert_equal('iabcjkd2e2lmgd3e3hno', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 50:  Throwing exceptions across script files			    {{{1
+"
+"	    When an exception is thrown but not caught inside a script file,
+"	    the sourcing script or function is checked for a matching :catch
+"	    clause.
+"
+"	    This test executes the bodies of the functions C, T1, and T2 from
+"	    the previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+func T50_F()
+  try
+    Xpath 'A'
+    exec "source" g:scriptC
+    Xpath 'B'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+
+  try
+    Xpath 'C'
+    exec "source" g:scriptT1
+    call assert_report('should not get here')
+  catch /arrgh/
+    Xpath 'D'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+endfunc
+
+func Test_throw_across_script()
+  XpathINIT
+  XloopINIT
+  let g:scriptC = MakeScript("T49_C")
+  let g:scriptT1 = MakeScript("T49_T1")
+  let scriptT2 = MakeScript("T49_T2", g:scriptT1)
+
+  try
+    Xpath 'E'
+    call T50_F()
+    Xpath 'F'
+    exec "source" scriptT2
+    call assert_report('should not get here')
+  catch /arrgh/
+    Xpath 'G'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+  Xpath 'H'
+  call assert_equal('EAabcBCd2e2DFgd3e3hGH', g:Xpath)
+
+  call delete(g:scriptC)
+  call delete(g:scriptT1)
+  call delete(scriptT2)
+  unlet g:scriptC g:scriptT1 scriptT2
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 52:  Uncaught exceptions						    {{{1
+"
+"	    When an exception is thrown but not caught, an error message is
+"	    displayed when the script is terminated.  In case of an interrupt
+"	    or error exception, the normal interrupt or error message(s) are
+"	    displayed.
+"-------------------------------------------------------------------------------
+
+func Test_uncaught_exception_1()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    Xpath 'a'
+    throw "arrgh"
+    call assert_report('should not get here')`
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('E605: Exception not caught: arrgh', v:errmsg)
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_2()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      throw "oops"
+      call assert_report('should not get here')`
+    catch /arrgh/
+      call assert_report('should not get here')`
+    endtry
+    call assert_report('should not get here')`
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('E605: Exception not caught: oops', v:errmsg)
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_3()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    func T()
+      Xpath 'c'
+      throw "brrr"
+      call assert_report('should not get here')`
+    endfunc
+
+    try
+      Xpath 'a'
+      throw "arrgh"
+      call assert_report('should not get here')`
+    catch /.*/
+      Xpath 'b'
+      call T()
+      call assert_report('should not get here')`
+    endtry
+    call assert_report('should not get here')`
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_4()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      throw "arrgh"
+      call assert_report('should not get here')`
+    finally
+      Xpath 'b'
+      throw "brrr"
+      call assert_report('should not get here')`
+    endtry
+    call assert_report('should not get here')`
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('E605: Exception not caught: brrr', v:errmsg)
+    call assert_equal('ab', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_5()
+  CheckEnglish
+
+  " Need to catch and handle interrupt, otherwise the test will wait for the
+  " user to press <Enter> to continue
+  let test =<< trim [CODE]
+    try
+      try
+        Xpath 'a'
+        call interrupt()
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    catch /^Vim:Interrupt$/
+      Xpath 'b'
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ab', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_6()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      let x = novar	" error E121; exception: E121
+    catch /E15:/	" should not catch
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+    call assert_equal('E121: Undefined variable: novar', v:errmsg)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_uncaught_exception_7()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      " error E108/E488; exception: E488
+      unlet novar #
+    catch /E108:/       " should not catch
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+    call assert_equal('E488: Trailing characters: #', v:errmsg)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 53:  Nesting errors: :endif/:else/:elseif			    {{{1
+"
+"	    For nesting errors of :if conditionals the correct error messages
+"	    should be given.
+"-------------------------------------------------------------------------------
+
+func Test_nested_if_else_errors()
+  CheckEnglish
+
+  " :endif without :if
+  let code =<< trim END
+    endif
+  END
+  call writefile(code, 'Xtest', 'D')
+  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
+
+  " :endif without :if
+  let code =<< trim END
+    while 1
+      endif
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
+
+  " :endif without :if
+  let code =<< trim END
+    try
+    finally
+      endif
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
+
+  " :endif without :if
+  let code =<< trim END
+    try
+      endif
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
+
+  " :endif without :if
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      endif
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endif):E580: :endif without :if')
+
+  " :else without :if
+  let code =<< trim END
+    else
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
+
+  " :else without :if
+  let code =<< trim END
+    while 1
+      else
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
+
+  " :else without :if
+  let code =<< trim END
+    try
+    finally
+      else
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
+
+  " :else without :if
+  let code =<< trim END
+    try
+      else
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
+
+  " :else without :if
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      else
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E581: :else without :if')
+
+  " :elseif without :if
+  let code =<< trim END
+    elseif 1
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
+
+  " :elseif without :if
+  let code =<< trim END
+    while 1
+      elseif 1
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
+
+  " :elseif without :if
+  let code =<< trim END
+    try
+    finally
+      elseif 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
+
+  " :elseif without :if
+  let code =<< trim END
+    try
+      elseif 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
+
+  " :elseif without :if
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      elseif 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E582: :elseif without :if')
+
+  " multiple :else
+  let code =<< trim END
+    if 1
+    else
+    else
+    endif
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(else):E583: Multiple :else')
+
+  " :elseif after :else
+  let code =<< trim END
+    if 1
+    else
+    elseif 1
+    endif
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(elseif):E584: :elseif after :else')
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 54:  Nesting errors: :while/:endwhile				    {{{1
+"
+"	    For nesting errors of :while conditionals the correct error messages
+"	    should be given.
+"
+"	    This test reuses the function MESSAGES() from the previous test.
+"	    This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+func Test_nested_while_error()
+  CheckEnglish
+
+  " :endwhile without :while
+  let code =<< trim END
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " :endwhile without :while
+  let code =<< trim END
+    if 1
+      endwhile
+    endif
+  END
+  call writefile(code, 'Xtest', 'D')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " Missing :endif
+  let code =<< trim END
+    while 1
+      if 1
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
+
+  " :endwhile without :while
+  let code =<< trim END
+    try
+    finally
+      endwhile
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " Missing :endtry
+  let code =<< trim END
+    while 1
+      try
+      finally
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
+
+  " Missing :endtry
+  let code =<< trim END
+    while 1
+      if 1
+        try
+        finally
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E600: Missing :endtry')
+
+  " Missing :endif
+  let code =<< trim END
+    while 1
+      try
+      finally
+        if 1
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E171: Missing :endif')
+
+  " :endwhile without :while
+  let code =<< trim END
+    try
+      endwhile
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " :endwhile without :while
+  let code =<< trim END
+    while 1
+      try
+        endwhile
+      endtry
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " :endwhile without :while
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      endwhile
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+
+  " :endwhile without :while
+  let code =<< trim END
+    while 1
+      try
+        throw "a"
+      catch /a/
+        endwhile
+      endtry
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endwhile):E588: :endwhile without :while')
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 55:  Nesting errors: :continue/:break				    {{{1
+"
+"	    For nesting errors of :continue and :break commands the correct
+"	    error messages should be given.
+"
+"	    This test reuses the function MESSAGES() from the previous test.
+"	    This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+func Test_nested_cont_break_error()
+  CheckEnglish
+
+  " :continue without :while
+  let code =<< trim END
+    continue
+  END
+  call writefile(code, 'Xtest', 'D')
+  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
+
+  " :continue without :while
+  let code =<< trim END
+    if 1
+      continue
+    endif
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
+
+  " :continue without :while
+  let code =<< trim END
+    try
+    finally
+      continue
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
+
+  " :continue without :while
+  let code =<< trim END
+    try
+      continue
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
+
+  " :continue without :while
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      continue
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(continue):E586: :continue without :while or :for')
+
+  " :break without :while
+  let code =<< trim END
+    break
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
+
+  " :break without :while
+  let code =<< trim END
+    if 1
+      break
+    endif
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
+
+  " :break without :while
+  let code =<< trim END
+    try
+    finally
+      break
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
+
+  " :break without :while
+  let code =<< trim END
+    try
+      break
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
+
+  " :break without :while
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      break
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(break):E587: :break without :while or :for')
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 56:  Nesting errors: :endtry					    {{{1
+"
+"	    For nesting errors of :try conditionals the correct error messages
+"	    should be given.
+"
+"	    This test reuses the function MESSAGES() from the previous test.
+"	    This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+func Test_nested_endtry_error()
+  CheckEnglish
+
+  " :endtry without :try
+  let code =<< trim END
+    endtry
+  END
+  call writefile(code, 'Xtest', 'D')
+  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
+
+  " :endtry without :try
+  let code =<< trim END
+    if 1
+      endtry
+    endif
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
+
+  " :endtry without :try
+  let code =<< trim END
+    while 1
+      endtry
+    endwhile
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E602: :endtry without :try')
+
+  " Missing :endif
+  let code =<< trim END
+    try
+        if 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
+
+  " Missing :endwhile
+  let code =<< trim END
+    try
+      while 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
+
+  " Missing :endif
+  let code =<< trim END
+    try
+    finally
+      if 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
+
+  " Missing :endwhile
+  let code =<< trim END
+    try
+    finally
+      while 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
+
+  " Missing :endif
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      if 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E171: Missing :endif')
+
+  " Missing :endwhile
+  let code =<< trim END
+    try
+      throw "a"
+    catch /a/
+      while 1
+    endtry
+  END
+  call writefile(code, 'Xtest')
+  call AssertException(['source Xtest'], 'Vim(endtry):E170: Missing :endwhile')
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 57:  v:exception and v:throwpoint for user exceptions		    {{{1
+"
+"	    v:exception evaluates to the value of the exception that was caught
+"	    most recently and is not finished.  (A caught exception is finished
+"	    when the next ":catch", ":finally", or ":endtry" is reached.)
+"	    v:throwpoint evaluates to the script/function name and line number
+"	    where that exception has been thrown.
+"-------------------------------------------------------------------------------
+
+func Test_user_exception_info()
+  CheckEnglish
+
+  XpathINIT
+  XloopINIT
+
+  func FuncException()
+    let g:exception = v:exception
+  endfunc
+
+  func FuncThrowpoint()
+    let g:throwpoint = v:throwpoint
+  endfunc
+
+  let scriptException  = MakeScript("FuncException")
+  let scriptThrowPoint = MakeScript("FuncThrowpoint")
+
+  command! CmdException  let g:exception  = v:exception
+  command! CmdThrowpoint let g:throwpoint = v:throwpoint
+
+  func T(arg, line)
+    if a:line == 2
+      throw a:arg		" in line 2
+    elseif a:line == 4
+      throw a:arg		" in line 4
+    elseif a:line == 6
+      throw a:arg		" in line 6
+    elseif a:line == 8
+      throw a:arg		" in line 8
+    endif
+  endfunc
+
+  func G(arg, line)
+    call T(a:arg, a:line)
+  endfunc
+
+  func F(arg, line)
+    call G(a:arg, a:line)
+  endfunc
+
+  let scriptT = MakeScript("T")
+  let scriptG = MakeScript("G", scriptT)
+  let scriptF = MakeScript("F", scriptG)
+
+  try
+    Xpath 'a'
+    call F("oops", 2)
+  catch /.*/
+    Xpath 'b'
+    let exception  = v:exception
+    let throwpoint = v:throwpoint
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+
+    exec "let exception  = v:exception"
+    exec "let throwpoint = v:throwpoint"
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+
+    CmdException
+    CmdThrowpoint
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+
+    call FuncException()
+    call FuncThrowpoint()
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+
+    exec "source" scriptException
+    exec "source" scriptThrowPoint
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+
+    try
+      Xpath 'c'
+      call G("arrgh", 4)
+    catch /.*/
+      Xpath 'd'
+      let exception  = v:exception
+      let throwpoint = v:throwpoint
+      call assert_equal("arrgh", v:exception)
+      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
+      call assert_match('\<4\>', v:throwpoint)
+
+      try
+        Xpath 'e'
+        let g:arg = "autsch"
+        let g:line = 6
+        exec "source" scriptF
+      catch /.*/
+        Xpath 'f'
+        let exception  = v:exception
+        let throwpoint = v:throwpoint
+        call assert_equal("autsch", v:exception)
+        call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
+        call assert_match('\<6\>', v:throwpoint)
+      finally
+        Xpath 'g'
+        let exception  = v:exception
+        let throwpoint = v:throwpoint
+        call assert_equal("arrgh", v:exception)
+        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
+        call assert_match('\<4\>', v:throwpoint)
+        try
+          Xpath 'h'
+          let g:arg = "brrrr"
+          let g:line = 8
+          exec "source" scriptG
+        catch /.*/
+          Xpath 'i'
+          let exception  = v:exception
+          let throwpoint = v:throwpoint
+          " Resolve scriptT for matching it against v:throwpoint.
+          call assert_equal("brrrr", v:exception)
+          call assert_match(fnamemodify(scriptT, ':t'), v:throwpoint)
+          call assert_match('\<8\>', v:throwpoint)
+        finally
+          Xpath 'j'
+          let exception  = v:exception
+          let throwpoint = v:throwpoint
+          call assert_equal("arrgh", v:exception)
+          call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
+          call assert_match('\<4\>', v:throwpoint)
+        endtry
+        Xpath 'k'
+        let exception  = v:exception
+        let throwpoint = v:throwpoint
+        call assert_equal("arrgh", v:exception)
+        call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
+        call assert_match('\<4\>', v:throwpoint)
+      endtry
+      Xpath 'l'
+      let exception  = v:exception
+      let throwpoint = v:throwpoint
+      call assert_equal("arrgh", v:exception)
+      call assert_match('\<G\[1]\.\.T\>', v:throwpoint)
+      call assert_match('\<4\>', v:throwpoint)
+    finally
+      Xpath 'm'
+      let exception  = v:exception
+      let throwpoint = v:throwpoint
+      call assert_equal("oops", v:exception)
+      call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+      call assert_match('\<2\>', v:throwpoint)
+    endtry
+    Xpath 'n'
+    let exception  = v:exception
+    let throwpoint = v:throwpoint
+    call assert_equal("oops", v:exception)
+    call assert_match('\<F\[1]\.\.G\[1]\.\.T\>', v:throwpoint)
+    call assert_match('\<2\>', v:throwpoint)
+  finally
+    Xpath 'o'
+    let exception  = v:exception
+    let throwpoint = v:throwpoint
+    call assert_equal("", v:exception)
+    call assert_match('^$', v:throwpoint)
+    call assert_match('^$', v:throwpoint)
+  endtry
+
+  call assert_equal('abcdefghijklmno', g:Xpath)
+
+  unlet exception throwpoint
+  delfunction FuncException
+  delfunction FuncThrowpoint
+  call delete(scriptException)
+  call delete(scriptThrowPoint)
+  unlet scriptException scriptThrowPoint
+  delcommand CmdException
+  delcommand CmdThrowpoint
+  delfunction T
+  delfunction G
+  delfunction F
+  call delete(scriptT)
+  call delete(scriptG)
+  call delete(scriptF)
+  unlet scriptT scriptG scriptF
+endfunc
+
+"-------------------------------------------------------------------------------
+"
+" Test 58:  v:exception and v:throwpoint for error/interrupt exceptions	    {{{1
+"
+"	    v:exception and v:throwpoint work also for error and interrupt
+"	    exceptions.
+"-------------------------------------------------------------------------------
+
+func Test_exception_info_for_error()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    func T(line)
+      if a:line == 2
+        delfunction T		" error (function in use) in line 2
+      elseif a:line == 4
+        call interrupt()
+      endif
+    endfunc
+
+    while 1
+      try
+        Xpath 'a'
+        call T(2)
+        call assert_report('should not get here')
+      catch /.*/
+        Xpath 'b'
+        if v:exception !~ 'Vim(delfunction):'
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint !~ '\<T\>'
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint !~ '\<2\>'
+          call assert_report('should not get here')
+        endif
+      finally
+        Xpath 'c'
+        if v:exception != ""
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint != ""
+          call assert_report('should not get here')
+        endif
+        break
+      endtry
+    endwhile
+
+    Xpath 'd'
+    if v:exception != ""
+      call assert_report('should not get here')
+    endif
+    if v:throwpoint != ""
+      call assert_report('should not get here')
+    endif
+
+    while 1
+      try
+        Xpath 'e'
+        call T(4)
+        call assert_report('should not get here')
+      catch /.*/
+        Xpath 'f'
+        if v:exception != 'Vim:Interrupt'
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint !~ 'function T'
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint !~ '\<4\>'
+          call assert_report('should not get here')
+        endif
+      finally
+        Xpath 'g'
+        if v:exception != ""
+          call assert_report('should not get here')
+        endif
+        if v:throwpoint != ""
+          call assert_report('should not get here')
+        endif
+        break
+      endtry
+    endwhile
+
+    Xpath 'h'
+    if v:exception != ""
+      call assert_report('should not get here')
+    endif
+    if v:throwpoint != ""
+      call assert_report('should not get here')
+    endif
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefgh', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+"
+" Test 59:  v:exception and v:throwpoint when discarding exceptions	    {{{1
+"
+"	    When a :catch clause is left by a ":break" etc or an error or
+"	    interrupt exception, v:exception and v:throwpoint are reset.  They
+"	    are not affected by an exception that is discarded before being
+"	    caught.
+"-------------------------------------------------------------------------------
+func Test_exception_info_on_discard()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    let sfile = expand("<sfile>")
+
+    while 1
+      try
+        throw "x1"
+      catch /.*/
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    while 1
+      try
+        throw "x2"
+      catch /.*/
+        break
+      finally
+        call assert_equal('', v:exception)
+        call assert_equal('', v:throwpoint)
+      endtry
+      break
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    while 1
+      try
+        let errcaught = 0
+        try
+          try
+            throw "x3"
+          catch /.*/
+            let lnum = expand("<sflnum>")
+            asdf
+          endtry
+        catch /.*/
+          let errcaught = 1
+          call assert_match('Vim:E492: Not an editor command:', v:exception)
+          call assert_match('line ' .. (lnum + 1), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, errcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'a'
+
+    while 1
+      try
+        let intcaught = 0
+        try
+          try
+            throw "x4"
+          catch /.*/
+            let lnum = expand("<sflnum>")
+            call interrupt()
+          endtry
+        catch /.*/
+          let intcaught = 1
+          call assert_match('Vim:Interrupt', v:exception)
+          call assert_match('line ' .. (lnum + 1), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, intcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'b'
+
+    while 1
+      try
+        let errcaught = 0
+        try
+          try
+            if 1
+              let lnum = expand("<sflnum>")
+              throw "x5"
+            " missing endif
+          catch /.*/
+            call assert_report('should not get here')
+          endtry
+        catch /.*/
+          let errcaught = 1
+          call assert_match('Vim(catch):E171: Missing :endif:', v:exception)
+          call assert_match('line ' .. (lnum + 3), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, errcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'c'
+
+    try
+      while 1
+        try
+          throw "x6"
+        finally
+          break
+        endtry
+        break
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    try
+      while 1
+        try
+          throw "x7"
+        finally
+          break
+        endtry
+        break
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      call assert_equal('', v:exception)
+      call assert_equal('', v:throwpoint)
+    endtry
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    while 1
+      try
+        let errcaught = 0
+        try
+          try
+            throw "x8"
+          finally
+            let lnum = expand("<sflnum>")
+            asdf
+          endtry
+        catch /.*/
+          let errcaught = 1
+          call assert_match('Vim:E492: Not an editor command:', v:exception)
+          call assert_match('line ' .. (lnum + 1), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, errcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'd'
+
+    while 1
+      try
+        let intcaught = 0
+        try
+          try
+            throw "x9"
+          finally
+            let lnum = expand("<sflnum>")
+            call interrupt()
+          endtry
+        catch /.*/
+          let intcaught = 1
+          call assert_match('Vim:Interrupt', v:exception)
+          call assert_match('line ' .. (lnum + 1), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, intcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'e'
+
+    while 1
+      try
+        let errcaught = 0
+        try
+          try
+            if 1
+              let lnum = expand("<sflnum>")
+              throw "x10"
+            " missing endif
+          finally
+            call assert_equal('', v:exception)
+            call assert_equal('', v:throwpoint)
+          endtry
+        catch /.*/
+          let errcaught = 1
+          call assert_match('Vim(finally):E171: Missing :endif:', v:exception)
+          call assert_match('line ' .. (lnum + 3), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, errcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'f'
+
+    while 1
+      try
+        let errcaught = 0
+        try
+          try
+            if 1
+              let lnum = expand("<sflnum>")
+              throw "x11"
+            " missing endif
+          endtry
+        catch /.*/
+          let errcaught = 1
+          call assert_match('Vim(endtry):E171: Missing :endif:', v:exception)
+          call assert_match('line ' .. (lnum + 3), v:throwpoint)
+        endtry
+      finally
+        call assert_equal(1, errcaught)
+        break
+      endtry
+    endwhile
+    call assert_equal('', v:exception)
+    call assert_equal('', v:throwpoint)
+
+    Xpath 'g'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefg', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+"
+" Test 60:  (Re)throwing v:exception; :echoerr.				    {{{1
+"
+"	    A user exception can be rethrown after catching by throwing
+"	    v:exception.  An error or interrupt exception cannot be rethrown
+"	    because Vim exceptions cannot be faked.  A Vim exception using the
+"	    value of v:exception can, however, be triggered by the :echoerr
+"	    command.
+"-------------------------------------------------------------------------------
+
+func Test_rethrow_exception_1()
+  XpathINIT
+  try
+    try
+      Xpath 'a'
+      throw "oops"
+    catch /oops/
+      Xpath 'b'
+      throw v:exception	" rethrow user exception
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+  catch /^oops$/			" catches rethrown user exception
+    Xpath 'c'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_rethrow_exception_2()
+  XpathINIT
+  try
+    let caught = 0
+    try
+      Xpath 'a'
+      write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
+      call assert_report('should not get here')
+    catch /^Vim(write):/
+      let caught = 1
+      throw v:exception	" throw error: cannot fake Vim exception
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'b'
+      call assert_equal(1, caught)
+    endtry
+  catch /^Vim(throw):/	" catches throw error
+    let caught = caught + 1
+  catch /.*/
+    call assert_report('should not get here')
+  finally
+    Xpath 'c'
+    call assert_equal(2, caught)
+  endtry
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_rethrow_exception_3()
+  XpathINIT
+  try
+    let caught = 0
+    try
+      Xpath 'a'
+      asdf
+    catch /^Vim/		" catch error exception
+      let caught = 1
+      " Trigger Vim error exception with value specified after :echoerr
+      let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+      echoerr value
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'b'
+      call assert_equal(1, caught)
+    endtry
+  catch /^Vim(echoerr):/
+    let caught = caught + 1
+    call assert_match(value, v:exception)
+  catch /.*/
+    call assert_report('should not get here')
+  finally
+    Xpath 'c'
+    call assert_equal(2, caught)
+  endtry
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_rethrow_exception_3()
+  XpathINIT
+  try
+    let errcaught = 0
+    try
+      Xpath 'a'
+      let intcaught = 0
+      call interrupt()
+    catch /^Vim:/		" catch interrupt exception
+      let intcaught = 1
+      " Trigger Vim error exception with value specified after :echoerr
+      echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'b'
+      call assert_equal(1, intcaught)
+    endtry
+  catch /^Vim(echoerr):/
+    let errcaught = 1
+    call assert_match('Interrupt', v:exception)
+  finally
+    Xpath 'c'
+    call assert_equal(1, errcaught)
+  endtry
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 61:  Catching interrupt exceptions				    {{{1
+"
+"	    When an interrupt occurs inside a :try/:endtry region, an
+"	    interrupt exception is thrown and can be caught.  Its value is
+"	    "Vim:Interrupt".  If the interrupt occurs after an error or a :throw
+"	    but before a matching :catch is reached, all following :catches of
+"	    that try block are ignored, but the interrupt exception can be
+"	    caught by the next surrounding try conditional.  An interrupt is
+"	    ignored when there is a previous interrupt that has not been caught
+"	    or causes a :finally clause to be executed.
+"-------------------------------------------------------------------------------
+
+func Test_catch_intr_exception()
+  let test =<< trim [CODE]
+    while 1
+      try
+        try
+          Xpath 'a'
+          call interrupt()
+          call assert_report('should not get here')
+        catch /^Vim:Interrupt$/
+          Xpath 'b'
+        finally
+          Xpath 'c'
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'd'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          try
+            Xpath 'e'
+            asdf
+            call assert_report('should not get here')
+          catch /do_not_catch/
+            call assert_report('should not get here')
+          catch /.*/
+            Xpath 'f'
+            call interrupt()
+            call assert_report('should not get here')
+          catch /.*/
+            call assert_report('should not get here')
+          finally
+            Xpath 'g'
+            call interrupt()
+            call assert_report('should not get here')
+          endtry
+        catch /^Vim:Interrupt$/
+          Xpath 'h'
+        finally
+          Xpath 'i'
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'j'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          try
+            Xpath 'k'
+            throw "x"
+            call assert_report('should not get here')
+          catch /do_not_catch/
+            call assert_report('should not get here')
+          catch /x/
+            Xpath 'l'
+            call interrupt()
+            call assert_report('should not get here')
+          catch /.*/
+            call assert_report('should not get here')
+          endtry
+        catch /^Vim:Interrupt$/
+          Xpath 'm'
+        finally
+          Xpath 'n'
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'o'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          Xpath 'p'
+          call interrupt()
+          call assert_report('should not get here')
+        catch /do_not_catch/
+          call interrupt()
+          call assert_report('should not get here')
+        catch /^Vim:Interrupt$/
+          Xpath 'q'
+        finally
+          Xpath 'r'
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 's'
+        break
+      endtry
+    endwhile
+
+    Xpath 't'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghijklmnopqrst', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 62:  Catching error exceptions					    {{{1
+"
+"	    An error inside a :try/:endtry region is converted to an exception
+"	    and can be caught.  The error exception has a "Vim(cmdname):" prefix
+"	    where cmdname is the name of the failing command, or a "Vim:" prefix
+"	    if no command name is known.  The "Vim" prefixes cannot be faked.
+"-------------------------------------------------------------------------------
+
+func Test_catch_err_exception_1()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        unlet novar
+      catch /^Vim(unlet):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match('E108: No such variable: "novar"', v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_catch_err_exception_2()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        throw novar			" error in :throw
+      catch /^Vim(throw):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match('E121: Undefined variable: novar', v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_catch_err_exception_3()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        throw "Vim:faked"		" error: cannot fake Vim exception
+      catch /^Vim(throw):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match("E608: Cannot :throw exceptions with 'Vim' prefix",
+              \ v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+endfunc
+
+func Test_catch_err_exception_4()
+  XpathINIT
+  func F()
+    while 1
+    " Missing :endwhile
+  endfunc
+
+  while 1
+    try
+      try
+        let caught = 0
+        call F()
+      catch /^Vim(endfunction):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match("E170: Missing :endwhile", v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+  delfunc F
+endfunc
+
+func Test_catch_err_exception_5()
+  XpathINIT
+  func F()
+    while 1
+    " Missing :endwhile
+  endfunc
+
+  while 1
+    try
+      try
+        let caught = 0
+        ExecAsScript F
+      catch /^Vim:/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match("E170: Missing :endwhile", v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+  delfunc F
+endfunc
+
+func Test_catch_err_exception_6()
+  XpathINIT
+  func G()
+    call G()
+  endfunc
+
+  while 1
+    try
+      let mfd_save = &mfd
+      set mfd=3
+      try
+        let caught = 0
+        call G()
+      catch /^Vim(call):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      let &mfd = mfd_save
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abc', g:Xpath)
+  delfunc G
+endfunc
+
+func Test_catch_err_exception_7()
+  XpathINIT
+  func H()
+    return H()
+  endfunc
+
+  while 1
+    try
+      let mfd_save = &mfd
+      set mfd=3
+      try
+        let caught = 0
+        call H()
+      catch /^Vim(return):/
+        Xpath 'a'
+        let caught = 1
+        let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
+      finally
+        Xpath 'b'
+        call assert_equal(1, caught)
+        call assert_match("E132: Function call depth is higher than 'maxfuncdepth'", v:errmsg)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'c'
+      let &mfd = mfd_save
+      break		" discard error for $VIMNOERRTHROW
+    endtry
+    call assert_report('should not get here')
+  endwhile
+
+  call assert_equal('abc', g:Xpath)
+  delfunc H
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 63:  Suppressing error exceptions by :silent!.			    {{{1
+"
+"	    A :silent! command inside a :try/:endtry region suppresses the
+"	    conversion of errors to an exception and the immediate abortion on
+"	    error.  When the commands executed by the :silent! themselves open
+"	    a new :try/:endtry region, conversion of errors to exception and
+"	    immediate abortion is switched on again - until the next :silent!
+"	    etc.  The :silent! has the effect of setting v:errmsg to the error
+"	    message text (without displaying it) and continuing with the next
+"	    script line.
+"
+"	    When a command triggering autocommands is executed by :silent!
+"	    inside a :try/:endtry, the autocommand execution is not suppressed
+"	    on error.
+"
+"	    This test reuses the function MSG() from the previous test.
+"-------------------------------------------------------------------------------
+
+func Test_silent_exception()
+  XpathINIT
+  XloopINIT
+  let g:taken = ""
+
+  func S(n) abort
+    XloopNEXT
+    let g:taken = g:taken . "E" . a:n
+    let v:errmsg = ""
+    exec "asdf" . a:n
+
+    " Check that ":silent!" continues:
+    Xloop 'a'
+
+    " Check that ":silent!" sets "v:errmsg":
+    call assert_match("E492: Not an editor command", v:errmsg)
+  endfunc
+
+  func Foo()
+    while 1
+      try
+        try
+          let caught = 0
+          " This is not silent:
+          call S(3)
+        catch /^Vim:/
+          Xpath 'b'
+          let caught = 1
+          let errmsg3 = substitute(v:exception, '^Vim:', '', "")
+          silent! call S(4)
+        finally
+          call assert_equal(1, caught)
+          Xpath 'c'
+          call assert_match("E492: Not an editor command", errmsg3)
+          silent! call S(5)
+          " Break out of try conditionals that cover ":silent!".  This also
+          " discards the aborting error when $VIMNOERRTHROW is non-zero.
+          break
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      endtry
+    endwhile
+    " This is a double ":silent!" (see caller).
+    silent! call S(6)
+  endfunc
+
+  func Bar()
+    try
+      silent! call S(2)
+      silent! execute "call Foo() | call S(7)"
+      silent! call S(8)
+    endtry	" normal end of try cond that covers ":silent!"
+    " This has a ":silent!" from the caller:
+    call S(9)
+  endfunc
+
+  silent! call S(1)
+  silent! call Bar()
+  silent! call S(10)
+
+  call assert_equal("E1E2E3E4E5E6E7E8E9E10", g:taken)
+
+  augroup TMP
+    au!
+    autocmd BufWritePost * Xpath 'd'
+  augroup END
+
+  Xpath 'e'
+  silent! write /i/m/p/o/s/s/i/b/l/e
+  Xpath 'f'
+
+  call assert_equal('a2a3ba5ca6a7a8a9a10a11edf', g:Xpath)
+
+  augroup TMP
+    au!
+  augroup END
+  augroup! TMP
+  delfunction S
+  delfunction Foo
+  delfunction Bar
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 64:  Error exceptions after error, interrupt or :throw		    {{{1
+"
+"	    When an error occurs after an interrupt or a :throw but before
+"	    a matching :catch is reached, all following :catches of that try
+"	    block are ignored, but the error exception can be caught by the next
+"	    surrounding try conditional.  Any previous error exception is
+"	    discarded.  An error is ignored when there is a previous error that
+"	    has not been caught.
+"-------------------------------------------------------------------------------
+
+func Test_exception_after_error_1()
+  XpathINIT
+  while 1
+    try
+      try
+        Xpath 'a'
+        let caught = 0
+        while 1
+          if 1
+          " Missing :endif
+        endwhile	" throw error exception
+      catch /^Vim(/
+        Xpath 'b'
+        let caught = 1
+      finally
+        Xpath 'c'
+        call assert_equal(1, caught)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'd'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abcd', g:Xpath)
+endfunc
+
+func Test_exception_after_error_2()
+  XpathINIT
+  while 1
+    try
+      try
+        Xpath 'a'
+        let caught = 0
+        try
+          if 1
+          " Missing :endif
+        catch /.*/	" throw error exception
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        endtry
+      catch /^Vim(/
+        Xpath 'b'
+        let caught = 1
+      finally
+        Xpath 'c'
+        call assert_equal(1, caught)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'd'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abcd', g:Xpath)
+endfunc
+
+func Test_exception_after_error_3()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        try
+          Xpath 'a'
+          call interrupt()
+        catch /do_not_catch/
+          call assert_report('should not get here')
+          if 1
+          " Missing :endif
+        catch /.*/	" throw error exception
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        endtry
+      catch /^Vim(/
+        Xpath 'b'
+        let caught = 1
+      finally
+        Xpath 'c'
+        call assert_equal(1, caught)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'd'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abcd', g:Xpath)
+endfunc
+
+func Test_exception_after_error_4()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        try
+          Xpath 'a'
+          throw "x"
+        catch /do_not_catch/
+          call assert_report('should not get here')
+          if 1
+          " Missing :endif
+        catch /x/	" throw error exception
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        endtry
+      catch /^Vim(/
+        Xpath 'b'
+        let caught = 1
+      finally
+        Xpath 'c'
+        call assert_equal(1, caught)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'd'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abcd', g:Xpath)
+endfunc
+
+func Test_exception_after_error_5()
+  XpathINIT
+  while 1
+    try
+      try
+        let caught = 0
+        Xpath 'a'
+        endif		" :endif without :if; throw error exception
+        if 1
+        " Missing :endif
+      catch /do_not_catch/ " ignore new error
+        call assert_report('should not get here')
+      catch /^Vim(endif):/
+        Xpath 'b'
+        let caught = 1
+      catch /^Vim(/
+        call assert_report('should not get here')
+      finally
+        Xpath 'c'
+        call assert_equal(1, caught)
+      endtry
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      Xpath 'd'
+      break
+    endtry
+    call assert_report('should not get here')
+  endwhile
+  call assert_equal('abcd', g:Xpath)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 65:  Errors in the /pattern/ argument of a :catch		    {{{1
+"
+"	    On an error in the /pattern/ argument of a :catch, the :catch does
+"	    not match.  Any following :catches of the same :try/:endtry don't
+"	    match either.  Finally clauses are executed.
+"-------------------------------------------------------------------------------
+
+func Test_catch_pattern_error()
+  CheckEnglish
+  XpathINIT
+
+  try
+    try
+      Xpath 'a'
+      throw "oops"
+    catch /^oops$/
+      Xpath 'b'
+    catch /\)/		" not checked; exception has already been caught
+      call assert_report('should not get here')
+    endtry
+    Xpath 'c'
+  catch /.*/
+    call assert_report('should not get here')
+  endtry
+  call assert_equal('abc', g:Xpath)
+
+  XpathINIT
+  func F()
+    try
+      try
+        try
+          Xpath 'a'
+          throw "ab"
+        catch /abc/	" does not catch
+          call assert_report('should not get here')
+        catch /\)/	" error; discards exception
+          call assert_report('should not get here')
+        catch /.*/	" not checked
+          call assert_report('should not get here')
+        finally
+          Xpath 'b'
+        endtry
+        call assert_report('should not get here')
+      catch /^ab$/	" checked, but original exception is discarded
+        call assert_report('should not get here')
+      catch /^Vim(catch):/
+        Xpath 'c'
+        call assert_match('Vim(catch):E475: Invalid argument:', v:exception)
+      finally
+        Xpath 'd'
+      endtry
+      Xpath 'e'
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+    Xpath 'f'
+  endfunc
+
+  call F()
+  call assert_equal('abcdef', g:Xpath)
+
+  delfunc F
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 66:  Stop range :call on error, interrupt, or :throw		    {{{1
+"
+"	    When a function which is multiply called for a range since it
+"	    doesn't handle the range itself has an error in a command
+"	    dynamically enclosed by :try/:endtry or gets an interrupt or
+"	    executes a :throw, no more calls for the remaining lines in the
+"	    range are made.  On an error in a command not dynamically enclosed
+"	    by :try/:endtry, the function is executed again for the remaining
+"	    lines in the range.
+"-------------------------------------------------------------------------------
+
+func Test_stop_range_on_error()
+  let test =<< trim [CODE]
+    let file = tempname()
+    exec "edit" file
+    call setline(1, ['line 1', 'line 2', 'line 3'])
+    let taken = ""
+    let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
+
+    func F(reason, n) abort
+      let g:taken = g:taken .. "F" .. a:n ..
+                          \ substitute(a:reason, '\(\l\).*', '\u\1', "") ..
+                          \ "(" .. line(".") .. ")"
+
+      if a:reason == "error"
+        asdf
+      elseif a:reason == "interrupt"
+        call interrupt()
+      elseif a:reason == "throw"
+        throw "xyz"
+      elseif a:reason == "aborting error"
+        XloopNEXT
+        call assert_equal(g:taken, g:expected)
+        try
+          bwipeout!
+          call delete(g:file)
+          asdf
+        endtry
+      endif
+    endfunc
+
+    func G(reason, n)
+      let g:taken = g:taken .. "G" .. a:n ..
+                              \ substitute(a:reason, '\(\l\).*', '\u\1', "")
+      1,3call F(a:reason, a:n)
+    endfunc
+
+    Xpath 'a'
+    call G("error", 1)
+    try
+      Xpath 'b'
+      try
+        call G("error", 2)
+        call assert_report('should not get here')
+      finally
+        Xpath 'c'
+        try
+          call G("interrupt", 3)
+          call assert_report('should not get here')
+        finally
+          Xpath 'd'
+          try
+            call G("throw", 4)
+            call assert_report('should not get here')
+          endtry
+        endtry
+      endtry
+    catch /xyz/
+      Xpath 'e'
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+    Xpath 'f'
+    call G("aborting error", 5)
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdef', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 67:  :throw across :call command					    {{{1
+"
+"	    On a call command, an exception might be thrown when evaluating the
+"	    function name, during evaluation of the arguments, or when the
+"	    function is being executed.  The exception can be caught by the
+"	    caller.
+"-------------------------------------------------------------------------------
+
+func THROW(x, n)
+  if a:n == 1
+    Xpath 'A'
+  elseif a:n == 2
+    Xpath 'B'
+  elseif a:n == 3
+    Xpath 'C'
+  endif
+  throw a:x
+endfunc
+
+func NAME(x, n)
+  if a:n == 1
+    call assert_report('should not get here')
+  elseif a:n == 2
+    Xpath 'D'
+  elseif a:n == 3
+    Xpath 'E'
+  elseif a:n == 4
+    Xpath 'F'
+  endif
+  return a:x
+endfunc
+
+func ARG(x, n)
+  if a:n == 1
+    call assert_report('should not get here')
+  elseif a:n == 2
+    call assert_report('should not get here')
+  elseif a:n == 3
+    Xpath 'G'
+  elseif a:n == 4
+    Xpath 'I'
+  endif
+  return a:x
+endfunc
+
+func Test_throw_across_call_cmd()
+  XpathINIT
+
+  func F(x, n)
+    if a:n == 2
+      call assert_report('should not get here')
+    elseif a:n == 4
+      Xpath 'a'
+    endif
+  endfunc
+
+  while 1
+    try
+      let v:errmsg = ""
+
+      while 1
+        try
+          Xpath 'b'
+          call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+          call assert_report('should not get here')
+        catch /^name$/
+          Xpath 'c'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+
+      while 1
+        try
+          Xpath 'd'
+          call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+          call assert_report('should not get here')
+        catch /^arg$/
+          Xpath 'e'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+
+      while 1
+        try
+          Xpath 'f'
+          call {NAME("THROW", 3)}(ARG("call", 3), 3)
+          call assert_report('should not get here')
+        catch /^call$/
+          Xpath 'g'
+        catch /^0$/	    " default return value
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+
+      while 1
+        try
+          Xpath 'h'
+          call {NAME("F", 4)}(ARG(4711, 4), 4)
+          Xpath 'i'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+
+    catch /^0$/	    " default return value
+      call assert_report('should not get here')
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      call assert_equal("", v:errmsg)
+      let v:errmsg = ""
+      break
+    endtry
+  endwhile
+
+  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
+  delfunction F
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 68:  :throw across function calls in expressions			    {{{1
+"
+"	    On a function call within an expression, an exception might be
+"	    thrown when evaluating the function name, during evaluation of the
+"	    arguments, or when the function is being executed.  The exception
+"	    can be caught by the caller.
+"
+"	    This test reuses the functions THROW(), NAME(), and ARG() from the
+"	    previous test.
+"-------------------------------------------------------------------------------
+
+func Test_throw_across_call_expr()
+  XpathINIT
+
+  func F(x, n)
+    if a:n == 2
+      call assert_report('should not get here')
+    elseif a:n == 4
+      Xpath 'a'
+    endif
+    return a:x
+  endfunction
+
+  while 1
+    try
+      let error = 0
+      let v:errmsg = ""
+
+      while 1
+        try
+          Xpath 'b'
+          let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+          call assert_report('should not get here')
+        catch /^name$/
+          Xpath 'c'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+      call assert_true(!exists('var1'))
+
+      while 1
+        try
+          Xpath 'd'
+          let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+          call assert_report('should not get here')
+        catch /^arg$/
+          Xpath 'e'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+      call assert_true(!exists('var2'))
+
+      while 1
+        try
+          Xpath 'f'
+          let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
+          call assert_report('should not get here')
+        catch /^call$/
+          Xpath 'g'
+        catch /^0$/	    " default return value
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+      call assert_true(!exists('var3'))
+
+      while 1
+        try
+          Xpath 'h'
+          let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
+          Xpath 'i'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          call assert_equal("", v:errmsg)
+          let v:errmsg = ""
+          break
+        endtry
+      endwhile
+      call assert_true(exists('var4') && var4 == 4711)
+
+    catch /^0$/	    " default return value
+      call assert_report('should not get here')
+    catch /.*/
+      call assert_report('should not get here')
+    finally
+      call assert_equal("", v:errmsg)
+      break
+    endtry
+  endwhile
+
+  call assert_equal('bAcdDBefEGCghFIai', g:Xpath)
+  delfunc F
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 76:  Errors, interrupts, :throw during expression evaluation	    {{{1
+"
+"	    When a function call made during expression evaluation is aborted
+"	    due to an error inside a :try/:endtry region or due to an interrupt
+"	    or a :throw, the expression evaluation is aborted as well.	No
+"	    message is displayed for the cancelled expression evaluation.  On an
+"	    error not inside :try/:endtry, the expression evaluation continues.
+"-------------------------------------------------------------------------------
+
+func Test_expr_eval_error()
+  let test =<< trim [CODE]
+    let taken = ""
+
+    func ERR(n)
+      let g:taken = g:taken .. "E" .. a:n
+      asdf
+    endfunc
+
+    func ERRabort(n) abort
+      let g:taken = g:taken .. "A" .. a:n
+      asdf
+    endfunc	" returns -1; may cause follow-up msg for illegal var/func name
+
+    func WRAP(n, arg)
+      let g:taken = g:taken .. "W" .. a:n
+      let g:saved_errmsg = v:errmsg
+      return arg
+    endfunc
+
+    func INT(n)
+      let g:taken = g:taken .. "I" .. a:n
+      call interrupt()
+    endfunc
+
+    func THR(n)
+      let g:taken = g:taken .. "T" .. a:n
+      throw "should not be caught"
+    endfunc
+
+    func CONT(n)
+      let g:taken = g:taken .. "C" .. a:n
+    endfunc
+
+    func MSG(n)
+      let g:taken = g:taken .. "M" .. a:n
+      let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
+      let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
+      call assert_match(msgptn, errmsg)
+      let v:errmsg = ""
+      let g:saved_errmsg = ""
+    endfunc
+
+    let v:errmsg = ""
+
+    try
+      let t = 1
+      while t <= 9
+        Xloop 'a'
+        try
+          if t == 1
+            let v{ERR(t) + CONT(t)} = 0
+          elseif t == 2
+            let v{ERR(t) + CONT(t)}
+          elseif t == 3
+            let var = exists('v{ERR(t) + CONT(t)}')
+          elseif t == 4
+            unlet v{ERR(t) + CONT(t)}
+          elseif t == 5
+            function F{ERR(t) + CONT(t)}()
+            endfunction
+          elseif t == 6
+            function F{ERR(t) + CONT(t)}
+          elseif t == 7
+            let var = exists('*F{ERR(t) + CONT(t)}')
+          elseif t == 8
+            delfunction F{ERR(t) + CONT(t)}
+          elseif t == 9
+            let var = ERR(t) + CONT(t)
+          endif
+        catch /asdf/
+          " v:errmsg is not set when the error message is converted to an
+          " exception.  Set it to the original error message.
+          let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+        catch /^Vim\((\a\+)\)\=:/
+          " An error exception has been thrown after the original error.
+          let v:errmsg = ""
+        finally
+          call MSG(t)
+          let t = t + 1
+          XloopNEXT
+          continue	" discard an aborting error
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+
+    try
+      let t = 10
+      while t <= 18
+        Xloop 'b'
+        try
+          if t == 10
+            let v{INT(t) + CONT(t)} = 0
+          elseif t == 11
+            let v{INT(t) + CONT(t)}
+          elseif t == 12
+            let var = exists('v{INT(t) + CONT(t)}')
+          elseif t == 13
+            unlet v{INT(t) + CONT(t)}
+          elseif t == 14
+            function F{INT(t) + CONT(t)}()
+            endfunction
+          elseif t == 15
+            function F{INT(t) + CONT(t)}
+          elseif t == 16
+            let var = exists('*F{INT(t) + CONT(t)}')
+          elseif t == 17
+            delfunction F{INT(t) + CONT(t)}
+          elseif t == 18
+            let var = INT(t) + CONT(t)
+          endif
+        catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
+          " An error exception has been triggered after the interrupt.
+          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+        finally
+          call MSG(t)
+          let t = t + 1
+          XloopNEXT
+          continue	" discard interrupt
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+
+    try
+      let t = 19
+      while t <= 27
+        Xloop 'c'
+        try
+          if t == 19
+            let v{THR(t) + CONT(t)} = 0
+          elseif t == 20
+            let v{THR(t) + CONT(t)}
+          elseif t == 21
+            let var = exists('v{THR(t) + CONT(t)}')
+          elseif t == 22
+            unlet v{THR(t) + CONT(t)}
+          elseif t == 23
+            function F{THR(t) + CONT(t)}()
+            endfunction
+          elseif t == 24
+            function F{THR(t) + CONT(t)}
+          elseif t == 25
+            let var = exists('*F{THR(t) + CONT(t)}')
+          elseif t == 26
+            delfunction F{THR(t) + CONT(t)}
+          elseif t == 27
+            let var = THR(t) + CONT(t)
+          endif
+        catch /^Vim\((\a\+)\)\=:/
+          " An error exception has been triggered after the :throw.
+          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+        finally
+          call MSG(t)
+          let t = t + 1
+          XloopNEXT
+          continue	" discard exception
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+
+    let v{ERR(28) + CONT(28)} = 0
+    call MSG(28)
+    let v{ERR(29) + CONT(29)}
+    call MSG(29)
+    let var = exists('v{ERR(30) + CONT(30)}')
+    call MSG(30)
+    unlet v{ERR(31) + CONT(31)}
+    call MSG(31)
+    function F{ERR(32) + CONT(32)}()
+    endfunction
+    call MSG(32)
+    function F{ERR(33) + CONT(33)}
+    call MSG(33)
+    let var = exists('*F{ERR(34) + CONT(34)}')
+    call MSG(34)
+    delfunction F{ERR(35) + CONT(35)}
+    call MSG(35)
+    let var = ERR(36) + CONT(36)
+    call MSG(36)
+
+    let saved_errmsg = ""
+
+    let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
+    call MSG(37)
+    let v{WRAP(38, ERRabort(38)) + CONT(38)}
+    call MSG(38)
+    let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
+    call MSG(39)
+    unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
+    call MSG(40)
+    function F{WRAP(41, ERRabort(41)) + CONT(41)}()
+    endfunction
+    call MSG(41)
+    function F{WRAP(42, ERRabort(42)) + CONT(42)}
+    call MSG(42)
+    let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
+    call MSG(43)
+    delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
+    call MSG(44)
+    let var = ERRabort(45) + CONT(45)
+    call MSG(45)
+    Xpath 'd'
+
+    let expected = ""
+          \ .. "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
+          \ .. "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
+          \ .. "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
+          \ .. "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
+          \ .. "E34C34M34E35C35M35E36C36M36"
+          \ .. "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
+          \ .. "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
+    call assert_equal(expected, taken)
+  [CODE]
+  let verify =<< trim [CODE]
+    let expected = "a1a2a3a4a5a6a7a8a9"
+                      \ .. "b10b11b12b13b14b15b16b17b18"
+                      \ .. "c19c20c21c22c23c24c25c26c27d"
+    call assert_equal(expected, g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 77:  Errors, interrupts, :throw in name{brace-expression}	    {{{1
+"
+"	    When a function call made during evaluation of an expression in
+"	    braces as part of a function name after ":function" is aborted due
+"	    to an error inside a :try/:endtry region or due to an interrupt or
+"	    a :throw, the expression evaluation is aborted as well, and the
+"	    function definition is ignored, skipping all commands to the
+"	    ":endfunction".  On an error not inside :try/:endtry, the expression
+"	    evaluation continues and the function gets defined, and can be
+"	    called and deleted.
+"-------------------------------------------------------------------------------
+func Test_brace_expr_error()
+  let test =<< trim [CODE]
+    func ERR() abort
+      Xloop 'a'
+      asdf
+    endfunc					" returns -1
+
+    func OK()
+      Xloop 'b'
+      let v:errmsg = ""
+      return 0
+    endfunc
+
+    let v:errmsg = ""
+
+    Xpath 'c'
+    func F{1 + ERR() + OK()}(arg)
+      " F0 should be defined.
+      if exists("a:arg") && a:arg == "calling"
+        Xpath 'd'
+      else
+        call assert_report('should not get here')
+      endif
+    endfunction
+    call assert_equal("", v:errmsg)
+    XloopNEXT
+
+    Xpath 'e'
+    call F{1 + ERR() + OK()}("calling")
+    call assert_equal("", v:errmsg)
+    XloopNEXT
+
+    Xpath 'f'
+    delfunction F{1 + ERR() + OK()}
+    call assert_equal("", v:errmsg)
+    XloopNEXT
+
+    try
+      while 1
+        try
+          Xpath 'g'
+          func G{1 + ERR() + OK()}(arg)
+            " G0 should not be defined, and the function body should be
+            " skipped.
+            call assert_report('should not get here')
+            " Use an unmatched ":finally" to check whether the body is
+            " skipped when an error occurs in ERR().  This works whether or
+            " not the exception is converted to an exception.
+            finally
+              call assert_report('should not get here')
+            endtry
+          try
+            call assert_report('should not get here')
+          endfunction
+
+          call assert_report('should not get here')
+        catch /asdf/
+          " Jumped to when the function is not defined and the body is
+          " skipped.
+          Xpath 'h'
+        catch /.*/
+          call assert_report('should not get here')
+        finally
+          Xpath 'i'
+          break
+        endtry			" jumped to when the body is not skipped
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ca1b1ea2b2dfa3b3ga4hi', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 78:  Messages on parsing errors in expression evaluation		    {{{1
+"
+"	    When an expression evaluation detects a parsing error, an error
+"	    message is given and converted to an exception, and the expression
+"	    evaluation is aborted.
+"-------------------------------------------------------------------------------
+func Test_expr_eval_error_msg()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    let taken = ""
+
+    func F(n)
+      let g:taken = g:taken . "F" . a:n
+    endfunc
+
+    func MSG(n, enr, emsg)
+      let g:taken = g:taken . "M" . a:n
+      call assert_match('^' .. a:enr .. ':', v:errmsg)
+      call assert_match(a:emsg, v:errmsg)
+    endfunc
+
+    func CONT(n)
+      let g:taken = g:taken . "C" . a:n
+    endfunc
+
+    let v:errmsg = ""
+    try
+      let t = 1
+      while t <= 14
+        let g:taken = g:taken . "T" . t
+        let v:errmsg = ""
+        try
+          if t == 1
+            let v{novar + CONT(t)} = 0
+          elseif t == 2
+            let v{novar + CONT(t)}
+          elseif t == 3
+            let var = exists('v{novar + CONT(t)}')
+          elseif t == 4
+            unlet v{novar + CONT(t)}
+          elseif t == 5
+            function F{novar + CONT(t)}()
+            endfunction
+          elseif t == 6
+            function F{novar + CONT(t)}
+          elseif t == 7
+            let var = exists('*F{novar + CONT(t)}')
+          elseif t == 8
+            delfunction F{novar + CONT(t)}
+          elseif t == 9
+            echo novar + CONT(t)
+          elseif t == 10
+            echo v{novar + CONT(t)}
+          elseif t == 11
+            echo F{novar + CONT(t)}
+          elseif t == 12
+            let var = novar + CONT(t)
+          elseif t == 13
+            let var = v{novar + CONT(t)}
+          elseif t == 14
+            let var = F{novar + CONT(t)}()
+          endif
+        catch /^Vim\((\a\+)\)\=:/
+          Xloop 'a'
+          " v:errmsg is not set when the error message is converted to an
+          " exception.  Set it to the original error message.
+          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+        finally
+          Xloop 'b'
+          if t <= 8 && t != 3 && t != 7
+            call MSG(t, 'E475', 'Invalid argument\>')
+          else
+            call MSG(t, 'E121', "Undefined variable")
+          endif
+          let t = t + 1
+          XloopNEXT
+          continue	" discard an aborting error
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+
+    func T(n, expr, enr, emsg)
+      try
+        let g:taken = g:taken . "T" . a:n
+        let v:errmsg = ""
+        try
+          execute "let var = " . a:expr
+        catch /^Vim\((\a\+)\)\=:/
+          Xloop 'c'
+          " v:errmsg is not set when the error message is converted to an
+          " exception.  Set it to the original error message.
+          let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+        finally
+          Xloop 'd'
+          call MSG(a:n, a:enr, a:emsg)
+          XloopNEXT
+          " Discard an aborting error:
+          return
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      endtry
+    endfunc
+
+    call T(15, 'Nofunc() + CONT(15)',	'E117',	"Unknown function")
+    call T(16, 'F(1 2 + CONT(16))',	'E116',	"Invalid arguments")
+    call T(17, 'F(1, 2) + CONT(17)',	'E118',	"Too many arguments")
+    call T(18, 'F() + CONT(18)',	'E119',	"Not enough arguments")
+    call T(19, '{(1} + CONT(19)',	'E110',	"Missing ')'")
+    call T(20, '("abc"[1) + CONT(20)',	'E111',	"Missing ']'")
+    call T(21, '(1 +) + CONT(21)',	'E15',	"Invalid expression")
+    call T(22, '1 2 + CONT(22)',	'E488',	"Trailing characters: 2 +")
+    call T(23, '(1 ? 2) + CONT(23)',	'E109',	"Missing ':' after '?'")
+    call T(24, '("abc) + CONT(24)',	'E114',	"Missing double quote")
+    call T(25, "('abc) + CONT(25)",	'E115',	"Missing single quote")
+    call T(26, '& + CONT(26)',		'E112', "Option name missing")
+    call T(27, '&asdf + CONT(27)',	'E113', "Unknown option")
+
+    let expected = ""
+      \ .. "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
+      \ .. "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
+      \ .. "T26M26T27M27"
+
+    call assert_equal(expected, taken)
+  [CODE]
+  let verify =<< trim [CODE]
+    let expected = "a1b1a2b2a3b3a4b4a5b5a6b6a7b7a8b8a9b9a10b10a11b11a12b12"
+                  \ .. "a13b13a14b14c15d15c16d16c17d17c18d18c19d19c20d20"
+                  \ .. "c21d21c22d22c23d23c24d24c25d25c26d26c27d27"
+    call assert_equal(expected, g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 79:  Throwing one of several errors for the same command		    {{{1
+"
+"	    When several errors appear in a row (for instance during expression
+"	    evaluation), the first as the most specific one is used when
+"	    throwing an error exception.  If, however, a syntax error is
+"	    detected afterwards, this one is used for the error exception.
+"	    On a syntax error, the next command is not executed, on a normal
+"	    error, however, it is (relevant only in a function without the
+"	    "abort" flag).  v:errmsg is not set.
+"
+"	    If throwing error exceptions is configured off, v:errmsg is always
+"	    set to the latest error message, that is, to the more general
+"	    message or the syntax error, respectively.
+"-------------------------------------------------------------------------------
+func Test_throw_multi_error()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    func NEXT(cmd)
+      exec a:cmd . " | Xloop 'a'"
+    endfun
+
+    call NEXT('echo novar')			" (checks nextcmd)
+    XloopNEXT
+    call NEXT('let novar #')			" (skips nextcmd)
+    XloopNEXT
+    call NEXT('unlet novar #')			" (skips nextcmd)
+    XloopNEXT
+    call NEXT('let {novar}')			" (skips nextcmd)
+    XloopNEXT
+    call NEXT('unlet{ novar}')			" (skips nextcmd)
+
+    call assert_equal('a1', g:Xpath)
+    XpathINIT
+    XloopINIT
+
+    func EXEC(cmd)
+      exec a:cmd
+    endfunc
+
+    try
+      while 1				" dummy loop
+        try
+          let v:errmsg = ""
+          call EXEC('echo novar')	" normal error
+        catch /^Vim\((\a\+)\)\=:/
+          Xpath 'b'
+          call assert_match('E121: Undefined variable: novar', v:exception)
+        finally
+          Xpath 'c'
+          call assert_equal("", v:errmsg)
+          break
+        endtry
+      endwhile
+
+      Xpath 'd'
+      let cmd = "let"
+      while cmd != ""
+        try
+          let v:errmsg = ""
+          call EXEC(cmd . ' novar #')		" normal plus syntax error
+        catch /^Vim\((\a\+)\)\=:/
+          Xloop 'e'
+          if cmd =~ 'unlet'
+            " TODO: should get error for 'novar'
+            call assert_match('E488: Trailing characters', v:exception)
+          else
+            call assert_match('E121: Undefined variable: novar', v:exception)
+          endif
+        finally
+          Xloop 'f'
+          call assert_equal("", v:errmsg)
+          if cmd == "let"
+            let cmd = "unlet"
+          else
+            let cmd = ""
+          endif
+          XloopNEXT
+          continue
+        endtry
+      endwhile
+
+      Xpath 'g'
+      let cmd = "let"
+      while cmd != ""
+        try
+          let v:errmsg = ""
+          call EXEC(cmd . ' {novar}')		" normal plus syntax error
+        catch /^Vim\((\a\+)\)\=:/
+          Xloop 'h'
+          call assert_match('E475: Invalid argument: {novar}', v:exception)
+        finally
+          Xloop 'i'
+          call assert_equal("", v:errmsg)
+          if cmd == "let"
+            let cmd = "unlet"
+          else
+            let cmd = ""
+          endif
+          XloopNEXT
+          continue
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+    Xpath 'j'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('bcde1f1e2f2gh3i3h4i4j', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 80:  Syntax error in expression for illegal :elseif		    {{{1
+"
+"	    If there is a syntax error in the expression after an illegal
+"	    :elseif, an error message is given (or an error exception thrown)
+"	    for the illegal :elseif rather than the expression error.
+"-------------------------------------------------------------------------------
+func Test_if_syntax_error()
+  CheckEnglish
+
+  let test =<< trim [CODE]
+    let v:errmsg = ""
+    if 0
+    else
+    elseif 1 ||| 2
+    endif
+    Xpath 'a'
+    call assert_match('E584: :elseif after :else', v:errmsg)
+
+    let v:errmsg = ""
+    if 1
+    else
+    elseif 1 ||| 2
+    endif
+    Xpath 'b'
+    call assert_match('E584: :elseif after :else', v:errmsg)
+
+    let v:errmsg = ""
+    elseif 1 ||| 2
+    Xpath 'c'
+    call assert_match('E582: :elseif without :if', v:errmsg)
+
+    let v:errmsg = ""
+    while 1
+      elseif 1 ||| 2
+    endwhile
+    Xpath 'd'
+    call assert_match('E582: :elseif without :if', v:errmsg)
+
+    while 1
+      try
+        try
+          let v:errmsg = ""
+          if 0
+          else
+          elseif 1 ||| 2
+          endif
+        catch /^Vim\((\a\+)\)\=:/
+          Xpath 'e'
+          call assert_match('E584: :elseif after :else', v:exception)
+        finally
+          Xpath 'f'
+          call assert_equal("", v:errmsg)
+        endtry
+      catch /.*/
+      call assert_report('should not get here')
+      finally
+        Xpath 'g'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          let v:errmsg = ""
+          if 1
+          else
+          elseif 1 ||| 2
+          endif
+        catch /^Vim\((\a\+)\)\=:/
+          Xpath 'h'
+          call assert_match('E584: :elseif after :else', v:exception)
+        finally
+          Xpath 'i'
+          call assert_equal("", v:errmsg)
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'j'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          let v:errmsg = ""
+          elseif 1 ||| 2
+        catch /^Vim\((\a\+)\)\=:/
+          Xpath 'k'
+          call assert_match('E582: :elseif without :if', v:exception)
+        finally
+          Xpath 'l'
+          call assert_equal("", v:errmsg)
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'm'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          let v:errmsg = ""
+          while 1
+              elseif 1 ||| 2
+          endwhile
+        catch /^Vim\((\a\+)\)\=:/
+          Xpath 'n'
+          call assert_match('E582: :elseif without :if', v:exception)
+        finally
+          Xpath 'o'
+          call assert_equal("", v:errmsg)
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'p'
+        break
+      endtry
+    endwhile
+    Xpath 'q'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghijklmnopq', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 81:  Discarding exceptions after an error or interrupt		    {{{1
+"
+"	    When an exception is thrown from inside a :try conditional without
+"	    :catch and :finally clauses and an error or interrupt occurs before
+"	    the :endtry is reached, the exception is discarded.
+"-------------------------------------------------------------------------------
+
+func Test_discard_exception_after_error_1()
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      try
+        Xpath 'b'
+        throw "arrgh"
+        call assert_report('should not get here')
+        if 1
+        call assert_report('should not get here')
+        " error after :throw: missing :endif
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('ab', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+" interrupt the code before the endtry is invoked
+func Test_discard_exception_after_error_2()
+  XpathINIT
+  let lines =<< trim [CODE]
+    try
+      Xpath 'a'
+      try
+        Xpath 'b'
+        throw "arrgh"
+        call assert_report('should not get here')
+      endtry                      " interrupt here
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  call writefile(lines, 'Xscript', 'D')
+
+  breakadd file 7 Xscript
+  try
+    let caught_intr = 0
+    debuggreedy
+    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
+  catch /^Vim:Interrupt$/
+    call assert_match('Xscript, line 7', v:throwpoint)
+    let caught_intr = 1
+  endtry
+  0debuggreedy
+  call assert_equal(1, caught_intr)
+  call assert_equal('ab', g:Xpath)
+  breakdel *
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 82:  Ignoring :catch clauses after an error or interrupt		    {{{1
+"
+"	    When an exception is thrown and an error or interrupt occurs before
+"	    the matching :catch clause is reached, the exception is discarded
+"	    and the :catch clause is ignored (also for the error or interrupt
+"	    exception being thrown then).
+"-------------------------------------------------------------------------------
+
+func Test_ignore_catch_after_error_1()
+  let test =<< trim [CODE]
+    try
+      try
+        Xpath 'a'
+        throw "arrgh"
+        call assert_report('should not get here')
+        if 1
+        call assert_report('should not get here')
+        " error after :throw: missing :endif
+      catch /.*/
+        call assert_report('should not get here')
+      catch /.*/
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+func Test_ignore_catch_after_error_2()
+  let test =<< trim [CODE]
+    func E()
+      try
+        try
+          Xpath 'a'
+          throw "arrgh"
+          call assert_report('should not get here')
+          if 1
+          call assert_report('should not get here')
+          " error after :throw: missing :endif
+        catch /.*/
+          call assert_report('should not get here')
+        catch /.*/
+          call assert_report('should not get here')
+        endtry
+        call assert_report('should not get here')
+      catch /arrgh/
+        call assert_report('should not get here')
+      endtry
+    endfunc
+
+    call E()
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('a', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+" interrupt right before a catch is invoked in a script
+func Test_ignore_catch_after_intr_1()
+  " for unknown reasons this test sometimes fails on MS-Windows.
+  let g:test_is_flaky = 1
+
+  XpathINIT
+  let lines =<< trim [CODE]
+    try
+      try
+        Xpath 'a'
+        throw "arrgh"
+        call assert_report('should not get here')
+      catch /.*/              " interrupt here
+        call assert_report('should not get here')
+      catch /.*/
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  call writefile(lines, 'Xscript', 'D')
+
+  breakadd file 6 Xscript
+  try
+    let caught_intr = 0
+    debuggreedy
+    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
+  catch /^Vim:Interrupt$/
+    call assert_match('Xscript, line 6', v:throwpoint)
+    let caught_intr = 1
+  endtry
+  0debuggreedy
+  call assert_equal(1, caught_intr)
+  call assert_equal('a', g:Xpath)
+  breakdel *
+endfunc
+
+" interrupt right before a catch is invoked inside a function.
+func Test_ignore_catch_after_intr_2()
+  " for unknown reasons this test sometimes fails on MS-Windows.
+  let g:test_is_flaky = 1
+
+  XpathINIT
+  func F()
+    try
+      try
+        Xpath 'a'
+        throw "arrgh"
+        call assert_report('should not get here')
+      catch /.*/              " interrupt here
+        call assert_report('should not get here')
+      catch /.*/
+        call assert_report('should not get here')
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  endfunc
+
+  breakadd func 6 F
+  try
+    let caught_intr = 0
+    debuggreedy
+    call feedkeys(":call F()\<CR>quit\<CR>", "xt")
+  catch /^Vim:Interrupt$/
+    call assert_match('\.F, line 6', v:throwpoint)
+    let caught_intr = 1
+  endtry
+  0debuggreedy
+  call assert_equal(1, caught_intr)
+  call assert_equal('a', g:Xpath)
+  breakdel *
+  delfunc F
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 83:  Executing :finally clauses after an error or interrupt	    {{{1
+"
+"	    When an exception is thrown and an error or interrupt occurs before
+"	    the :finally of the innermost :try is reached, the exception is
+"	    discarded and the :finally clause is executed.
+"-------------------------------------------------------------------------------
+
+func Test_finally_after_error()
+  let test =<< trim [CODE]
+    try
+      Xpath 'a'
+      try
+        Xpath 'b'
+        throw "arrgh"
+        call assert_report('should not get here')
+        if 1
+        call assert_report('should not get here')
+        " error after :throw: missing :endif
+      finally
+        Xpath 'c'
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abc', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+" interrupt the code right before the finally is invoked
+func Test_finally_after_intr()
+  XpathINIT
+  let lines =<< trim [CODE]
+    try
+      Xpath 'a'
+      try
+        Xpath 'b'
+        throw "arrgh"
+        call assert_report('should not get here')
+      finally		" interrupt here
+        Xpath 'c'
+      endtry
+      call assert_report('should not get here')
+    catch /arrgh/
+      call assert_report('should not get here')
+    endtry
+    call assert_report('should not get here')
+  [CODE]
+  call writefile(lines, 'Xscript', 'D')
+
+  breakadd file 7 Xscript
+  try
+    let caught_intr = 0
+    debuggreedy
+    call feedkeys(":source Xscript\<CR>quit\<CR>", "xt")
+  catch /^Vim:Interrupt$/
+    call assert_match('Xscript, line 7', v:throwpoint)
+    let caught_intr = 1
+  endtry
+  0debuggreedy
+  call assert_equal(1, caught_intr)
+  call assert_equal('abc', g:Xpath)
+  breakdel *
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 84:  Exceptions in autocommand sequences.			    {{{1
+"
+"	    When an exception occurs in a sequence of autocommands for
+"	    a specific event, the rest of the sequence is not executed.  The
+"	    command that triggered the autocommand execution aborts, and the
+"	    exception is propagated to the caller.
+"
+"	    For the FuncUndefined event under a function call expression or
+"	    :call command, the function is not executed, even when it has
+"	    been defined by the autocommands before the exception occurred.
+"-------------------------------------------------------------------------------
+
+func Test_autocmd_exception()
+  let test =<< trim [CODE]
+    func INT()
+      call interrupt()
+    endfunc
+
+    aug TMP
+      autocmd!
+
+      autocmd User x1 Xpath 'a'
+      autocmd User x1 throw "x1"
+      autocmd User x1 call assert_report('should not get here')
+
+      autocmd User x2 Xpath 'b'
+      autocmd User x2 asdf
+      autocmd User x2 call assert_report('should not get here')
+
+      autocmd User x3 Xpath 'c'
+      autocmd User x3 call INT()
+      autocmd User x3 call assert_report('should not get here')
+
+      autocmd FuncUndefined U1 func U1()
+      autocmd FuncUndefined U1   call assert_report('should not get here')
+      autocmd FuncUndefined U1 endfunc
+      autocmd FuncUndefined U1 Xpath 'd'
+      autocmd FuncUndefined U1 throw "U1"
+      autocmd FuncUndefined U1 call assert_report('should not get here')
+
+      autocmd FuncUndefined U2 func U2()
+      autocmd FuncUndefined U2   call assert_report('should not get here')
+      autocmd FuncUndefined U2 endfunc
+      autocmd FuncUndefined U2 Xpath 'e'
+      autocmd FuncUndefined U2 ASDF
+      autocmd FuncUndefined U2 call assert_report('should not get here')
+
+      autocmd FuncUndefined U3 func U3()
+      autocmd FuncUndefined U3   call assert_report('should not get here')
+      autocmd FuncUndefined U3 endfunc
+      autocmd FuncUndefined U3 Xpath 'f'
+      autocmd FuncUndefined U3 call INT()
+      autocmd FuncUndefined U3 call assert_report('should not get here')
+    aug END
+
+    try
+      try
+        Xpath 'g'
+        doautocmd User x1
+      catch /x1/
+        Xpath 'h'
+      endtry
+
+      while 1
+        try
+          Xpath 'i'
+          doautocmd User x2
+        catch /asdf/
+          Xpath 'j'
+        finally
+          Xpath 'k'
+          break
+        endtry
+      endwhile
+
+      while 1
+        try
+          Xpath 'l'
+          doautocmd User x3
+        catch /Vim:Interrupt/
+          Xpath 'm'
+        finally
+          Xpath 'n'
+          " ... but break loop for caught interrupt exception,
+          " or discard interrupt and break loop if $VIMNOINTTHROW
+          break
+        endtry
+      endwhile
+
+      if exists("*U1") | delfunction U1 | endif
+      if exists("*U2") | delfunction U2 | endif
+      if exists("*U3") | delfunction U3 | endif
+
+      try
+        Xpath 'o'
+        call U1()
+      catch /U1/
+        Xpath 'p'
+      endtry
+
+      while 1
+        try
+          Xpath 'q'
+          call U2()
+        catch /ASDF/
+          Xpath 'r'
+        finally
+          Xpath 's'
+          " ... but break loop for caught error exception,
+          " or discard error and break loop if $VIMNOERRTHROW
+          break
+        endtry
+      endwhile
+
+      while 1
+        try
+          Xpath 't'
+          call U3()
+        catch /Vim:Interrupt/
+          Xpath 'u'
+        finally
+          Xpath 'v'
+          " ... but break loop for caught interrupt exception,
+          " or discard interrupt and break loop if $VIMNOINTTHROW
+          break
+        endtry
+      endwhile
+    catch /.*/
+      call assert_report('should not get here')
+    endtry
+    Xpath 'w'
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('gahibjklcmnodpqerstfuvw', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 85:  Error exceptions in autocommands for I/O command events	    {{{1
+"
+"	    When an I/O command is inside :try/:endtry, autocommands to be
+"	    executed after it should be skipped on an error (exception) in the
+"	    command itself or in autocommands to be executed before the command.
+"	    In the latter case, the I/O command should not be executed either.
+"	    Example 1: BufWritePre, :write, BufWritePost
+"	    Example 2: FileReadPre, :read, FileReadPost.
+"-------------------------------------------------------------------------------
+
+func Test_autocmd_error_io_exception()
+  let test =<< trim [CODE]
+    " Remove the autocommands for the events specified as arguments in all used
+    " autogroups.
+    func Delete_autocommands(...)
+      let augfile = tempname()
+      while 1
+        try
+          exec "redir >" . augfile
+          aug
+          redir END
+          exec "edit" augfile
+          g/^$/d
+          norm G$
+          let wrap = "w"
+          while search('\%(  \|^\)\@<=.\{-}\%(  \)\@=', wrap) > 0
+            let wrap = "W"
+            exec "norm y/  \n"
+            let argno = 1
+            while argno <= a:0
+              exec "au!" escape(@", " ") a:{argno}
+              let argno = argno + 1
+            endwhile
+          endwhile
+        catch /.*/
+        finally
+          bwipeout!
+          call delete(augfile)
+          break
+        endtry
+      endwhile
+    endfunc
+
+    call Delete_autocommands("BufWritePre", "BufWritePost")
+
+    while 1
+      try
+        try
+          let post = 0
+          aug TMP
+            au! BufWritePost * let post = 1
+          aug END
+          write /n/o/n/e/x/i/s/t/e/n/t
+        catch /^Vim(write):/
+          Xpath 'a'
+          call assert_match("E212: Can't open file for writing", v:exception)
+        finally
+          Xpath 'b'
+          call assert_equal(0, post)
+          au! TMP
+          aug! TMP
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'c'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        try
+          let post = 0
+          aug TMP
+            au! BufWritePre  * asdf
+            au! BufWritePost * let post = 1
+          aug END
+          let tmpfile = tempname()
+          exec "write" tmpfile
+        catch /^Vim\((write)\)\=:/
+          Xpath 'd'
+          call assert_match('E492: Not an editor command', v:exception)
+        finally
+          Xpath 'e'
+          if filereadable(tmpfile)
+            call assert_report('should not get here')
+          endif
+          call assert_equal(0, post)
+          au! TMP
+          aug! TMP
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'f'
+        break
+      endtry
+    endwhile
+
+    call delete(tmpfile)
+
+    call Delete_autocommands("BufWritePre", "BufWritePost",
+          \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
+
+    while 1
+      try
+        try
+          let post = 0
+          aug TMP
+            au! FileReadPost * let post = 1
+          aug END
+          let caught = 0
+          read /n/o/n/e/x/i/s/t/e/n/t
+        catch /^Vim(read):/
+          Xpath 'g'
+          call assert_match("E484: Can't open file", v:exception)
+        finally
+          Xpath 'h'
+          call assert_equal(0, post)
+          au! TMP
+          aug! TMP
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'i'
+        break
+      endtry
+    endwhile
+
+    while 1
+      try
+        let infile = tempname()
+        let tmpfile = tempname()
+        call writefile(["XYZ"], infile)
+        exec "edit" tmpfile
+        try
+          Xpath 'j'
+          try
+            let post = 0
+            aug TMP
+              au! FileReadPre  * asdf
+              au! FileReadPost * let post = 1
+            aug END
+            exec "0read" infile
+          catch /^Vim\((read)\)\=:/
+            Xpath 'k'
+            call assert_match('E492: Not an editor command', v:exception)
+          finally
+            Xpath 'l'
+            if getline("1") == "XYZ"
+              call assert_report('should not get here')
+            endif
+            call assert_equal(0, post)
+            au! TMP
+            aug! TMP
+          endtry
+        finally
+          Xpath 'm'
+          bwipeout!
+        endtry
+      catch /.*/
+        call assert_report('should not get here')
+      finally
+        Xpath 'n'
+        break
+      endtry
+    endwhile
+
+    call delete(infile)
+    call delete(tmpfile)
+  [CODE]
+  let verify =<< trim [CODE]
+    call assert_equal('abcdefghijklmn', g:Xpath)
+  [CODE]
+  call RunInNewVim(test, verify)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 87   using (expr) ? funcref : funcref				    {{{1
+"
+"	    Vim needs to correctly parse the funcref and even when it does
+"	    not execute the funcref, it needs to consume the trailing ()
+"-------------------------------------------------------------------------------
+
+func Add2(x1, x2)
+  return a:x1 + a:x2
+endfu
+
+func GetStr()
+  return "abcdefghijklmnopqrstuvwxyp"
+endfu
+
+func Test_funcref_with_condexpr()
+  call assert_equal(5, function('Add2')(2,3))
+
+  call assert_equal(3, 1 ? function('Add2')(1,2) : function('Add2')(2,3))
+  call assert_equal(5, 0 ? function('Add2')(1,2) : function('Add2')(2,3))
+  " Make sure, GetStr() still works.
+  call assert_equal('abcdefghijk', GetStr()[0:10])
+endfunc
+
+" Test 90:  Recognizing {} in variable name.			    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_curlies()
+    let s:var = 66
+    let ns = 's'
+    call assert_equal(66, {ns}:var)
+
+    let g:a = {}
+    let g:b = 't'
+    let g:a[g:b] = 77
+    call assert_equal(77, g:a['t'])
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 91:  using type().					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_type()
+    call assert_equal(0, type(0))
+    call assert_equal(1, type(""))
+    call assert_equal(2, type(function("tr")))
+    call assert_equal(2, type(function("tr", [8])))
+    call assert_equal(3, type([]))
+    call assert_equal(4, type({}))
+    call assert_equal(5, type(0.0))
+    call assert_equal(6, type(v:false))
+    call assert_equal(6, type(v:true))
+    call assert_equal(7, type(v:none))
+    call assert_equal(7, type(v:null))
+    call assert_equal(8, v:t_job)
+    call assert_equal(9, v:t_channel)
+    call assert_equal(v:t_number, type(0))
+    call assert_equal(v:t_string, type(""))
+    call assert_equal(v:t_func, type(function("tr")))
+    call assert_equal(v:t_func, type(function("tr", [8])))
+    call assert_equal(v:t_list, type([]))
+    call assert_equal(v:t_dict, type({}))
+    call assert_equal(v:t_float, type(0.0))
+    call assert_equal(v:t_bool, type(v:false))
+    call assert_equal(v:t_bool, type(v:true))
+    call assert_equal(v:t_none, type(v:none))
+    call assert_equal(v:t_none, type(v:null))
+    call assert_equal(v:t_string, type(test_null_string()))
+    call assert_equal(v:t_func, type(test_null_function()))
+    call assert_equal(v:t_func, type(test_null_partial()))
+    call assert_equal(v:t_list, type(test_null_list()))
+    call assert_equal(v:t_dict, type(test_null_dict()))
+    if has('job')
+      call assert_equal(v:t_job, type(test_null_job()))
+    endif
+    if has('channel')
+      call assert_equal(v:t_channel, type(test_null_channel()))
+    endif
+    call assert_equal(v:t_blob, type(test_null_blob()))
+
+    call assert_fails("call type(test_void())", ['E340:', 'E685:'])
+    call assert_fails("call type(test_unknown())", ['E340:', 'E685:'])
+
+    call assert_equal(0, 0 + v:false)
+    call assert_equal(1, 0 + v:true)
+    call assert_equal(0, 0 + v:none)
+    call assert_equal(0, 0 + v:null)
+
+    call assert_equal('v:false', '' . v:false)
+    call assert_equal('v:true', '' . v:true)
+    call assert_equal('v:none', '' . v:none)
+    call assert_equal('v:null', '' . v:null)
+
+    call assert_true(v:false == 0)
+    call assert_false(v:false != 0)
+    call assert_true(v:true == 1)
+    call assert_false(v:true != 1)
+    call assert_false(v:true == v:false)
+    call assert_true(v:true != v:false)
+
+    call assert_true(v:null == 0)
+    call assert_false(v:null == 1)
+    call assert_false(v:null != 0)
+    call assert_true(v:none == 0)
+    call assert_false(v:none == 1)
+    call assert_false(v:none != 0)
+    call assert_true(v:null == 0.0)
+    call assert_false(v:null == 0.1)
+    call assert_false(v:null != 0.0)
+
+    call assert_true(v:false is v:false)
+    call assert_true(v:true is v:true)
+    call assert_true(v:none is v:none)
+    call assert_true(v:null is v:null)
+
+    call assert_false(v:false isnot v:false)
+    call assert_false(v:true isnot v:true)
+    call assert_false(v:none isnot v:none)
+    call assert_false(v:null isnot v:null)
+
+    call assert_false(v:false is 0)
+    call assert_false(v:true is 1)
+    call assert_false(v:true is v:false)
+    call assert_false(v:none is 0)
+    call assert_false(v:none is [])
+    call assert_false(v:none is {})
+    call assert_false(v:none is 'text')
+    call assert_false(v:null is 0)
+    call assert_false(v:null is v:none)
+
+    call assert_true(v:false isnot 0)
+    call assert_true(v:true isnot 1)
+    call assert_true(v:true isnot v:false)
+    call assert_true(v:none isnot 0)
+    call assert_true(v:null isnot 0)
+    call assert_true(v:null isnot v:none)
+
+    call assert_equal(v:false, eval(string(v:false)))
+    call assert_equal(v:true, eval(string(v:true)))
+    call assert_equal(v:none, eval(string(v:none)))
+    call assert_equal(v:null, eval(string(v:null)))
+
+    call assert_equal(v:false, copy(v:false))
+    call assert_equal(v:true, copy(v:true))
+    call assert_equal(v:none, copy(v:none))
+    call assert_equal(v:null, copy(v:null))
+
+    call assert_equal([v:false], deepcopy([v:false]))
+    call assert_equal([v:true], deepcopy([v:true]))
+    call assert_equal([v:none], deepcopy([v:none]))
+    call assert_equal([v:null], deepcopy([v:null]))
+
+    call assert_true(empty(v:false))
+    call assert_false(empty(v:true))
+    call assert_true(empty(v:null))
+    call assert_true(empty(v:none))
+
+    func ChangeYourMind()
+	try
+	    return v:true
+	finally
+	    return 'something else'
+	endtry
+    endfunc
+
+    call ChangeYourMind()
+endfunc
+
+func Test_typename()
+  call assert_equal('number', typename(123))
+  call assert_equal('string', typename('x'))
+  call assert_equal('list<number>', typename([123]))
+  call assert_equal('dict<number>', typename(#{key: 123}))
+  call assert_equal('list<dict<number>>', typename([#{key: 123}]))
+
+  let l = []
+  let d = #{a: 0}
+  let l = [d]
+  let l[0].e = #{b: l}
+  call assert_equal('list<dict<any>>', typename(l))
+  call assert_equal('dict<any>', typename(d))
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 92:  skipping code					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_skip()
+    let Fn = function('Test_type')
+    call assert_false(0 && Fn[1])
+    call assert_false(0 && string(Fn))
+    call assert_false(0 && len(Fn))
+    let l = []
+    call assert_false(0 && l[1])
+    call assert_false(0 && string(l))
+    call assert_false(0 && len(l))
+    let f = 1.0
+    call assert_false(0 && f[1])
+    call assert_false(0 && string(f))
+    call assert_false(0 && len(f))
+    let sp = v:null
+    call assert_false(0 && sp[1])
+    call assert_false(0 && string(sp))
+    call assert_false(0 && len(sp))
+
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 93:  :echo and string()					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_echo_and_string()
+    " String
+    let a = 'foo bar'
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["foo bar",
+		     \ "'foo bar'"], l)
+
+    " Float
+    let a = -1.2e0
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["-1.2",
+                     \ "-1.2"], l)
+
+    " Funcref
+    redir => result
+    echo function('string')
+    echo string(function('string'))
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["string",
+		     \ "function('string')"], l)
+
+    " Recursive dictionary
+    let a = {}
+    let a["a"] = a
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {...}}",
+		     \ "{'a': {...}}"], l)
+
+    " Recursive list
+    let a = [0]
+    let a[0] = a
+    redir => result
+    echo a
+    echo string(a)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[...]]",
+		     \ "[[...]]"], l)
+
+    " Empty dictionaries in a list
+    let a = {}
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[{}, {}, {}]",
+		     \ "[{}, {}, {}]"], l)
+
+    " Empty dictionaries in a dictionary
+    let a = {}
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {}, 'b': {}}",
+		     \ "{'a': {}, 'b': {}}"], l)
+
+    " Empty lists in a list
+    let a = []
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[], [], []]",
+		     \ "[[], [], []]"], l)
+
+    " Empty lists in a dictionary
+    let a = []
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': [], 'b': []}",
+		     \ "{'a': [], 'b': []}"], l)
+
+    " Dictionaries in a list
+    let a = {"one": "yes", "two": "yes", "three": "yes"}
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {...}, {...}]",
+		     \ "[{'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}, {'one': 'yes', 'two': 'yes', 'three': 'yes'}]"], l)
+
+    " Dictionaries in a dictionary
+    let a = {"one": "yes", "two": "yes", "three": "yes"}
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {...}}",
+		     \ "{'a': {'one': 'yes', 'two': 'yes', 'three': 'yes'}, 'b': {'one': 'yes', 'two': 'yes', 'three': 'yes'}}"], l)
+
+    " Lists in a list
+    let a = [1, 2, 3]
+    redir => result
+    echo [a, a, a]
+    echo string([a, a, a])
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["[[1, 2, 3], [...], [...]]",
+		     \ "[[1, 2, 3], [1, 2, 3], [1, 2, 3]]"], l)
+
+    " Lists in a dictionary
+    let a = [1, 2, 3]
+    let b = {"a": a, "b": a}
+    redir => result
+    echo b
+    echo string(b)
+    redir END
+    let l = split(result, "\n")
+    call assert_equal(["{'a': [1, 2, 3], 'b': [...]}",
+		     \ "{'a': [1, 2, 3], 'b': [1, 2, 3]}"], l)
+
+    call assert_fails('echo &:', 'E112:')
+    call assert_fails('echo &g:', 'E112:')
+    call assert_fails('echo &l:', 'E112:')
+
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 94:  64-bit Numbers					    {{{1
+"-------------------------------------------------------------------------------
+
+func Test_num64()
+    call assert_notequal( 4294967296, 0)
+    call assert_notequal(-4294967296, 0)
+    call assert_equal( 4294967296,  0xFFFFffff + 1)
+    call assert_equal(-4294967296, -0xFFFFffff - 1)
+
+    call assert_equal( 9223372036854775807,  1 / 0)
+    call assert_equal(-9223372036854775807, -1 / 0)
+    call assert_equal(-9223372036854775807 - 1,  0 / 0)
+
+    call assert_equal( 0x7FFFffffFFFFffff, float2nr( 1.0e150))
+    call assert_equal(-0x7FFFffffFFFFffff, float2nr(-1.0e150))
+
+    let rng = range(0xFFFFffff, 0x100000001)
+    call assert_equal([0xFFFFffff, 0x100000000, 0x100000001], rng)
+    call assert_equal(0x100000001, max(rng))
+    call assert_equal(0xFFFFffff, min(rng))
+    call assert_equal(rng, sort(range(0x100000001, 0xFFFFffff, -1), 'N'))
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 95:  lines of :append, :change, :insert			    {{{1
+"-------------------------------------------------------------------------------
+
+func DefineFunction(name, body)
+    let func = join(['function! ' . a:name . '()'] + a:body + ['endfunction'], "\n")
+    exec func
+endfunc
+
+func Test_script_lines()
+    " :append
+    try
+	call DefineFunction('T_Append', [
+		    \ 'append',
+		    \ 'py <<EOS',
+		    \ '.',
+		    \ ])
+    catch
+	call assert_report("Can't define function")
+    endtry
+    try
+	call DefineFunction('T_Append', [
+		    \ 'append',
+		    \ 'abc',
+		    \ ])
+	call assert_report("Shouldn't be able to define function")
+    catch
+	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
+    endtry
+
+    " :change
+    try
+	call DefineFunction('T_Change', [
+		    \ 'change',
+		    \ 'py <<EOS',
+		    \ '.',
+		    \ ])
+    catch
+	call assert_report("Can't define function")
+    endtry
+    try
+	call DefineFunction('T_Change', [
+		    \ 'change',
+		    \ 'abc',
+		    \ ])
+	call assert_report("Shouldn't be able to define function")
+    catch
+	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
+    endtry
+
+    " :insert
+    try
+	call DefineFunction('T_Insert', [
+		    \ 'insert',
+		    \ 'py <<EOS',
+		    \ '.',
+		    \ ])
+    catch
+	call assert_report("Can't define function")
+    endtry
+    try
+	call DefineFunction('T_Insert', [
+		    \ 'insert',
+		    \ 'abc',
+		    \ ])
+	call assert_report("Shouldn't be able to define function")
+    catch
+	call assert_exception('Vim(function):E1145: Missing heredoc end marker: .')
+    endtry
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 96:  line continuation						    {{{1
+"
+"	    Undefined behavior was detected by ubsan with line continuation
+"	    after an empty line.
+"-------------------------------------------------------------------------------
+func Test_script_empty_line_continuation()
+
+    \
+endfunc
+
+"-------------------------------------------------------------------------------
+" Test 97:  bitwise functions						    {{{1
+"-------------------------------------------------------------------------------
+func Test_bitwise_functions()
+    " and
+    call assert_equal(127, and(127, 127))
+    call assert_equal(16, and(127, 16))
+    eval 127->and(16)->assert_equal(16)
+    call assert_equal(0, and(127, 128))
+    call assert_fails("call and([], 1)", 'E745:')
+    call assert_fails("call and({}, 1)", 'E728:')
+    call assert_fails("call and(1.0, 1)", 'E805:')
+    call assert_fails("call and(1, 1.0)", 'E805:')
+    call assert_fails("call and(1, [])", 'E745:')
+    call assert_fails("call and(1, {})", 'E728:')
+    " or
+    call assert_equal(23, or(16, 7))
+    call assert_equal(15, or(8, 7))
+    eval 8->or(7)->assert_equal(15)
+    call assert_equal(123, or(0, 123))
+    call assert_fails("call or([], 1)", 'E745:')
+    call assert_fails("call or({}, 1)", 'E728:')
+    call assert_fails("call or(1.0, 1)", 'E805:')
+    call assert_fails("call or(1, 1.0)", 'E805:')
+    call assert_fails("call or(1, [])", 'E745:')
+    call assert_fails("call or(1, {})", 'E728:')
+    " xor
+    call assert_equal(0, xor(127, 127))
+    call assert_equal(111, xor(127, 16))
+    eval 127->xor(16)->assert_equal(111)
+    call assert_equal(255, xor(127, 128))
+    call assert_fails("call xor(1.0, 1)", 'E805:')
+    call assert_fails("call xor(1, 1.0)", 'E805:')
+    call assert_fails("call xor([], 1)", 'E745:')
+    call assert_fails("call xor({}, 1)", 'E728:')
+    call assert_fails("call xor(1, [])", 'E745:')
+    call assert_fails("call xor(1, {})", 'E728:')
+    " invert
+    call assert_equal(65408, and(invert(127), 65535))
+    eval 127->invert()->and(65535)->assert_equal(65408)
+    call assert_equal(65519, and(invert(16), 65535))
+    call assert_equal(65407, and(invert(128), 65535))
+    call assert_fails("call invert(1.0)", 'E805:')
+    call assert_fails("call invert([])", 'E745:')
+    call assert_fails("call invert({})", 'E728:')
+endfunc
+
+" Test using bang after user command				    {{{1
+func Test_user_command_with_bang()
+    command -bang Nieuw let nieuw = 1
+    Ni!
+    call assert_equal(1, nieuw)
+    unlet nieuw
+    delcommand Nieuw
+endfunc
+
+func Test_script_expand_sfile()
+  let lines =<< trim END
+    func s:snr()
+      return expand('<sfile>')
+    endfunc
+    let g:result = s:snr()
+  END
+  call writefile(lines, 'Xexpand', 'D')
+  source Xexpand
+  call assert_match('<SNR>\d\+_snr', g:result)
+  source Xexpand
+  call assert_match('<SNR>\d\+_snr', g:result)
+
+  unlet g:result
+endfunc
+
+func Test_compound_assignment_operators()
+    " Test for number
+    let x = 1
+    let x += 10
+    call assert_equal(11, x)
+    let x -= 5
+    call assert_equal(6, x)
+    let x *= 4
+    call assert_equal(24, x)
+    let x /= 3
+    call assert_equal(8, x)
+    let x %= 3
+    call assert_equal(2, x)
+    let x .= 'n'
+    call assert_equal('2n', x)
+
+    " Test special cases: division or modulus with 0.
+    let x = 1
+    let x /= 0
+    call assert_equal(0x7FFFFFFFFFFFFFFF, x)
+
+    let x = -1
+    let x /= 0
+    call assert_equal(-0x7FFFFFFFFFFFFFFF, x)
+
+    let x = 0
+    let x /= 0
+    call assert_equal(-0x7FFFFFFFFFFFFFFF - 1, x)
+
+    let x = 1
+    let x %= 0
+    call assert_equal(0, x)
+
+    let x = -1
+    let x %= 0
+    call assert_equal(0, x)
+
+    let x = 0
+    let x %= 0
+    call assert_equal(0, x)
+
+    " Test for string
+    let x = 'str'
+    let x .= 'ing'
+    call assert_equal('string', x)
+    let x += 1
+    call assert_equal(1, x)
+
+    " Test for float
+    let x -= 1.5
+    call assert_equal(-0.5, x)
+    let x = 0.5
+    let x += 4.5
+    call assert_equal(5.0, x)
+    let x -= 1.5
+    call assert_equal(3.5, x)
+    let x *= 3.0
+    call assert_equal(10.5, x)
+    let x /= 2.5
+    call assert_equal(4.2, x)
+    call assert_fails('let x %= 0.5', 'E734:')
+    call assert_fails('let x .= "f"', 'E734:')
+    let x = !3.14
+    call assert_equal(0.0, x)
+
+    " integer and float operations
+    let x = 1
+    let x *= 2.1
+    call assert_equal(2.1, x)
+    let x = 1
+    let x /= 0.25
+    call assert_equal(4.0, x)
+    let x = 1
+    call assert_fails('let x %= 0.25', 'E734:')
+    let x = 1
+    call assert_fails('let x .= 0.25', 'E734:')
+    let x = 1.0
+    call assert_fails('let x += [1.1]', 'E734:')
+
+    " Test for environment variable
+    let $FOO = 1
+    call assert_fails('let $FOO += 1', 'E734:')
+    call assert_fails('let $FOO -= 1', 'E734:')
+    call assert_fails('let $FOO *= 1', 'E734:')
+    call assert_fails('let $FOO /= 1', 'E734:')
+    call assert_fails('let $FOO %= 1', 'E734:')
+    let $FOO .= 's'
+    call assert_equal('1s', $FOO)
+    unlet $FOO
+
+    " Test for option variable (type: number)
+    let &scrolljump = 1
+    let &scrolljump += 5
+    call assert_equal(6, &scrolljump)
+    let &scrolljump -= 2
+    call assert_equal(4, &scrolljump)
+    let &scrolljump *= 3
+    call assert_equal(12, &scrolljump)
+    let &scrolljump /= 2
+    call assert_equal(6, &scrolljump)
+    let &scrolljump %= 5
+    call assert_equal(1, &scrolljump)
+    call assert_fails('let &scrolljump .= "j"', ['E734:', 'E734:'])
+    set scrolljump&vim
+
+    let &foldlevelstart = 2
+    let &foldlevelstart -= 1
+    call assert_equal(1, &foldlevelstart)
+    let &foldlevelstart -= 1
+    call assert_equal(0, &foldlevelstart)
+    let &foldlevelstart = 2
+    let &foldlevelstart -= 2
+    call assert_equal(0, &foldlevelstart)
+
+    " Test for register
+    let @/ = 1
+    call assert_fails('let @/ += 1', 'E734:')
+    call assert_fails('let @/ -= 1', 'E734:')
+    call assert_fails('let @/ *= 1', 'E734:')
+    call assert_fails('let @/ /= 1', 'E734:')
+    call assert_fails('let @/ %= 1', 'E734:')
+    let @/ .= 's'
+    call assert_equal('1s', @/)
+    let @/ = ''
+endfunc
+
+func Test_unlet_env()
+  let $TESTVAR = 'yes'
+  call assert_equal('yes', $TESTVAR)
+  call assert_fails('lockvar $TESTVAR', 'E940:')
+  call assert_fails('unlockvar $TESTVAR', 'E940:')
+  call assert_equal('yes', $TESTVAR)
+  if 0
+    unlet $TESTVAR
+  endif
+  call assert_equal('yes', $TESTVAR)
+  unlet $TESTVAR
+  call assert_equal('', $TESTVAR)
+endfunc
+
+func Test_refcount()
+    " Immediate values
+    call assert_equal(-1, test_refcount(1))
+    call assert_equal(-1, test_refcount('s'))
+    call assert_equal(-1, test_refcount(v:true))
+    call assert_equal(0, test_refcount([]))
+    call assert_equal(0, test_refcount({}))
+    call assert_equal(0, test_refcount(0zff))
+    call assert_equal(0, test_refcount({-> line('.')}))
+    call assert_equal(-1, test_refcount(0.1))
+    if has('job')
+        call assert_equal(0, test_refcount(job_start([&shell, &shellcmdflag, 'echo .'])))
+    endif
+
+    " No refcount types
+    let x = 1
+    call assert_equal(-1, test_refcount(x))
+    let x = 's'
+    call assert_equal(-1, test_refcount(x))
+    let x = v:true
+    call assert_equal(-1, test_refcount(x))
+    let x = 0.1
+    call assert_equal(-1, test_refcount(x))
+
+    " Check refcount
+    let x = []
+    call assert_equal(1, test_refcount(x))
+
+    let x = {}
+    call assert_equal(1, x->test_refcount())
+
+    let x = 0zff
+    call assert_equal(1, test_refcount(x))
+
+    let X = {-> line('.')}
+    call assert_equal(1, test_refcount(X))
+    let Y = X
+    call assert_equal(2, test_refcount(X))
+
+    if has('job')
+        let job = job_start([&shell, &shellcmdflag, 'echo .'])
+        call assert_equal(1, test_refcount(job))
+        call assert_equal(1, test_refcount(job_getchannel(job)))
+        call assert_equal(1, test_refcount(job))
+    endif
+
+    " Function arguments, copying and unassigning
+    func ExprCheck(x, i)
+        let i = a:i + 1
+        call assert_equal(i, test_refcount(a:x))
+        let Y = a:x
+        call assert_equal(i + 1, test_refcount(a:x))
+        call assert_equal(test_refcount(a:x), test_refcount(Y))
+        let Y = 0
+        call assert_equal(i, test_refcount(a:x))
+    endfunc
+    call ExprCheck([], 0)
+    call ExprCheck({}, 0)
+    call ExprCheck(0zff, 0)
+    call ExprCheck({-> line('.')}, 0)
+    if has('job')
+	call ExprCheck(job, 1)
+	call ExprCheck(job_getchannel(job), 1)
+	call job_stop(job)
+    endif
+    delfunc ExprCheck
+
+    " Regarding function
+    func Func(x) abort
+        call assert_equal(2, test_refcount(function('Func')))
+        call assert_equal(0, test_refcount(funcref('Func')))
+    endfunc
+    call assert_equal(1, test_refcount(function('Func')))
+    call assert_equal(0, test_refcount(function('Func', [1])))
+    call assert_equal(0, test_refcount(funcref('Func')))
+    call assert_equal(0, test_refcount(funcref('Func', [1])))
+    let X = function('Func')
+    let Y = X
+    call assert_equal(1, test_refcount(X))
+    let X = function('Func', [1])
+    let Y = X
+    call assert_equal(2, test_refcount(X))
+    let X = funcref('Func')
+    let Y = X
+    call assert_equal(2, test_refcount(X))
+    let X = funcref('Func', [1])
+    let Y = X
+    call assert_equal(2, test_refcount(X))
+    unlet X
+    unlet Y
+    call Func(1)
+    delfunc Func
+
+    " Function with dict
+    func DictFunc() dict
+        call assert_equal(3, test_refcount(self))
+    endfunc
+    let d = {'Func': function('DictFunc')}
+    call assert_equal(1, test_refcount(d))
+    call assert_equal(0, test_refcount(d.Func))
+    call d.Func()
+    unlet d
+    delfunc DictFunc
+
+    if has('channel')
+      call assert_equal(-1, test_refcount(test_null_job()))
+      call assert_equal(-1, test_refcount(test_null_channel()))
+    endif
+    call assert_equal(-1, test_refcount(test_null_function()))
+    call assert_equal(-1, test_refcount(test_null_partial()))
+    call assert_equal(-1, test_refcount(test_null_blob()))
+    call assert_equal(-1, test_refcount(test_null_list()))
+    call assert_equal(-1, test_refcount(test_null_dict()))
+endfunc
+
+" Test for missing :endif, :endfor, :endwhile and :endtry           {{{1
+func Test_missing_end()
+  call writefile(['if 2 > 1', 'echo ">"'], 'Xscript', 'D')
+  call assert_fails('source Xscript', 'E171:')
+  call writefile(['for i in range(5)', 'echo i'], 'Xscript')
+  call assert_fails('source Xscript', 'E170:')
+  call writefile(['while v:true', 'echo "."'], 'Xscript')
+  call assert_fails('source Xscript', 'E170:')
+  call writefile(['try', 'echo "."'], 'Xscript')
+  call assert_fails('source Xscript', 'E600:')
+
+  " Using endfor with :while
+  let caught_e732 = 0
+  try
+    while v:true
+    endfor
+  catch /E732:/
+    let caught_e732 = 1
+  endtry
+  call assert_equal(1, caught_e732)
+
+  " Using endwhile with :for
+  let caught_e733 = 0
+  try
+    for i in range(1)
+    endwhile
+  catch /E733:/
+    let caught_e733 = 1
+  endtry
+  call assert_equal(1, caught_e733)
+
+  " Using endfunc with :if
+  call assert_fails('exe "if 1 | endfunc | endif"', 'E193:')
+
+  " Missing 'in' in a :for statement
+  call assert_fails('for i range(1) | endfor', 'E690:')
+
+  " Incorrect number of variables in for
+  call assert_fails('for [i,] in range(3) | endfor', 'E475:')
+endfunc
+
+" Test for deep nesting of if/for/while/try statements              {{{1
+func Test_deep_nest()
+  CheckRunVimInTerminal
+
+  let lines =<< trim [SCRIPT]
+    " Deep nesting of if ... endif
+    func Test1()
+      let @a = join(repeat(['if v:true'], 51), "\n")
+      let @a ..= "\n"
+      let @a ..= join(repeat(['endif'], 51), "\n")
+      @a
+      let @a = ''
+    endfunc
+
+    " Deep nesting of for ... endfor
+    func Test2()
+      let @a = join(repeat(['for i in [1]'], 51), "\n")
+      let @a ..= "\n"
+      let @a ..= join(repeat(['endfor'], 51), "\n")
+      @a
+      let @a = ''
+    endfunc
+
+    " Deep nesting of while ... endwhile
+    func Test3()
+      let @a = join(repeat(['while v:true'], 51), "\n")
+      let @a ..= "\n"
+      let @a ..= join(repeat(['endwhile'], 51), "\n")
+      @a
+      let @a = ''
+    endfunc
+
+    " Deep nesting of try ... endtry
+    func Test4()
+      let @a = join(repeat(['try'], 51), "\n")
+      let @a ..= "\necho v:true\n"
+      let @a ..= join(repeat(['endtry'], 51), "\n")
+      @a
+      let @a = ''
+    endfunc
+
+    " Deep nesting of function ... endfunction
+    func Test5()
+      let @a = join(repeat(['function X()'], 51), "\n")
+      let @a ..= "\necho v:true\n"
+      let @a ..= join(repeat(['endfunction'], 51), "\n")
+      @a
+      let @a = ''
+    endfunc
+  [SCRIPT]
+  call writefile(lines, 'Xscript', 'D')
+
+  let buf = RunVimInTerminal('-S Xscript', {'rows': 6})
+
+  " Deep nesting of if ... endif
+  call term_sendkeys(buf, ":call Test1()\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E579:', term_getline(buf, 5))})
+
+  " Deep nesting of for ... endfor
+  call term_sendkeys(buf, ":call Test2()\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
+
+  " Deep nesting of while ... endwhile
+  call term_sendkeys(buf, ":call Test3()\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E585:', term_getline(buf, 5))})
+
+  " Deep nesting of try ... endtry
+  call term_sendkeys(buf, ":call Test4()\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E601:', term_getline(buf, 5))})
+
+  " Deep nesting of function ... endfunction
+  call term_sendkeys(buf, ":call Test5()\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E1058:', term_getline(buf, 4))})
+  call term_sendkeys(buf, "\<C-C>\n")
+  call TermWait(buf)
+
+  "let l = ''
+  "for i in range(1, 6)
+  "  let l ..= term_getline(buf, i) . "\n"
+  "endfor
+  "call assert_report(l)
+
+  call StopVimInTerminal(buf)
+endfunc
+
+" Test for errors in converting to float from various types         {{{1
+func Test_float_conversion_errors()
+  call assert_fails('let x = 4.0 % 2.0', 'E804:')
+  call assert_fails('echo 1.1[0]', 'E806:')
+  call assert_fails('echo sort([function("min"), 1], "f")', 'E891:')
+  call assert_fails('echo 3.2 == "vim"', 'E892:')
+  call assert_fails('echo sort([[], 1], "f")', 'E893:')
+  call assert_fails('echo sort([{}, 1], "f")', 'E894:')
+  call assert_fails('echo 3.2 == v:true', 'E362:')
+  call assert_fails('echo 3.2 == v:none', 'E907:')
+endfunc
+
+" invalid function names               {{{1
+func Test_invalid_function_names()
+  " function name not starting with capital
+  let caught_e128 = 0
+  try
+    func! g:test()
+      echo "test"
+    endfunc
+  catch /E128:/
+    let caught_e128 = 1
+  endtry
+  call assert_equal(1, caught_e128)
+
+  " function name includes a colon
+  let caught_e884 = 0
+  try
+    func! b:test()
+      echo "test"
+    endfunc
+  catch /E884:/
+    let caught_e884 = 1
+  endtry
+  call assert_equal(1, caught_e884)
+
+  " function name followed by #
+  let caught_e128 = 0
+  try
+    func! test2() "#
+      echo "test2"
+    endfunc
+  catch /E128:/
+    let caught_e128 = 1
+  endtry
+  call assert_equal(1, caught_e128)
+
+  " function name starting with/without "g:", buffer-local funcref.
+  function! g:Foo(n)
+    return 'called Foo(' . a:n . ')'
+  endfunction
+  let b:my_func = function('Foo')
+  call assert_equal('called Foo(1)', b:my_func(1))
+  call assert_equal('called Foo(2)', g:Foo(2))
+  call assert_equal('called Foo(3)', Foo(3))
+  delfunc g:Foo
+
+  " script-local function used in Funcref must exist.
+  let lines =<< trim END
+    func s:Testje()
+      return "foo"
+    endfunc
+    let Bar = function('s:Testje')
+    call assert_equal(0, exists('s:Testje'))
+    call assert_equal(1, exists('*s:Testje'))
+    call assert_equal(1, exists('Bar'))
+    call assert_equal(1, exists('*Bar'))
+  END
+  call writefile(lines, 'Xscript', 'D')
+  source Xscript
+endfunc
+
+" substring and variable name              {{{1
+func Test_substring_var()
+  let str = 'abcdef'
+  let n = 3
+  call assert_equal('def', str[n:])
+  call assert_equal('abcd', str[:n])
+  call assert_equal('d', str[n:n])
+  unlet n
+  let nn = 3
+  call assert_equal('def', str[nn:])
+  call assert_equal('abcd', str[:nn])
+  call assert_equal('d', str[nn:nn])
+  unlet nn
+  let b:nn = 4
+  call assert_equal('ef', str[b:nn:])
+  call assert_equal('abcde', str[:b:nn])
+  call assert_equal('e', str[b:nn:b:nn])
+  unlet b:nn
+endfunc
+
+" Test using s: with a typed command              {{{1
+func Test_typed_script_var()
+  CheckRunVimInTerminal
+
+  let buf = RunVimInTerminal('', {'rows': 6})
+
+  " Deep nesting of if ... endif
+  call term_sendkeys(buf, ":echo get(s:, 'foo', 'x')\n")
+  call TermWait(buf)
+  call WaitForAssert({-> assert_match('^E116:', term_getline(buf, 5))})
+
+  call StopVimInTerminal(buf)
+endfunc
+
+" Test for issue6776              {{{1
+func Test_ternary_expression()
+  try
+    call eval('0 ? 0')
+  catch
+  endtry
+  " previous failure should not cause next expression to fail
+  call assert_equal(v:false, eval(string(v:false)))
+
+  try
+    call eval('0 ? "burp')
+  catch
+  endtry
+  " previous failure should not cause next expression to fail
+  call assert_equal(v:false, eval(string(v:false)))
+
+  try
+    call eval('1 ? 0 : "burp')
+  catch
+  endtry
+  " previous failure should not cause next expression to fail
+  call assert_equal(v:false, eval(string(v:false)))
+endfunction
+
+func Test_for_over_string()
+  let res = ''
+  for c in 'aéc̀d'
+    let res ..= c .. '-'
+  endfor
+  call assert_equal('a-é-c̀-d-', res)
+
+  let res = ''
+  for c in ''
+    let res ..= c .. '-'
+  endfor
+  call assert_equal('', res)
+
+  let res = ''
+  for c in test_null_string()
+    let res ..= c .. '-'
+  endfor
+  call assert_equal('', res)
+endfunc
+
+" Test for deeply nested :source command  {{{1
+func Test_deeply_nested_source()
+  let lines =<< trim END
+
+      so
+      sil 0scr
+      delete
+      so
+      0
+  END
+  call writefile(["vim9 silent! @0 \n/"] + lines, 'Xnested.vim', 'D')
+
+  " this must not crash
+  let cmd = GetVimCommand() .. " -e -s -S Xnested.vim -c qa!"
+  call system(cmd)
+endfunc
+
+"-------------------------------------------------------------------------------
+" Modelines								    {{{1
+" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
+"-------------------------------------------------------------------------------