changeset 21632:792398a9fe39 v8.2.1366

patch 8.2.1366: test 49 is old style Commit: https://github.com/vim/vim/commit/a6296200bd5191bab7efcdcc16c9e79eb498e8e0 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Aug 5 11:23:13 2020 +0200 patch 8.2.1366: test 49 is old style Problem: Test 49 is old style. Solution: Convert several tests to new style. (Yegappan Lakshmanan, closes #6629)
author Bram Moolenaar <Bram@vim.org>
date Wed, 05 Aug 2020 11:30:03 +0200
parents e55aba8c2146
children e7d7508f78bb
files src/testdir/script_util.vim src/testdir/test49.ok src/testdir/test49.vim src/testdir/test_vimscript.vim src/version.c
diffstat 5 files changed, 1842 insertions(+), 1759 deletions(-) [+]
line wrap: on
line diff
new file mode 100644
--- /dev/null
+++ b/src/testdir/script_util.vim
@@ -0,0 +1,69 @@
+" Functions shared by the tests for Vim Script
+
+" Commands to track the execution path of a script
+com!		   XpathINIT  let g:Xpath = ''
+com! -nargs=1 -bar Xpath      let g:Xpath ..= <args>
+com!               XloopINIT  let g:Xloop = 1
+com! -nargs=1 -bar Xloop      let g:Xpath ..= <args> .. g:Xloop
+com!               XloopNEXT  let g:Xloop += 1
+
+" MakeScript() - Make a script file from a function.			    {{{2
+"
+" Create a script that consists of the body of the function a:funcname.
+" Replace any ":return" by a ":finish", any argument variable by a global
+" variable, and every ":call" by a ":source" for the next following argument
+" in the variable argument list.  This function is useful if similar tests are
+" to be made for a ":return" from a function call or a ":finish" in a script
+" file.
+func MakeScript(funcname, ...)
+    let script = tempname()
+    execute "redir! >" . script
+    execute "function" a:funcname
+    redir END
+    execute "edit" script
+    " Delete the "function" and the "endfunction" lines.  Do not include the
+    " word "function" in the pattern since it might be translated if LANG is
+    " set.  When MakeScript() is being debugged, this deletes also the debugging
+    " output of its line 3 and 4.
+    exec '1,/.*' . a:funcname . '(.*)/d'
+    /^\d*\s*endfunction\>/,$d
+    %s/^\d*//e
+    %s/return/finish/e
+    %s/\<a:\(\h\w*\)/g:\1/ge
+    normal gg0
+    let cnt = 0
+    while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
+	let cnt = cnt + 1
+	s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
+    endwhile
+    g/^\s*$/d
+    write
+    bwipeout
+    return script
+endfunc
+
+" ExecAsScript - Source a temporary script made from a function.	    {{{2
+"
+" Make a temporary script file from the function a:funcname, ":source" it, and
+" delete it afterwards.  However, if an exception is thrown the file may remain,
+" the caller should call DeleteTheScript() afterwards.
+let s:script_name = ''
+function! ExecAsScript(funcname)
+    " Make a script from the function passed as argument.
+    let s:script_name = MakeScript(a:funcname)
+
+    " Source and delete the script.
+    exec "source" s:script_name
+    call delete(s:script_name)
+    let s:script_name = ''
+endfunction
+
+function! DeleteTheScript()
+    if s:script_name
+	call delete(s:script_name)
+	let s:script_name = ''
+    endif
+endfunc
+
+com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
+
--- a/src/testdir/test49.ok
+++ b/src/testdir/test49.ok
@@ -1,25 +1,4 @@
 Results of test49.vim:
-*** Test  18: OK (67224583)
-*** Test  19: OK (69275973)
-*** Test  20: OK (1874575085)
-*** Test  21: OK (147932225)
-*** Test  22: OK (4161)
-*** Test  23: OK (49)
-*** Test  24: OK (41)
-*** Test  27: OK (1996459)
-*** Test  28: OK (1996459)
-*** Test  29: OK (170428555)
-*** Test  30: OK (190905173)
-*** Test  31: OK (190905173)
-*** Test  34: OK (2146584868)
-*** Test  35: OK (2146584868)
-*** Test  36: OK (1071644672)
-*** Test  37: OK (1071644672)
-*** Test  38: OK (357908480)
-*** Test  39: OK (357908480)
-*** Test  40: OK (357908480)
-*** Test  49: OK (179000669)
-*** Test  50: OK (363550045)
 *** Test  52: OK (1247112011)
 *** Test  53: OK (131071)
 *** Test  54: OK (2047)
--- a/src/testdir/test49.vim
+++ b/src/testdir/test49.vim
@@ -1,6 +1,6 @@
 " Vim script language tests
 " Author:	Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
-" Last Change:	2019 Nov 03
+" Last Change:	2020 Jun 07
 
 "-------------------------------------------------------------------------------
 " Test environment							    {{{1
@@ -607,1647 +607,10 @@ com! -nargs=1 -bar ExecAsScript call Exe
 
 " END_OF_TEST_ENVIRONMENT - do not change or remove this line.
 
-
-" Tests 1 to 17 were moved to test_vimscript.vim
-let Xtest = 18
-
-"-------------------------------------------------------------------------------
-" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
-"
-"	    On an interrupt, the script processing is terminated immediately.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    if 1
-	Xpath 1					" X: 1
-	while 1
-	    Xpath 2				" X: 2
-	    if 1
-		Xpath 4				" X: 4
-		"INTERRUPT
-		Xpath 8				" X: 0
-		break
-		finish
-	    endif | Xpath 16			" X: 0
-	    Xpath 32				" X: 0
-	endwhile | Xpath 64			" X: 0
-	Xpath 128				" X: 0
-    endif | Xpath 256				" X: 0
-    Xpath 512					" X: 0
-endif
-
-if ExtraVim()
-    try
-	Xpath 1024				" X: 1024
-	"INTERRUPT
-	Xpath 2048				" X: 0
-    endtry | Xpath 4096				" X: 0
-    Xpath 8192					" X: 0
-endif
-
-if ExtraVim()
-    function! F()
-	if 1
-	    Xpath 16384				" X: 16384
-	    while 1
-		Xpath 32768			" X: 32768
-		if 1
-		    Xpath 65536			" X: 65536
-		    "INTERRUPT
-		    Xpath 131072		" X: 0
-		    break
-		    return
-		endif | Xpath 262144		" X: 0
-		Xpath Xpath 524288		" X: 0
-	    endwhile | Xpath 1048576		" X: 0
-	    Xpath Xpath 2097152			" X: 0
-	endif | Xpath Xpath 4194304		" X: 0
-	Xpath Xpath 8388608			" X: 0
-    endfunction
-
-    call F() | Xpath 16777216			" X: 0
-    Xpath 33554432				" X: 0
-endif
-
-if ExtraVim()
-    function! G()
-	try
-	    Xpath 67108864			" X: 67108864
-	    "INTERRUPT
-	    Xpath 134217728			" X: 0
-	endtry | Xpath 268435456		" X: 0
-	Xpath 536870912				" X: 0
-    endfunction
-
-    call G() | Xpath 1073741824			" X: 0
-    " The Xpath command does not accept 2^31 (negative); display explicitly:
-    exec "!echo 2147483648 >>" . g:ExtraVimResult
-						" X: 0
-endif
-
-Xcheck 67224583
-
-
-"-------------------------------------------------------------------------------
-" Test 19:  Aborting on errors inside :try/:endtry			    {{{1
-"
-"	    An error in a command dynamically enclosed in a :try/:endtry region
-"	    aborts script processing immediately.  It does not matter whether
-"	    the failing command is outside or inside a function and whether a
-"	    function has an "abort" attribute.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    function! F() abort
-	Xpath 1					" X: 1
-	asdf
-	Xpath 2					" X: 0
-    endfunction
-
-    try
-	Xpath 4					" X: 4
-	call F()
-	Xpath 8					" X: 0
-    endtry | Xpath 16				" X: 0
-    Xpath 32					" X: 0
-endif
-
-if ExtraVim()
-    function! G()
-	Xpath 64				" X: 64
-	asdf
-	Xpath 128				" X: 0
-    endfunction
-
-    try
-	Xpath 256				" X: 256
-	call G()
-	Xpath 512				" X: 0
-    endtry | Xpath 1024				" X: 0
-    Xpath 2048					" X: 0
-endif
-
-if ExtraVim()
-    try
-	Xpath 4096				" X: 4096
-	asdf
-	Xpath 8192				" X: 0
-    endtry | Xpath 16384			" X: 0
-    Xpath 32768					" X: 0
-endif
-
-if ExtraVim()
-    if 1
-	try
-	    Xpath 65536				" X: 65536
-	    asdf
-	    Xpath 131072			" X: 0
-	endtry | Xpath 262144			" X: 0
-    endif | Xpath 524288			" X: 0
-    Xpath 1048576				" X: 0
-endif
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-	try
-	    Xpath 2097152			" X: 2097152
-	    asdf
-	    Xpath 4194304			" X: 0
-	endtry | Xpath 8388608			" X: 0
-    endwhile | Xpath 16777216			" X: 0
-    Xpath 33554432				" X: 0
-endif
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-"	try
-	    Xpath 67108864			" X: 67108864
-    endwhile | Xpath 134217728			" X: 0
-    Xpath 268435456				" X: 0
-endif
-
-Xcheck 69275973
-"-------------------------------------------------------------------------------
-" Test 20:  Aborting on errors after :try/:endtry			    {{{1
-"
-"	    When an error occurs after the last active :try/:endtry region has
-"	    been left, termination behavior is as if no :try/:endtry has been
-"	    seen.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-	try
-	    Xpath 1				" X: 1
-	endtry
-	asdf
-    endwhile | Xpath 2				" X: 0
-    Xpath 4					" X: 4
-endif
-
-if ExtraVim()
-    while 1
-	try
-	    Xpath 8				" X: 8
-	    break
-	    Xpath 16				" X: 0
-	endtry
-    endwhile
-    Xpath 32					" X: 32
-    asdf
-    Xpath 64					" X: 64
-endif
-
-if ExtraVim()
-    while 1
-	try
-	    Xpath 128				" X: 128
-	    break
-	    Xpath 256				" X: 0
-	finally
-	    Xpath 512				" X: 512
-	endtry
-    endwhile
-    Xpath 1024					" X: 1024
-    asdf
-    Xpath 2048					" X: 2048
-endif
-
-if ExtraVim()
-    while 1
-	try
-	    Xpath 4096				" X: 4096
-	finally
-	    Xpath 8192				" X: 8192
-	    break
-	    Xpath 16384				" X: 0
-	endtry
-    endwhile
-    Xpath 32768					" X: 32768
-    asdf
-    Xpath 65536					" X: 65536
-endif
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-	try
-	    Xpath 131072			" X: 131072
-	    continue
-	    Xpath 262144			" X: 0
-	endtry
-    endwhile
-    Xpath 524288				" X: 524288
-    asdf
-    Xpath 1048576				" X: 1048576
-endif
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-	try
-	    Xpath 2097152			" X: 2097152
-	    continue
-	    Xpath 4194304			" X: 0
-	finally
-	    Xpath 8388608			" X: 8388608
-	endtry
-    endwhile
-    Xpath 16777216				" X: 16777216
-    asdf
-    Xpath 33554432				" X: 33554432
-endif
-
-if ExtraVim()
-    let p = 1
-    while p
-	let p = 0
-	try
-	    Xpath 67108864			" X: 67108864
-	finally
-	    Xpath 134217728			" X: 134217728
-	    continue
-	    Xpath 268435456			" X: 0
-	endtry
-    endwhile
-    Xpath 536870912				" X: 536870912
-    asdf
-    Xpath 1073741824				" X: 1073741824
-endif
-
-Xcheck 1874575085
-
-
-"-------------------------------------------------------------------------------
-" Test 21:  :finally for :try after :continue/:break/:return/:finish	    {{{1
-"
-"	    If a :try conditional stays inactive due to a preceding :continue,
-"	    :break, :return, or :finish, its :finally clause should not be
-"	    executed.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    function F()
-	let loops = 2
-	XloopINIT! 1 256
-	while loops > 0
-	    XloopNEXT
-	    let loops = loops - 1
-	    try
-		if loops == 1
-		    Xloop 1			" X: 1
-		    continue
-		    Xloop 2			" X: 0
-		elseif loops == 0
-		    Xloop 4			" X: 4*256
-		    break
-		    Xloop 8			" X: 0
-		endif
-
-		try		" inactive
-		    Xloop 16			" X: 0
-		finally
-		    Xloop 32			" X: 0
-		endtry
-	    finally
-		Xloop 64			" X: 64 + 64*256
-	    endtry
-	    Xloop 128				" X: 0
-	endwhile
-
-	try
-	    Xpath 65536				" X: 65536
-	    return
-	    Xpath 131072			" X: 0
-	    try		    " inactive
-		Xpath 262144			" X: 0
-	    finally
-		Xpath 524288			" X: 0
-	    endtry
-	finally
-	    Xpath 1048576			" X: 1048576
-	endtry
-	Xpath 2097152				" X: 0
-    endfunction
-
-    try
-	Xpath 4194304				" X: 4194304
-	call F()
-	Xpath 8388608				" X: 8388608
-	finish
-	Xpath 16777216				" X: 0
-	try		" inactive
-	    Xpath 33554432			" X: 0
-	finally
-	    Xpath 67108864			" X: 0
-	endtry
-    finally
-	Xpath 134217728				" X: 134217728
-    endtry
-    Xpath 268435456				" X: 0
-endif
-
-Xcheck 147932225
-
-
-"-------------------------------------------------------------------------------
-" Test 22:  :finally for a :try after an error/interrupt/:throw		    {{{1
-"
-"	    If a :try conditional stays inactive due to a preceding error or
-"	    interrupt or :throw, its :finally clause should not be executed.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    function! Error()
-	try
-	    asdf    " aborting error, triggering error exception
-	endtry
-    endfunction
-
-    Xpath 1					" X: 1
-    call Error()
-    Xpath 2					" X: 0
-
-    if 1	" not active due to error
-	try	" not active since :if inactive
-	    Xpath 4				" X: 0
-	finally
-	    Xpath 8				" X: 0
-	endtry
-    endif
-
-    try		" not active due to error
-	Xpath 16				" X: 0
-    finally
-	Xpath 32				" X: 0
-    endtry
-endif
-
-if ExtraVim()
-    function! Interrupt()
-	try
-	    "INTERRUPT	" triggering interrupt exception
-	endtry
-    endfunction
-
-    Xpath 64					" X: 64
-    call Interrupt()
-    Xpath 128					" X: 0
-
-    if 1	" not active due to interrupt
-	try	" not active since :if inactive
-	    Xpath 256				" X: 0
-	finally
-	    Xpath 512				" X: 0
-	endtry
-    endif
-
-    try		" not active due to interrupt
-	Xpath 1024				" X: 0
-    finally
-	Xpath 2048				" X: 0
-    endtry
-endif
-
-if ExtraVim()
-    function! Throw()
-	throw "xyz"
-    endfunction
-
-    Xpath 4096					" X: 4096
-    call Throw()
-    Xpath 8192					" X: 0
-
-    if 1	" not active due to :throw
-	try	" not active since :if inactive
-	    Xpath 16384				" X: 0
-	finally
-	    Xpath 32768				" X: 0
-	endtry
-    endif
-
-    try		" not active due to :throw
-	Xpath 65536				" X: 0
-    finally
-	Xpath 131072				" X: 0
-    endtry
-endif
-
-Xcheck 4161
-
-
-"-------------------------------------------------------------------------------
-" Test 23:  :catch clauses for a :try after a :throw			    {{{1
-"
-"	    If a :try conditional stays inactive due to a preceding :throw,
-"	    none of its :catch clauses should be executed.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    try
-	Xpath 1					" X: 1
-	throw "xyz"
-	Xpath 2					" X: 0
-
-	if 1	" not active due to :throw
-	    try	" not active since :if inactive
-		Xpath 4				" X: 0
-	    catch /xyz/
-		Xpath 8				" X: 0
-	    endtry
-	endif
-    catch /xyz/
-	Xpath 16				" X: 16
-    endtry
-
-    Xpath 32					" X: 32
-    throw "abc"
-    Xpath 64					" X: 0
-
-    try		" not active due to :throw
-	Xpath 128				" X: 0
-    catch /abc/
-	Xpath 256				" X: 0
-    endtry
-endif
-
-Xcheck 49
-
-
-"-------------------------------------------------------------------------------
-" Test 24:  :endtry for a :try after a :throw				    {{{1
-"
-"	    If a :try conditional stays inactive due to a preceding :throw,
-"	    its :endtry should not rethrow the exception to the next surrounding
-"	    active :try conditional.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    try			" try 1
-	try		" try 2
-	    Xpath 1				" X: 1
-	    throw "xyz"	" makes try 2 inactive
-	    Xpath 2				" X: 0
-
-	    try		" try 3
-		Xpath 4				" X: 0
-	    endtry	" no rethrow to try 1
-	catch /xyz/	" should catch although try 2 inactive
-	    Xpath 8				" X: 8
-	endtry
-    catch /xyz/		" try 1 active, but exception already caught
-	Xpath 16				" X: 0
-    endtry
-    Xpath 32					" X: 32
-endif
-
-Xcheck 41
-
-" Tests 25 and 26 were moved to test_trycatch.vim
-let Xtest = 27
-
-
-"-------------------------------------------------------------------------------
-" Test 27:  Executing :finally clauses after :return			    {{{1
-"
-"	    For a :return command dynamically enclosed in a :try/:endtry region,
-"	    :finally clauses are executed and the called function is ended.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! F()
-    try
-	Xpath 1					" X: 1
-	try
-	    Xpath 2				" X: 2
-	    return
-	    Xpath 4				" X: 0
-	finally
-	    Xpath 8				" X: 8
-	endtry
-	Xpath 16				" X: 0
-    finally
-	Xpath 32				" X: 32
-    endtry
-    Xpath 64					" X: 0
-endfunction
-
-function! G()
-    try
-	Xpath 128				" X: 128
-	return
-	Xpath 256				" X: 0
-    finally
-	Xpath 512				" X: 512
-	call F()
-	Xpath 1024				" X: 1024
-    endtry
-    Xpath 2048					" X: 0
-endfunction
-
-function! H()
-    try
-	Xpath 4096				" X: 4096
-	call G()
-	Xpath 8192				" X: 8192
-    finally
-	Xpath 16384				" X: 16384
-	return
-	Xpath 32768				" X: 0
-    endtry
-    Xpath 65536					" X: 0
-endfunction
-
-try
-    Xpath 131072				" X: 131072
-    call H()
-    Xpath 262144				" X: 262144
-finally
-    Xpath 524288				" X: 524288
-endtry
-Xpath 1048576					" X: 1048576
-
-Xcheck 1996459
-
-" Leave F, G, and H for execution as scripts in the next test.
-
-
-"-------------------------------------------------------------------------------
-" Test 28:  Executing :finally clauses after :finish			    {{{1
-"
-"	    For a :finish command dynamically enclosed in a :try/:endtry region,
-"	    :finally clauses are executed and the sourced file is finished.
-"
-"	    This test executes the bodies of the functions F, G, and H from the
-"	    previous test as script files (:return replaced by :finish).
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let scriptF = MakeScript("F")			" X: 1 + 2 + 8 + 32
-let scriptG = MakeScript("G", scriptF)		" X: 128 + 512 + 1024
-let scriptH = MakeScript("H", scriptG)		" X: 4096 + 8192 + 16384
-
-try
-    Xpath 131072				" X: 131072
-    exec "source" scriptH
-    Xpath 262144				" X: 262144
-finally
-    Xpath 524288				" X: 524288
-endtry
-Xpath 1048576					" X: 1048576
-
-call delete(scriptF)
-call delete(scriptG)
-call delete(scriptH)
-unlet scriptF scriptG scriptH
-delfunction F
-delfunction G
-delfunction H
-
-Xcheck 1996459
-
-
-"-------------------------------------------------------------------------------
-" Test 29:  Executing :finally clauses on errors			    {{{1
-"
-"	    After an error in a command dynamically enclosed in a :try/:endtry
-"	    region, :finally clauses are executed and the script processing is
-"	    terminated.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    function! F()
-	while 1
-	    try
-		Xpath 1				" X: 1
-		while 1
-		    try
-			Xpath 2			" X: 2
-			asdf	    " error
-			Xpath 4			" X: 0
-		    finally
-			Xpath 8			" X: 8
-		    endtry | Xpath 16		" X: 0
-		    Xpath 32			" X: 0
-		    break
-		endwhile
-		Xpath 64			" X: 0
-	    finally
-		Xpath 128			" X: 128
-	    endtry | Xpath 256			" X: 0
-	    Xpath 512				" X: 0
-	    break
-	endwhile
-	Xpath 1024				" X: 0
-    endfunction
-
-    while 1
-	try
-	    Xpath 2048				" X: 2048
-	    while 1
-		call F()
-		Xpath 4096			" X: 0
-		break
-	    endwhile  | Xpath 8192		" X: 0
-	    Xpath 16384				" X: 0
-	finally
-	    Xpath 32768				" X: 32768
-	endtry | Xpath 65536			" X: 0
-    endwhile | Xpath 131072			" X: 0
-    Xpath 262144				" X: 0
-endif
-
-if ExtraVim()
-    function! G() abort
-	if 1
-	    try
-		Xpath 524288			" X: 524288
-		asdf	    " error
-		Xpath 1048576			" X: 0
-	    finally
-		Xpath 2097152			" X: 2097152
-	    endtry | Xpath 4194304		" X: 0
-	endif | Xpath 8388608			" X: 0
-	Xpath 16777216				" X: 0
-    endfunction
-
-    if 1
-	try
-	    Xpath 33554432			" X: 33554432
-	    call G()
-	    Xpath 67108864			" X: 0
-	finally
-	    Xpath 134217728			" X: 134217728
-	endtry | Xpath 268435456		" X: 0
-    endif | Xpath 536870912			" X: 0
-    Xpath 1073741824				" X: 0
-endif
-
-Xcheck 170428555
-
-
-"-------------------------------------------------------------------------------
-" Test 30:  Executing :finally clauses on interrupt			    {{{1
-"
-"	    After an interrupt in a command dynamically enclosed in
-"	    a :try/:endtry region, :finally clauses are executed and the
-"	    script processing is terminated.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    XloopINIT 1 16
-
-    function! F()
-	try
-	    Xloop 1				" X: 1 + 1*16
-	    "INTERRUPT
-	    Xloop 2				" X: 0
-	finally
-	    Xloop 4				" X: 4 + 4*16
-	endtry
-	Xloop 8					" X: 0
-    endfunction
-
-    try
-	Xpath 256				" X: 256
-	try
-	    Xpath 512				" X: 512
-	    "INTERRUPT
-	    Xpath 1024				" X: 0
-	finally
-	    Xpath 2048				" X: 2048
-	    try
-		Xpath 4096			" X: 4096
-		try
-		    Xpath 8192			" X: 8192
-		finally
-		    Xpath 16384			" X: 16384
-		    try
-			Xpath 32768		" X: 32768
-			"INTERRUPT
-			Xpath 65536		" X: 0
-		    endtry
-		    Xpath 131072		" X: 0
-		endtry
-		Xpath 262144			" X: 0
-	    endtry
-	    Xpath 524288			" X: 0
-	endtry
-	Xpath 1048576				" X: 0
-    finally
-	Xpath 2097152				" X: 2097152
-	try
-	    Xpath 4194304			" X: 4194304
-	    call F()
-	    Xpath 8388608			" X: 0
-	finally
-	    Xpath 16777216			" X: 16777216
-	    try
-		Xpath 33554432			" X: 33554432
-		XloopNEXT
-		ExecAsScript F
-		Xpath 67108864			" X: 0
-	    finally
-		Xpath 134217728			" X: 134217728
-	    endtry
-	    Xpath 268435456			" X: 0
-	endtry
-	Xpath 536870912				" X: 0
-    endtry
-    Xpath 1073741824				" X: 0
-endif
-
-Xcheck 190905173
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-    XloopINIT 1 16
-
-    function! F()
-	try
-	    Xloop 1				" X: 1 + 1*16
-	    throw "exception"
-	    Xloop 2				" X: 0
-	finally
-	    Xloop 4				" X: 4 + 4*16
-	endtry
-	Xloop 8					" X: 0
-    endfunction
-
-    try
-	Xpath 256				" X: 256
-	try
-	    Xpath 512				" X: 512
-	    throw "exception"
-	    Xpath 1024				" X: 0
-	finally
-	    Xpath 2048				" X: 2048
-	    try
-		Xpath 4096			" X: 4096
-		try
-		    Xpath 8192			" X: 8192
-		finally
-		    Xpath 16384			" X: 16384
-		    try
-			Xpath 32768		" X: 32768
-			throw "exception"
-			Xpath 65536		" X: 0
-		    endtry
-		    Xpath 131072		" X: 0
-		endtry
-		Xpath 262144			" X: 0
-	    endtry
-	    Xpath 524288			" X: 0
-	endtry
-	Xpath 1048576				" X: 0
-    finally
-	Xpath 2097152				" X: 2097152
-	try
-	    Xpath 4194304			" X: 4194304
-	    call F()
-	    Xpath 8388608			" X: 0
-	finally
-	    Xpath 16777216			" X: 16777216
-	    try
-		Xpath 33554432			" X: 33554432
-		XloopNEXT
-		ExecAsScript F
-		Xpath 67108864			" X: 0
-	    finally
-		Xpath 134217728			" X: 134217728
-	    endtry
-	    Xpath 268435456			" X: 0
-	endtry
-	Xpath 536870912				" X: 0
-    endtry
-    Xpath 1073741824				" X: 0
-endif
-
-Xcheck 190905173
-
-" Tests 32 and 33 were moved to test_trycatch.vim
-let Xtest = 34
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 8
-
-    function! 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"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    continue	" discards jump that caused the :finally
-		    Xloop 1		" X: 0
-		endtry
-		Xloop 2			" X: 0
-	    elseif loop == 2
-		Xloop 4			" X: 4*(1+8+64+512+4096+32768+262144)
-	    endif
-	endwhile
-    endfunction
-
-    call C("continue")
-    Xpath 2097152				" X: 2097152
-    call C("break")
-    Xpath 4194304				" X: 4194304
-    call C("return")
-    Xpath 8388608				" X: 8388608
-    let g:jump = "finish"
-    ExecAsScript C
-    unlet g:jump
-    Xpath 16777216				" X: 16777216
-    try
-	call C("error")
-	Xpath 33554432				" X: 33554432
-    finally
-	Xpath 67108864				" X: 67108864
-	try
-	    call C("interrupt")
-	    Xpath 134217728			" X: 134217728
-	finally
-	    Xpath 268435456			" X: 268435456
-	    call C("throw")
-	    Xpath 536870912			" X: 536870912
-	endtry
-    endtry
-    Xpath 1073741824				" X: 1073741824
-
-    delfunction C
-
-endif
-
-Xcheck 2146584868
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 8
-
-    function! 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"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    break	" discards jump that caused the :finally
-		    Xloop 1		" X: 0
-		endtry
-	    elseif loop == 2
-		Xloop 2			" X: 0
-	    endif
-	endwhile
-	Xloop 4				" X: 4*(1+8+64+512+4096+32768+262144)
-    endfunction
-
-    call B("continue")
-    Xpath 2097152				" X: 2097152
-    call B("break")
-    Xpath 4194304				" X: 4194304
-    call B("return")
-    Xpath 8388608				" X: 8388608
-    let g:jump = "finish"
-    ExecAsScript B
-    unlet g:jump
-    Xpath 16777216				" X: 16777216
-    try
-	call B("error")
-	Xpath 33554432				" X: 33554432
-    finally
-	Xpath 67108864				" X: 67108864
-	try
-	    call B("interrupt")
-	    Xpath 134217728			" X: 134217728
-	finally
-	    Xpath 268435456			" X: 268435456
-	    call B("throw")
-	    Xpath 536870912			" X: 536870912
-	endtry
-    endtry
-    Xpath 1073741824				" X: 1073741824
-
-    delfunction B
-
-endif
-
-Xcheck 2146584868
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 8
-
-    function! R(jump, retval) abort
-	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"
-			return
-		    elseif a:jump == "error"
-			asdf
-		    elseif a:jump == "interrupt"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    return a:retval	" discards jump that caused the :finally
-		    Xloop 1			" X: 0
-		endtry
-	    elseif loop == 2
-		Xloop 2				" X: 0
-	    endif
-	endwhile
-	Xloop 4					" X: 0
-    endfunction
-
-    let sum =  -R("continue", -8)
-    Xpath 2097152				" X: 2097152
-    let sum = sum - R("break", -16)
-    Xpath 4194304				" X: 4194304
-    let sum = sum - R("return", -32)
-    Xpath 8388608				" X: 8388608
-    try
-	let sum = sum - R("error", -64)
-	Xpath 16777216				" X: 16777216
-    finally
-	Xpath 33554432				" X: 33554432
-	try
-	    let sum = sum - R("interrupt", -128)
-	    Xpath 67108864			" X: 67108864
-	finally
-	    Xpath 134217728			" X: 134217728
-	    let sum = sum - R("throw", -256)
-	    Xpath 268435456			" X: 268435456
-	endtry
-    endtry
-    Xpath 536870912				" X: 536870912
-
-    let expected = 8 + 16 + 32 + 64 + 128 + 256
-    if sum != expected
-	Xpath 1073741824			" X: 0
-	Xout "sum =" . sum . ", expected: " . expected
-    endif
-
-    unlet sum expected
-    delfunction R
-
-endif
-
-Xcheck 1071644672
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 8
-
-    function! F(jump)	" not executed as function, transformed to a script
-	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 == "finish"
-			finish
-		    elseif a:jump == "error"
-			asdf
-		    elseif a:jump == "interrupt"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    finish	" discards jump that caused the :finally
-		    Xloop 1			" X: 0
-		endtry
-	    elseif loop == 2
-		Xloop 2				" X: 0
-	    endif
-	endwhile
-	Xloop 4					" X: 0
-    endfunction
-
-    let scriptF = MakeScript("F")
-    delfunction F
-
-    let g:jump = "continue"
-    exec "source" scriptF
-    Xpath 2097152				" X: 2097152
-    let g:jump = "break"
-    exec "source" scriptF
-    Xpath 4194304				" X: 4194304
-    let g:jump = "finish"
-    exec "source" scriptF
-    Xpath 8388608				" X: 8388608
-    try
-	let g:jump = "error"
-	exec "source" scriptF
-	Xpath 16777216				" X: 16777216
-    finally
-	Xpath 33554432				" X: 33554432
-	try
-	    let g:jump = "interrupt"
-	    exec "source" scriptF
-	    Xpath 67108864			" X: 67108864
-	finally
-	    Xpath 134217728			" X: 134217728
-	    try
-		let g:jump = "throw"
-		exec "source" scriptF
-		Xpath 268435456			" X: 268435456
-	    finally
-		Xpath 536870912			" X: 536870912
-	    endtry
-	endtry
-    endtry
-    unlet g:jump
-
-    call delete(scriptF)
-    unlet scriptF
-
-endif
-
-Xcheck 1071644672
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 4
-
-    function! E(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"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    asdf	" error; discards jump that caused the :finally
-		endtry
-	    elseif loop == 2
-		Xloop 1				" X: 0
-	    endif
-	endwhile
-	Xloop 2					" X: 0
-    endfunction
-
-    try
-	Xpath 16384				" X: 16384
-	call E("continue")
-	Xpath 32768				" X: 0
-    finally
-	try
-	    Xpath 65536				" X: 65536
-	    call E("break")
-	    Xpath 131072			" X: 0
-	finally
-	    try
-		Xpath 262144			" X: 262144
-		call E("return")
-		Xpath 524288			" X: 0
-	    finally
-		try
-		    Xpath 1048576		" X: 1048576
-		    let g:jump = "finish"
-		    ExecAsScript E
-		    Xpath 2097152		" X: 0
-		finally
-		    unlet g:jump
-		    try
-			Xpath 4194304		" X: 4194304
-			call E("error")
-			Xpath 8388608		" X: 0
-		    finally
-			try
-			    Xpath 16777216	" X: 16777216
-			    call E("interrupt")
-			    Xpath 33554432	" X: 0
-			finally
-			    try
-				Xpath 67108864	" X: 67108864
-				call E("throw")
-				Xpath 134217728	" X: 0
-			    finally
-				Xpath 268435456	" X: 268435456
-				delfunction E
-			    endtry
-			endtry
-		    endtry
-		endtry
-	    endtry
-	endtry
-    endtry
-    Xpath 536870912				" X: 0
-
-endif
-
-Xcheck 357908480
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 4
-
-    function! I(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"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    "INTERRUPT - discards jump that caused the :finally
-		    let dummy = 0
-		endtry
-	    elseif loop == 2
-		Xloop 1				" X: 0
-	    endif
-	endwhile
-	Xloop 2					" X: 0
-    endfunction
-
-    try
-	Xpath 16384				" X: 16384
-	call I("continue")
-	Xpath 32768				" X: 0
-    finally
-	try
-	    Xpath 65536				" X: 65536
-	    call I("break")
-	    Xpath 131072			" X: 0
-	finally
-	    try
-		Xpath 262144			" X: 262144
-		call I("return")
-		Xpath 524288			" X: 0
-	    finally
-		try
-		    Xpath 1048576		" X: 1048576
-		    let g:jump = "finish"
-		    ExecAsScript I
-		    Xpath 2097152		" X: 0
-		finally
-		    unlet g:jump
-		    try
-			Xpath 4194304		" X: 4194304
-			call I("error")
-			Xpath 8388608		" X: 0
-		    finally
-			try
-			    Xpath 16777216	" X: 16777216
-			    call I("interrupt")
-			    Xpath 33554432	" X: 0
-			finally
-			    try
-				Xpath 67108864	" X: 67108864
-				call I("throw")
-				Xpath 134217728	" X: 0
-			    finally
-				Xpath 268435456	" X: 268435456
-				delfunction I
-			    endtry
-			endtry
-		    endtry
-		endtry
-	    endtry
-	endtry
-    endtry
-    Xpath 536870912				" X: 0
-
-endif
-
-Xcheck 357908480
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-if ExtraVim()
-
-    XloopINIT! 1 4
-
-    function! T(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"
-			"INTERRUPT
-			let dummy = 0
-		    elseif a:jump == "throw"
-			throw "abc"
-		    endif
-		finally
-		    throw "xyz"	" discards jump that caused the :finally
-		endtry
-	    elseif loop == 2
-		Xloop 1				" X: 0
-	    endif
-	endwhile
-	Xloop 2					" X: 0
-    endfunction
-
-    try
-	Xpath 16384				" X: 16384
-	call T("continue")
-	Xpath 32768				" X: 0
-    finally
-	try
-	    Xpath 65536				" X: 65536
-	    call T("break")
-	    Xpath 131072			" X: 0
-	finally
-	    try
-		Xpath 262144			" X: 262144
-		call T("return")
-		Xpath 524288			" X: 0
-	    finally
-		try
-		    Xpath 1048576		" X: 1048576
-		    let g:jump = "finish"
-		    ExecAsScript T
-		    Xpath 2097152		" X: 0
-		finally
-		    unlet g:jump
-		    try
-			Xpath 4194304		" X: 4194304
-			call T("error")
-			Xpath 8388608		" X: 0
-		    finally
-			try
-			    Xpath 16777216	" X: 16777216
-			    call T("interrupt")
-			    Xpath 33554432	" X: 0
-			finally
-			    try
-				Xpath 67108864	" X: 67108864
-				call T("throw")
-				Xpath 134217728	" X: 0
-			    finally
-				Xpath 268435456	" X: 268435456
-				delfunction T
-			    endtry
-			endtry
-		    endtry
-		endtry
-	    endtry
-	endtry
-    endtry
-    Xpath 536870912				" X: 0
-
-endif
-
-Xcheck 357908480
-
-" Tests 41 to 48 were moved to test_trycatch.vim
-let Xtest = 49
-
-
-"-------------------------------------------------------------------------------
-" 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.
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-function! C()
-    try
-	Xpath 1					" X: 1
-	throw "arrgh"
-	Xpath 2					" X: 0
-    catch /arrgh/
-	Xpath 4					" X: 4
-    endtry
-    Xpath 8					" X: 8
-endfunction
-
-XloopINIT! 16 16
-
-function! T1()
-    XloopNEXT
-    try
-	Xloop 1					" X: 16 + 16*16
-	throw "arrgh"
-	Xloop 2					" X: 0
-    finally
-	Xloop 4					" X: 64 + 64*16
-    endtry
-    Xloop 8					" X: 0
-endfunction
-
-function! T2()
-    try
-	Xpath 4096				" X: 4096
-	call T1()
-	Xpath 8192				" X: 0
-    finally
-	Xpath 16384				" X: 16384
-    endtry
-    Xpath 32768					" X: 0
-endfunction
-
-try
-    Xpath 65536					" X: 65536
-    call C()	" throw and catch
-    Xpath 131072				" X: 131072
-catch /.*/
-    Xpath 262144				" X: 0
-    Xout v:exception "in" v:throwpoint
-endtry
-
-try
-    Xpath 524288				" X: 524288
-    call T1()  " throw, one level
-    Xpath 1048576				" X: 0
-catch /arrgh/
-    Xpath 2097152				" X: 2097152
-catch /.*/
-    Xpath 4194304				" X: 0
-    Xout v:exception "in" v:throwpoint
-endtry
-
-try
-    Xpath 8388608				" X: 8388608
-    call T2()	" throw, two levels
-    Xpath 16777216				" X: 0
-catch /arrgh/
-    Xpath 33554432				" X: 33554432
-catch /.*/
-    Xpath 67108864				" X: 0
-    Xout v:exception "in" v:throwpoint
-endtry
-Xpath 134217728					" X: 134217728
-
-Xcheck 179000669
-
-" Leave C, T1, and T2 for execution as scripts in the next test.
-
-
-"-------------------------------------------------------------------------------
-" 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).
-"-------------------------------------------------------------------------------
-
-XpathINIT
-
-let scriptC = MakeScript("C")			" X: 1 + 4 + 8
-delfunction C
-
-XloopINIT! 16 16
-
-let scriptT1 = MakeScript("T1")			" X: 16 + 64 + 16*16 + 64*16
-delfunction T1
-
-let scriptT2 = MakeScript("T2", scriptT1)	" X: 4096 + 16384
-delfunction T2
-
-function! F()
-    try
-	Xpath 65536				" X: 65536
-	exec "source" g:scriptC
-	Xpath 131072				" X: 131072
-    catch /.*/
-	Xpath 262144				" X: 0
-	Xout v:exception "in" v:throwpoint
-    endtry
-
-    try
-	Xpath 524288				" X: 524288
-	exec "source" g:scriptT1
-	Xpath 1048576				" X: 0
-    catch /arrgh/
-	Xpath 2097152				" X: 2097152
-    catch /.*/
-	Xpath 4194304				" X: 0
-	Xout v:exception "in" v:throwpoint
-    endtry
-endfunction
-
-try
-    Xpath 8388608				" X: 8388608
-    call F()
-    Xpath 16777216				" X: 16777216
-    exec "source" scriptT2
-    Xpath 33554432				" X: 0
-catch /arrgh/
-    Xpath 67108864				" X: 67108864
-catch /.*/
-    Xpath 134217728				" X: 0
-    Xout v:exception "in" v:throwpoint
-endtry
-Xpath 268435456					" X: 268435456
-
-call delete(scriptC)
-call delete(scriptT1)
-call delete(scriptT2)
-unlet scriptC scriptT1 scriptT2
-delfunction F
-
-Xcheck 363550045
-
-" Test 51 was moved to test_trycatch.vim
+" Tests 1 to 50, 87 were moved to test_vimscript.vim
+" Tests 25, 26, 32, 33, 41-48, 51, 69-75 were moved to test_trycatch.vim
 let Xtest = 52
 
-
 "-------------------------------------------------------------------------------
 " Test 52:  Uncaught exceptions						    {{{1
 "
--- a/src/testdir/test_vimscript.vim
+++ b/src/testdir/test_vimscript.vim
@@ -3,14 +3,12 @@
 
 source check.vim
 source shared.vim
+source script_util.vim
 
 "-------------------------------------------------------------------------------
 " Test environment							    {{{1
 "-------------------------------------------------------------------------------
 
-com!		   XpathINIT  let g:Xpath = ''
-com! -nargs=1 -bar Xpath      let g:Xpath = g:Xpath . <args>
-
 " Append a message to the "messages" file
 func Xout(text)
     split messages
@@ -20,67 +18,30 @@ endfunc
 
 com! -nargs=1	     Xout     call Xout(<args>)
 
-" MakeScript() - Make a script file from a function.			    {{{2
-"
-" Create a script that consists of the body of the function a:funcname.
-" Replace any ":return" by a ":finish", any argument variable by a global
-" variable, and every ":call" by a ":source" for the next following argument
-" in the variable argument list.  This function is useful if similar tests are
-" to be made for a ":return" from a function call or a ":finish" in a script
-" file.
-func MakeScript(funcname, ...)
-    let script = tempname()
-    execute "redir! >" . script
-    execute "function" a:funcname
-    redir END
-    execute "edit" script
-    " Delete the "function" and the "endfunction" lines.  Do not include the
-    " word "function" in the pattern since it might be translated if LANG is
-    " set.  When MakeScript() is being debugged, this deletes also the debugging
-    " output of its line 3 and 4.
-    exec '1,/.*' . a:funcname . '(.*)/d'
-    /^\d*\s*endfunction\>/,$d
-    %s/^\d*//e
-    %s/return/finish/e
-    %s/\<a:\(\h\w*\)/g:\1/ge
-    normal gg0
-    let cnt = 0
-    while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
-	let cnt = cnt + 1
-	s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
-    endwhile
-    g/^\s*$/d
-    write
-    bwipeout
-    return script
+" 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
+    source script_util.vim
+    XpathINIT
+    XloopINIT
+  END
+  let cleanup =<< trim END
+    call writefile(v:errors, 'Xtest.out')
+    qall
+  END
+  call writefile(init, 'Xtest.vim')
+  call writefile(a:test, 'Xtest.vim', 'a')
+  call writefile(a:verify, 'Xverify.vim')
+  call writefile(cleanup, 'Xverify.vim', 'a')
+  call RunVim([], [], "-S Xtest.vim -S Xverify.vim")
+  call assert_equal([], readfile('Xtest.out'))
+  call delete('Xtest.out')
+  call delete('Xtest.vim')
+  call delete('Xverify.vim')
 endfunc
 
-" ExecAsScript - Source a temporary script made from a function.	    {{{2
-"
-" Make a temporary script file from the function a:funcname, ":source" it, and
-" delete it afterwards.  However, if an exception is thrown the file may remain,
-" the caller should call DeleteTheScript() afterwards.
-let s:script_name = ''
-function! ExecAsScript(funcname)
-    " Make a script from the function passed as argument.
-    let s:script_name = MakeScript(a:funcname)
-
-    " Source and delete the script.
-    exec "source" s:script_name
-    call delete(s:script_name)
-    let s:script_name = ''
-endfunction
-
-function! DeleteTheScript()
-    if s:script_name
-	call delete(s:script_name)
-	let s:script_name = ''
-    endif
-endfunc
-
-com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
-
-
 "-------------------------------------------------------------------------------
 " Test 1:   :endwhile in function					    {{{1
 "
@@ -90,7 +51,7 @@ com! -nargs=1 -bar ExecAsScript call Exe
 "	    tests will hang.
 "-------------------------------------------------------------------------------
 
-function! T1_F()
+func T1_F()
     Xpath 'a'
     let first = 1
     while 1
@@ -104,9 +65,9 @@ function! T1_F()
 	    return
 	endif
     endwhile
-endfunction
-
-function! T1_G()
+endfunc
+
+func T1_G()
     Xpath 'h'
     let first = 1
     while 1
@@ -121,7 +82,7 @@ function! T1_G()
 	endif
 	if 1	" unmatched :if
     endwhile
-endfunction
+endfunc
 
 func Test_endwhile_function()
   XpathINIT
@@ -175,7 +136,7 @@ endfunc
 " Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
 "-------------------------------------------------------------------------------
 
-function Test_if_while()
+func Test_if_while()
     XpathINIT
     if 1
 	Xpath 'a'
@@ -235,7 +196,7 @@ endfunc
 " Test 4:   :return							    {{{1
 "-------------------------------------------------------------------------------
 
-function! T4_F()
+func T4_F()
     if 1
 	Xpath 'a'
 	let loops = 3
@@ -253,15 +214,15 @@ function! T4_F()
     else
 	Xpath 'g'
     endif
-endfunction
-
-function Test_return()
+endfunc
+
+func Test_return()
     XpathINIT
     call T4_F()
     Xpath '4'
 
     call assert_equal('ab3e3b2c24', g:Xpath)
-endfunction
+endfunc
 
 
 "-------------------------------------------------------------------------------
@@ -271,14 +232,14 @@ endfunction
 "	    test as a script file (:return replaced by :finish).
 "-------------------------------------------------------------------------------
 
-function Test_finish()
+func Test_finish()
     XpathINIT
     ExecAsScript T4_F
     Xpath '5'
     call DeleteTheScript()
 
     call assert_equal('ab3e3b2c25', g:Xpath)
-endfunction
+endfunc
 
 
 
@@ -412,7 +373,7 @@ delfunction G31
 delfunction G32
 delfunction G33
 
-function Test_defining_functions()
+func Test_defining_functions()
     call assert_equal('ade2ie3ibcg0h1g1h2g2h3fg0h1g1h2g2h3m', g:test6_result)
     call assert_equal('F1G1F2G21G22G23F3G31G32G33', g:test6_calls)
 endfunc
@@ -476,7 +437,7 @@ endfunc
 
 XpathINIT
 
-function! T8_F()
+func T8_F()
     if 1
 	Xpath 'a'
 	while 1
@@ -508,9 +469,9 @@ function! T8_F()
     return novar		" returns (default return value 0)
     Xpath 'q'
     return 1			" not reached
-endfunction
-
-function! T8_G() abort
+endfunc
+
+func T8_G() abort
     if 1
 	Xpath 'r'
 	while 1
@@ -524,9 +485,9 @@ function! T8_G() abort
     Xpath 'x'
 
     return -4			" not reached
-endfunction
-
-function! T8_H() abort
+endfunc
+
+func T8_H() abort
     while 1
 	Xpath 'A'
 	if 1
@@ -540,7 +501,7 @@ function! T8_H() abort
     Xpath 'F'
 
     return -4			" not reached
-endfunction
+endfunc
 
 " Aborted functions (T8_G and T8_H) return -1.
 let g:test8_sum = (T8_F() + 1) - 4 * T8_G() - 8 * T8_H()
@@ -567,7 +528,7 @@ endfunc
 
 XpathINIT
 
-function! F() abort
+func F() abort
     Xpath 'a'
     let result = G()	" not aborted
     Xpath 'b'
@@ -575,30 +536,30 @@ function! F() abort
 	Xpath 'c'
     endif
     return 1
-endfunction
-
-function! G()		" no abort attribute
+endfunc
+
+func G()		" no abort attribute
     Xpath 'd'
     if H() != -1	" aborted
 	Xpath 'e'
     endif
     Xpath 'f'
     return 2
-endfunction
-
-function! H() abort
+endfunc
+
+func H() abort
     Xpath 'g'
     call I()		" aborted
     Xpath 'h'
     return 4
-endfunction
-
-function! I() abort
+endfunc
+
+func I() abort
     Xpath 'i'
     asdf		" error
     Xpath 'j'
     return 8
-endfunction
+endfunc
 
 if F() != 1
     Xpath 'k'
@@ -626,7 +587,7 @@ endfunc
 
 XpathINIT
 
-function! MSG(enr, emsg)
+func MSG(enr, emsg)
     let english = v:lang == "C" || v:lang =~ '^[Ee]n'
     if a:enr == ""
 	Xout "TODO: Add message number for:" a:emsg
@@ -710,10 +671,10 @@ XpathINIT
 
 let calls = 0
 
-function! P(num)
+func P(num)
     let g:calls = g:calls + a:num   " side effect on call
     return 0
-endfunction
+endfunc
 
 if 1
     Xpath 'a'
@@ -1092,7 +1053,1716 @@ func Test_unmatched_if_in_while()
 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 87   using (expr) ? funcref : funcref				    {{{1
 "
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1366,
+/**/
     1365,
 /**/
     1364,