summaryrefslogtreecommitdiff
path: root/src/testdir
diff options
context:
space:
mode:
Diffstat (limited to 'src/testdir')
-rw-r--r--src/testdir/Make_amiga.mak97
-rw-r--r--src/testdir/Make_dos.mak64
-rw-r--r--src/testdir/Make_os2.mak52
-rw-r--r--src/testdir/Make_vms.mms124
-rw-r--r--src/testdir/Makefile58
-rw-r--r--src/testdir/amiga.vim4
-rw-r--r--src/testdir/dos.vim7
-rw-r--r--src/testdir/dotest.in3
-rw-r--r--src/testdir/main.aap58
-rw-r--r--src/testdir/os2.vim3
-rw-r--r--src/testdir/test1.in40
-rw-r--r--src/testdir/test1.ok1
-rw-r--r--src/testdir/test10.in57
-rw-r--r--src/testdir/test10.ok23
-rw-r--r--src/testdir/test10a.in73
-rw-r--r--src/testdir/test10a.ok23
-rw-r--r--src/testdir/test11.in77
-rw-r--r--src/testdir/test11.ok61
-rw-r--r--src/testdir/test12.in52
-rw-r--r--src/testdir/test12.ok10
-rw-r--r--src/testdir/test13.in58
-rw-r--r--src/testdir/test13.ok30
-rw-r--r--src/testdir/test14.in65
-rw-r--r--src/testdir/test14.ok17
-rw-r--r--src/testdir/test15.in136
-rw-r--r--src/testdir/test15.ok111
-rw-r--r--src/testdir/test16.in10
-rw-r--r--src/testdir/test16.ok2
-rw-r--r--src/testdir/test17.in27
-rw-r--r--src/testdir/test17.ok3
-rw-r--r--src/testdir/test17a.in3
-rw-r--r--src/testdir/test18.in16
-rw-r--r--src/testdir/test18.ok4
-rw-r--r--src/testdir/test19.in23
-rw-r--r--src/testdir/test19.ok7
-rw-r--r--src/testdir/test2.in29
-rw-r--r--src/testdir/test2.ok4
-rw-r--r--src/testdir/test20.in22
-rw-r--r--src/testdir/test20.ok6
-rw-r--r--src/testdir/test21.in19
-rw-r--r--src/testdir/test21.ok2
-rw-r--r--src/testdir/test22.in13
-rw-r--r--src/testdir/test22.ok4
-rw-r--r--src/testdir/test23.in15
-rw-r--r--src/testdir/test23.ok2
-rw-r--r--src/testdir/test24.in21
-rw-r--r--src/testdir/test24.ok7
-rw-r--r--src/testdir/test25.in31
-rw-r--r--src/testdir/test25.ok1
-rw-r--r--src/testdir/test26.in43
-rw-r--r--src/testdir/test26.ok10
-rw-r--r--src/testdir/test27.in20
-rw-r--r--src/testdir/test27.ok2
-rw-r--r--src/testdir/test28.inbin0 -> 364 bytes
-rw-r--r--src/testdir/test28.ok2
-rw-r--r--src/testdir/test29.in67
-rw-r--r--src/testdir/test29.ok28
-rw-r--r--src/testdir/test3.in1217
-rw-r--r--src/testdir/test3.ok1090
-rw-r--r--src/testdir/test30.in183
-rw-r--r--src/testdir/test30.ok96
-rw-r--r--src/testdir/test31.in68
-rw-r--r--src/testdir/test31.ok11
-rw-r--r--src/testdir/test32.in56
-rw-r--r--src/testdir/test32.ok15
-rw-r--r--src/testdir/test33.in34
-rw-r--r--src/testdir/test33.ok23
-rw-r--r--src/testdir/test34.in31
-rw-r--r--src/testdir/test34.ok1
-rw-r--r--src/testdir/test35.in21
-rw-r--r--src/testdir/test35.ok4
-rw-r--r--src/testdir/test36.in40
-rw-r--r--src/testdir/test36.ok16
-rw-r--r--src/testdir/test37.in116
-rw-r--r--src/testdir/test37.ok33
-rw-r--r--src/testdir/test38.in33
-rw-r--r--src/testdir/test38.ok13
-rw-r--r--src/testdir/test39.in24
-rw-r--r--src/testdir/test39.ok5
-rw-r--r--src/testdir/test4.in31
-rw-r--r--src/testdir/test4.ok17
-rw-r--r--src/testdir/test40.in63
-rw-r--r--src/testdir/test40.ok11
-rw-r--r--src/testdir/test41.in24
-rw-r--r--src/testdir/test41.ok3
-rw-r--r--src/testdir/test42.inbin0 -> 2368 bytes
-rw-r--r--src/testdir/test42.okbin0 -> 407 bytes
-rw-r--r--src/testdir/test43.in27
-rw-r--r--src/testdir/test43.ok8
-rw-r--r--src/testdir/test44.in37
-rw-r--r--src/testdir/test44.ok11
-rw-r--r--src/testdir/test45.in72
-rw-r--r--src/testdir/test45.ok16
-rw-r--r--src/testdir/test46.in27
-rw-r--r--src/testdir/test46.ok13
-rw-r--r--src/testdir/test47.in44
-rw-r--r--src/testdir/test47.ok3
-rw-r--r--src/testdir/test48.in74
-rw-r--r--src/testdir/test48.ok21
-rw-r--r--src/testdir/test49.in13
-rw-r--r--src/testdir/test49.ok92
-rw-r--r--src/testdir/test49.vim9666
-rw-r--r--src/testdir/test5.in29
-rw-r--r--src/testdir/test5.ok9
-rw-r--r--src/testdir/test50.in85
-rw-r--r--src/testdir/test50.ok14
-rw-r--r--src/testdir/test51.in34
-rw-r--r--src/testdir/test51.ok15
-rw-r--r--src/testdir/test52.in65
-rw-r--r--src/testdir/test52.ok18
-rw-r--r--src/testdir/test6.in24
-rw-r--r--src/testdir/test6.ok18
-rw-r--r--src/testdir/test7.in26
-rw-r--r--src/testdir/test7.ok12
-rw-r--r--src/testdir/test8.in24
-rw-r--r--src/testdir/test8.ok6
-rw-r--r--src/testdir/test9.in12
-rw-r--r--src/testdir/test9.ok2
-rw-r--r--src/testdir/todos.vim3
-rw-r--r--src/testdir/unix.vim3
-rw-r--r--src/testdir/vms.vim4
121 files changed, 15553 insertions, 0 deletions
diff --git a/src/testdir/Make_amiga.mak b/src/testdir/Make_amiga.mak
new file mode 100644
index 000000000..0970b729f
--- /dev/null
+++ b/src/testdir/Make_amiga.mak
@@ -0,0 +1,97 @@
+#
+# Makefile to run al tests for Vim, on Amiga
+#
+# Requires "rm", "csh" and "diff"!
+
+VIMPROG = /vim
+
+# These tests don't work (yet):
+# test2 "\\tmp" doesn't work
+# test10 'errorformat' is different
+# test11 "cat" doesn't work properly
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*"
+# test52 only for Win32
+
+SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out \
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+.SUFFIXES: .in .out
+
+nongui: /tmp $(SCRIPTS)
+ csh -c echo ALL DONE
+
+clean:
+ csh -c \rm -rf *.out /tmp/* Xdotest small.vim tiny.vim mbyte.vim test.ok viminfo
+
+.in.out:
+ copy $*.ok test.ok
+ $(VIMPROG) -u amiga.vim -U NONE --noplugin -s dotest.in $*.in
+ diff test.out $*.ok
+ rename test.out $*.out
+ -delete X#? ALL QUIET
+ -delete test.ok
+
+# Create a directory for temp files
+/tmp:
+ makedir /tmp
+
+# Manx requires all dependencies...
+test1.out: test1.in
+test2.out: test2.in
+test3.out: test3.in
+test4.out: test4.in
+test5.out: test5.in
+test6.out: test6.in
+test7.out: test7.in
+test8.out: test8.in
+test9.out: test9.in
+test10.out: test10.in
+test11.out: test11.in
+test12.out: test12.in
+test13.out: test13.in
+test14.out: test14.in
+test15.out: test15.in
+test16.out: test16.in
+test17.out: test17.in
+test18.out: test18.in
+test19.out: test19.in
+test20.out: test20.in
+test21.out: test21.in
+test22.out: test22.in
+test23.out: test23.in
+test24.out: test24.in
+test25.out: test25.in
+test26.out: test26.in
+test27.out: test27.in
+test28.out: test28.in
+test29.out: test29.in
+test30.out: test30.in
+test31.out: test31.in
+test32.out: test32.in
+test33.out: test33.in
+test34.out: test34.in
+test35.out: test35.in
+test36.out: test36.in
+test37.out: test37.in
+test38.out: test38.in
+test39.out: test39.in
+test40.out: test40.in
+test41.out: test41.in
+test42.out: test42.in
+test43.out: test43.in
+test44.out: test44.in
+test45.out: test45.in
+test46.out: test46.in
+test47.out: test47.in
+test48.out: test48.in
+test51.out: test51.in
diff --git a/src/testdir/Make_dos.mak b/src/testdir/Make_dos.mak
new file mode 100644
index 000000000..b15951e6d
--- /dev/null
+++ b/src/testdir/Make_dos.mak
@@ -0,0 +1,64 @@
+#
+# Makefile to run al tests for Vim, on Dos-like machines.
+#
+# Requires a set of Unix tools: echo, diff, etc.
+
+VIMPROG = ..\\vim
+
+# Omitted:
+# test2 "\\tmp" doesn't work.
+# test10 'errorformat' is different
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*" in file name
+# test31 16 bit version runs out of memory...
+
+SCRIPTS16 = test1.out test19.out test20.out test22.out \
+ test23.out test24.out test28.out test29.out \
+ test35.out test36.out test43.out \
+ test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+SCRIPTS = test3.out test4.out test5.out test6.out test7.out \
+ test8.out test9.out test11.out test13.out test14.out \
+ test15.out test17.out test18.out test21.out test26.out \
+ test30.out test31.out test32.out test33.out test34.out \
+ test37.out test38.out test39.out test40.out test41.out \
+ test42.out test52.out
+
+SCRIPTS32 = test50.out
+
+SCRIPTS_GUI = test16.out
+
+.SUFFIXES: .in .out
+
+nongui: $(SCRIPTS16) $(SCRIPTS)
+ echo ALL DONE
+
+small: $(SCRIPTS16)
+ echo ALL DONE
+
+gui: $(SCRIPTS16) $(SCRIPTS) $(SCRIPTS_GUI)
+ echo ALL DONE
+
+win32: $(SCRIPTS16) $(SCRIPTS) $(SCRIPTS32)
+ echo ALL DONE
+
+clean:
+ -del *.out
+ -del test.ok
+ -del small.vim
+ -del tiny.vim
+ -del mbyte.vim
+ -del X*
+ -del viminfo
+
+.in.out:
+ copy $*.ok test.ok
+ $(VIMPROG) -u dos.vim -U NONE --noplugin -s dotest.in $*.in
+ diff test.out $*.ok
+ -del $*.out
+ rename test.out $*.out
+ -del X*
+ -del test.ok
+ -del viminfo
diff --git a/src/testdir/Make_os2.mak b/src/testdir/Make_os2.mak
new file mode 100644
index 000000000..af582023a
--- /dev/null
+++ b/src/testdir/Make_os2.mak
@@ -0,0 +1,52 @@
+#
+# Makefile to run al tests for Vim, on OS/2
+#
+# Requires a set of Unix tools: echo, diff, etc.
+
+VIMPROG = ../vim.exe
+
+# Omitted:
+# test2 "\\tmp" doesn't work.
+# test10 'errorformat' is different
+# test11 requires sed
+# test12 can't unlink a swap file
+# test25 uses symbolic link
+# test27 can't edit file with "*" in file name
+# test52 only for Win32
+
+SCRIPTS = test1.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out \
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test51.out
+
+.SUFFIXES: .in .out
+
+all: /tmp $(SCRIPTS)
+ @echo ALL DONE
+
+$(SCRIPTS): $(VIMPROG)
+
+clean:
+ -rm -rf *.out Xdotest test.ok tiny.vim small.vim mbyte.vim viminfo
+
+# Make sure all .in and .out files are in DOS fileformat.
+.in.out:
+ $(VIMPROG) -u NONE -s todos.vim $*.in
+ $(VIMPROG) -u NONE -s todos.vim $*.ok
+ copy $*.ok test.ok
+ $(VIMPROG) -u os2.vim --noplugin -s dotest.in $*.in
+ $(VIMPROG) -u NONE -s todos.vim test.out
+ diff test.out $*.ok
+ rename test.out $*.out
+ -rm -rf X* viminfo
+ -del test.ok
+
+# Create a directory for temp files
+/tmp:
+ -mkdir /tmp
diff --git a/src/testdir/Make_vms.mms b/src/testdir/Make_vms.mms
new file mode 100644
index 000000000..23b0b26fc
--- /dev/null
+++ b/src/testdir/Make_vms.mms
@@ -0,0 +1,124 @@
+#
+# Makefile to run all tests for Vim on VMS
+#
+# Authors: Zoltan Arpadffy, <arpadffy@polarhome.com>
+# Sandor Kopanyi, <sandor.kopanyi@mailbox.hu>
+#
+# Last change: 2004 May 03
+#
+# This has been tested on VMS 6.2 to 7.2 on DEC Alpha and VAX.
+# Edit the lines in the Configuration section below to select.
+#
+# Execute with:
+# mms/descrip=Make_vms.mms
+# Cleanup with:
+# mms/descrip=Make_vms.mms clean
+#
+# Make files are MMK compatible.
+#
+# NOTE: You can run this script just in X/Window environment. It will
+# create a new terminals, therefore you have to set up your DISPLAY
+# logical. More info in VMS documentation or with: help set disp.
+#
+#######################################################################
+# Configuration section.
+#######################################################################
+
+# Uncomment if you want tests in GUI mode. Terminal mode is default.
+# WANT_GUI = YES
+
+# Comment out if you want to run Unix specific tests as well, but please
+# be aware, that on OpenVMS will fail, because of cat, rm, etc commands
+# and directory handling.
+# WANT_UNIX = YES
+
+# Comment out if you have gzip on your system
+# HAVE_GZIP = YES
+
+# Comment out if you have GNU compatible diff on your system
+# HAVE_GDIFF = YES
+
+#######################################################################
+# End of configuration section.
+#
+# Please, do not change anything below without programming experience.
+#######################################################################
+
+VIMPROG = <->vim.exe
+
+.SUFFIXES : .out .in
+
+SCRIPT = test1.out test2.out test3.out test4.out test5.out \
+ test6.out test7.out test8.out test9.out test10a.out\
+ test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test26.out \
+ test28.out test29.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out \
+ test48.out test51.out
+
+.IFDEF WANT_GUI
+SCRIPT_GUI = test16.out
+GUI_OPTION = -g
+.ENDIF
+
+.IFDEF WANT_UNIX
+SCRIPT_UNIX = test10.out test12.out test25.out test27.out test30.out test49.out
+.ENDIF
+
+.IFDEF HAVE_GZIP
+SCRIPT_GZIP = test11.out
+.ENDIF
+
+.IFDEF HAVE_GDIFF
+SCRIPT_GDIFF = test47.out
+.ENDIF
+
+.in.out :
+ -@ write sys$output " "
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " "$*" "
+ -@ write sys$output "-----------------------------------------------"
+ -@ create/term/wait mcr $(VIMPROG) $(GUI_OPTION) -u vms.vim --noplugin -s dotest.in $*.in
+ -@ if "''F$SEARCH("test.out.*")'" .NES. "" then differences test.out $*.ok;
+ -@ if "''F$SEARCH("test.out.*")'" .NES. "" then rename test.out $*.out
+ -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.*
+
+all : clean nolog $(SCRIPT) $(SCRIPT_GUI) $(SCRIPT_UNIX) $(SCRIPT_GZIP) $(SCRIPT_GDIFF)
+ -@ write sys$output " "
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " All done"
+ -@ write sys$output "-----------------------------------------------"
+ -@ deassign sys$output
+ -@ delete/noconfirm/nolog x*.*.*
+ -@ type test.log
+
+nolog :
+ -@ define sys$output test.log
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " Standard VIM test cases"
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " OpenVMS version: ''F$GETSYI("VERSION")'"
+ -@ write sys$output " Vim version:"
+ -@ mcr $(VIMPROG) --version
+ -@ write sys$output " Test date:"
+ -@ show time
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output " Test results:"
+ -@ write sys$output "-----------------------------------------------"
+ -@ write sys$output "MAKE_VMS.MMS options:"
+ -@ write sys$output " WANT_GUI = ""$(WANT_GUI)"" "
+ -@ write sys$output " WANT_UNIX = ""$(WANT_UNIX)"" "
+ -@ write sys$output " HAVE_GZIP = ""$(HAVE_GZIP)"" "
+ -@ write sys$output " HAVE_GDIFF= ""$(HAVE_GDIFF)"" "
+ -@ write sys$output "Default vimrc file is VMS.VIM:
+ -@ write sys$output "-----------------------------------------------"
+ -@ type VMS.VIM
+
+clean :
+ -@ if "''F$SEARCH("*.out")'" .NES. "" then delete/noconfirm/nolog *.out.*
+ -@ if "''F$SEARCH("test.log")'" .NES. "" then delete/noconfirm/nolog test.log.*
+ -@ if "''F$SEARCH("Xdotest.*")'" .NES. "" then delete/noconfirm/nolog Xdotest.*.*
+ -@ if "''F$SEARCH("*.*_sw*")'" .NES. "" then delete/noconfirm/nolog *.*_sw*.*
diff --git a/src/testdir/Makefile b/src/testdir/Makefile
new file mode 100644
index 000000000..7ed97fe21
--- /dev/null
+++ b/src/testdir/Makefile
@@ -0,0 +1,58 @@
+#
+# Makefile to run al tests for Vim
+#
+
+VIMPROG = ../vim
+
+SCRIPTS = test1.out test2.out test3.out test4.out test5.out test6.out \
+ test7.out test8.out test9.out test10.out test11.out \
+ test12.out test13.out test14.out test15.out test17.out \
+ test18.out test19.out test20.out test21.out test22.out \
+ test23.out test24.out test25.out test26.out test27.out \
+ test28.out test29.out test30.out test31.out test32.out \
+ test33.out test34.out test35.out test36.out test37.out \
+ test38.out test39.out test40.out test41.out test42.out \
+ test43.out test44.out test45.out test46.out test47.out \
+ test48.out test49.out test51.out test52.out
+
+SCRIPTS_GUI = test16.out
+
+.SUFFIXES: .in .out
+
+nongui: nolog $(SCRIPTS)
+ @echo
+ @cat test.log
+ @echo ALL DONE
+
+gui: nolog $(SCRIPTS) $(SCRIPTS_GUI)
+ @echo
+ @cat test.log
+ @echo ALL DONE
+
+$(SCRIPTS) $(SCRIPTS_GUI): $(VIMPROG)
+
+clean:
+ -rm -rf *.out *.rej *.orig test.log tiny.vim small.vim mbyte.vim test.ok X* viminfo
+
+test1.out: test1.in
+ -rm -f $*.failed tiny.vim small.vim mbyte.vim test.ok X* viminfo
+ $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+ @/bin/sh -c "if diff test.out $*.ok; \
+ then mv -f test.out $*.out; \
+ else echo; \
+ echo test1 FAILED - Something basic is wrong; \
+ echo; exit 1; fi"
+ -rm -rf X* viminfo
+
+.in.out:
+ -rm -f $*.failed test.ok X*
+ cp $*.ok test.ok
+ $(VIMPROG) -u unix.vim -U NONE --noplugin -s dotest.in $*.in
+ @/bin/sh -c "if diff test.out $*.ok; \
+ then mv -f test.out $*.out; \
+ else echo $* FAILED >>test.log; mv -f test.out $*.failed; \
+ fi"
+ -rm -rf X* test.ok viminfo
+
+nolog:
+ -echo Test results: >test.log
diff --git a/src/testdir/amiga.vim b/src/testdir/amiga.vim
new file mode 100644
index 000000000..e0ca47a8e
--- /dev/null
+++ b/src/testdir/amiga.vim
@@ -0,0 +1,4 @@
+" Settings for test script execution
+set shell=csh
+map! /tmp t:
+cmap !rm !Delete all
diff --git a/src/testdir/dos.vim b/src/testdir/dos.vim
new file mode 100644
index 000000000..27764db9d
--- /dev/null
+++ b/src/testdir/dos.vim
@@ -0,0 +1,7 @@
+" Settings for test script execution
+" Always use "COMMAND.COM", don't use the value of "$SHELL".
+set shell=c:\COMMAND.COM shellquote= shellxquote= shellcmdflag=/c shellredir=>
+" This is used only when the +eval feature is available.
+if executable("cmd.exe")
+ set shell=cmd.exe
+endif
diff --git a/src/testdir/dotest.in b/src/testdir/dotest.in
new file mode 100644
index 000000000..b2a0e1a68
--- /dev/null
+++ b/src/testdir/dotest.in
@@ -0,0 +1,3 @@
+:set cp
+:map dotest /^STARTTEST j:set ff=unix cpo-=A :.,/ENDTEST/-1w! Xdotest :set ff& cpo+=A nj0:so! Xdotest dotest
+dotest
diff --git a/src/testdir/main.aap b/src/testdir/main.aap
new file mode 100644
index 000000000..0293b92f8
--- /dev/null
+++ b/src/testdir/main.aap
@@ -0,0 +1,58 @@
+#
+# Makefile to run al tests for Vim
+#
+
+VimProg ?= ../vim
+
+Scripts = test1.out test2.out test3.out test4.out test5.out test6.out
+ test7.out test8.out test9.out test10.out test11.out
+ test12.out test13.out test14.out test15.out test17.out
+ test18.out test19.out test20.out test21.out test22.out
+ test23.out test24.out test25.out test26.out test27.out
+ test28.out test29.out test30.out test31.out test32.out
+ test33.out test34.out test35.out test36.out test37.out
+ test38.out test39.out test40.out test41.out test42.out
+ test43.out test44.out test45.out test46.out test47.out
+ test48.out test49.out
+
+ScriptsGUI = test16.out
+
+# Build "nongui" when no target was specified.
+nongui: newlog $Scripts
+ :print
+ :cat test.log
+ :print ALL DONE
+
+# Build "ngui" when specified.
+gui: newlog $Scripts $ScriptsGUI
+ :print
+ :cat test.log
+ :print ALL DONE
+
+$Scripts $ScriptsGUI: $VimProg
+
+clean:
+ :del {r}{force} *.out test.log tiny.vim small.vim mbyte.vim test.ok X*
+
+# test1 is special, it checks for features
+test1.out: test1.in
+ :del {force} test1.failed tiny.vim small.vim mbyte.vim
+ :sys {i} $VimProg -u unix.vim -U NONE --noplugin -s dotest.in test1.in
+ @if os.system("diff test.out test1.ok") != 0:
+ :error test1 FAILED - Something basic is wrong
+ :move {force} test.out test1.out
+ :del {r}{force} X*
+
+:rule %.out : %.in
+ :del {force} $(match).failed test.ok
+ :copy $(match).ok test.ok
+ :sys {i} $VimProg -u unix.vim -U NONE --noplugin -s dotest.in $(match).in
+ @if os.system("diff test.out " + match + ".ok") != 0:
+ :print $match FAILED >>test.log
+ :move {force} test.out $(match).failed
+ @else:
+ :move {force} test.out $(match).out
+ :del {r}{force} X* test.ok
+
+newlog:
+ :print Test results: >! test.log
diff --git a/src/testdir/os2.vim b/src/testdir/os2.vim
new file mode 100644
index 000000000..c97ba5d00
--- /dev/null
+++ b/src/testdir/os2.vim
@@ -0,0 +1,3 @@
+" Settings for test script execution
+" Always use "CMD.EXE", don't use the value of "$SHELL".
+set shell=CMD.EXE shellquote= shellxquote= shellcmdflag=/c shellredir=>
diff --git a/src/testdir/test1.in b/src/testdir/test1.in
new file mode 100644
index 000000000..6d1bddee9
--- /dev/null
+++ b/src/testdir/test1.in
@@ -0,0 +1,40 @@
+
+First a simple test to check if the test script works.
+
+If Vim was not compiled with the +eval feature, the small.vim script will be
+set to copy the test.ok file to test.out, so that it looks like the test
+succeeded. Otherwise an empty small.vim is written. small.vim is sourced by
+tests that require the +eval feature or other features that are missing in the
+small version.
+
+If Vim was not compiled with the +windows feature, the tiny.vim script will be
+set like small.vim above. tiny.vim is sourced by tests that require the
++windows feature or other features that are missing in the tiny version.
+
+If Vim was not compiled with the +multi_byte feature, the mbyte.vim script will be set like small.vim above. mbyte.vim is sourced by tests that require the
++multi_byte feature.
+
+STARTTEST
+:" Write a single line to test.out to check if testing works at all.
+:%d
+athis is a test:w! test.out
+:" Create small.vim and tiny.vim empty, create mbyte.vim to skip the test.
+0D:w! small.vim
+:w! tiny.vim
+ae! test.ok
+w! test.out
+qa!
+:w! mbyte.vim
+:" If +multi_byte feature supported, make mbyte.vim empty.
+:if has("multi_byte") | sp another | w! mbyte.vim | q | endif
+:" If +eval feature supported quit here, leaving tiny.vim and small.vim empty.
+:" Otherwise write small.vim to skip the test.
+:if 1 | q! | endif
+:w! small.vim
+:" If +windows feature not supported :sp will fail and tiny.vim will be
+:" written to skip the test.
+:sp another
+:wq! tiny.vim
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test1.ok b/src/testdir/test1.ok
new file mode 100644
index 000000000..90bfcb510
--- /dev/null
+++ b/src/testdir/test1.ok
@@ -0,0 +1 @@
+this is a test
diff --git a/src/testdir/test10.in b/src/testdir/test10.in
new file mode 100644
index 000000000..f15c4f5d2
--- /dev/null
+++ b/src/testdir/test10.in
@@ -0,0 +1,57 @@
+Test for 'errorformat'.
+
+STARTTEST
+:so small.vim
+:/start of errorfile/,/end of errorfile/w! Xerrorfile
+:/start of testfile/,/end of testfile/w! Xtestfile
+:cf Xerrorfile
+rA
+:cn
+rB
+:cn
+rC
+:cn
+rD
+:cn
+rE
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of errorfile
+"Xtestfile", line 4.12: 1506-045 (S) Undeclared identifier fd_set.
+"Xtestfile", line 7 col 19; this is an error
+gcc -c -DHAVE_CONFIsing-prototypes -I/usr/X11R6/include version.c
+Xtestfile:13: parse error before `asd'
+make: *** [vim] Error 1
+in file "Xtestfile" linenr 16: there is an error
+
+2 returned
+"Xtestfile", linenr 19: yet another problem
+
+Does anyone know what is the problem and how to correction it?
+end of errorfile
+
+start of testfile
+line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10.ok b/src/testdir/test10.ok
new file mode 100644
index 000000000..2c86889c1
--- /dev/null
+++ b/src/testdir/test10.ok
@@ -0,0 +1,23 @@
+start of testfile
+line 2 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxAxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxBxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Cine 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Dine 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Eine 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10a.in b/src/testdir/test10a.in
new file mode 100644
index 000000000..19e8652fe
--- /dev/null
+++ b/src/testdir/test10a.in
@@ -0,0 +1,73 @@
+Test for 'errorformat'.
+
+STARTTEST
+:so small.vim
+:/start of errorfile/,/end of errorfile/w! Xerrorfile
+:/start of testfile/,/end of testfile/w! Xtestfile
+:cf Xerrorfile
+rA
+:cn
+rB
+:cn
+rC
+:cn
+rD
+:cn
+rE
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of errorfile
+
+ printf(" %d \n", (number/other)%10 );
+..................^
+%CC-E-NOSEMI, Missing ";".
+at line number 4 in file SYS$DISK:XTESTFILE
+
+ other=10000000;
+.............^
+%CC-E-UNDECLARED, In this statement, "oszt" is not declared.
+at line number 7 in file SYS$DISK:XTESTFILE
+
+ for (i = 0; i<7 ; i++ ){
+..................^
+%CC-E-UNDECLARED, In this statement, "i" is not declared.
+at line number 16 in file SYS$DISK:XTESTFILE
+
+some other error somewhere here.
+...........................^
+%CC-W-WARRING, Sorry, but no expalnation for such an warring.
+at line number 19 in file SYS$DISK:XTESTFILE
+
+and finally some other error exactly here.
+.....................................^
+%CC-I-INFORMATIONAL, It should be some informational message.
+at line number 20 in file SYS$DISK:XTESTFILE
+
+Does anyone know what is the problem and how to correct ?? :)
+end of errorfile
+
+start of testfile
+01234567890123456789012345678901234567
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test10a.ok b/src/testdir/test10a.ok
new file mode 100644
index 000000000..10e78c923
--- /dev/null
+++ b/src/testdir/test10a.ok
@@ -0,0 +1,23 @@
+start of testfile
+01234567890123456789012345678901234567
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 xxxxxxxxxxAxxxxxxxxxxxxxxxxxxx
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 7 xxxxxBxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 11 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 12 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 13 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 14 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 15 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 16 xxxxxxxxxxCxxxxxxxxxxxxxxxxxxx
+line 17 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 18 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 19 xxxxxxxxxxxxxxxxxxxDxxxxxxxxxx
+line 20 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxE
+line 21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 22 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+end of testfile
diff --git a/src/testdir/test11.in b/src/testdir/test11.in
new file mode 100644
index 000000000..6b296fd4e
--- /dev/null
+++ b/src/testdir/test11.in
@@ -0,0 +1,77 @@
+Tests for autocommands:
+- FileWritePre writing a compressed file
+- FileReadPost reading a compressed file
+- BufNewFile reading a file template
+- BufReadPre decompressing the file to be read
+- FilterReadPre substituting characters in the temp file
+- FilterReadPost substituting characters after filtering
+- FileReadPre set options for decompression
+- FileReadPost decompress the file
+
+Note: This test will fail if "gzip" is not available.
+$GZIP is made empty, "-v" would cause trouble.
+Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz" being
+modified outside of Vim (noticed on Solaris).
+
+STARTTEST
+:so small.vim
+:let $GZIP = ""
+:au FileChangedShell * echo "caught FileChangedShell"
+:set bin
+:au FileWritePre *.gz '[,']!gzip
+:au FileWritePost *.gz undo
+:/start of testfile/,/end of testfile/w! Xtestfile.gz
+:au FileReadPost *.gz '[,']!gzip -d
+:$r Xtestfile.gz " Read and decompress the testfile
+:?startstart?,$w! test.out " Write contents of this file
+:au BufNewFile *.c read Xtest.c
+gg/^end of testfile
+:/start of test.c/+1,/end of test.c/-1w! Xtest.c
+:e! foo.c " Will load Xtest.c
+:au FileAppendPre *.out '[,']s/new/NEW/
+:au FileAppendPost *.out !cat Xtest.c >>test.out
+:w>>test.out " Append it to the output file
+:au! FileAppendPre
+:" setup autocommands to decompress before reading and re-compress afterwards
+:au BufReadPre *.gz !gzip -d <afile>
+:au BufReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
+:au BufReadPost *.gz call rename(expand("<afile>"), expand("<afile>:r"))
+:au BufReadPost *.gz !gzip <afile>:r
+:e! Xtestfile.gz " Edit compressed file
+:w>>test.out " Append it to the output file
+:au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>").".t")
+:au FilterReadPre *.out !sed s/e/E/ <afile>.t ><afile>
+:au FilterReadPre *.out !rm <afile>.t
+:au FilterReadPost *.out '[,']s/x/X/g
+:e! test.out " Edit the output file
+:23,$!cat
+:au! FileReadPre *.gz !gzip -d <afile>
+:au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
+:au! FileReadPost *.gz '[,']s/l/L/
+:$r Xtestfile.gz " Read compressed file
+:w " write it, after filtering
+:au! " remove all autocommands
+:e " Edit test.out again
+:set nobin ff& " use the default fileformat for writing
+:w
+:qa!
+ENDTEST
+
+startstart
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 Abcdefghijklmnopqrstuvwxyz
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 Abcdefghijklmnopqrstuvwxyz
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfile
+
+start of test.c
+/*
+ * Here is a new .c file
+ */
+end of test.c
diff --git a/src/testdir/test11.ok b/src/testdir/test11.ok
new file mode 100644
index 000000000..af8c5ce26
--- /dev/null
+++ b/src/testdir/test11.ok
@@ -0,0 +1,61 @@
+startstart
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 6 Abcdefghijklmnopqrstuvwxyz
+line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 8 Abcdefghijklmnopqrstuvwxyz
+line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfile
+
+start of test.c
+/*
+ * Here is a new .c file
+ */
+end of test.c
+start of testfile
+line 2 Abcdefghijklmnopqrstuvwxyz
+line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+line 4 Abcdefghijklmnopqrstuvwxyz
+linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 6 AbcdefghijklmnopqrstuvwXyz
+linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 8 AbcdefghijklmnopqrstuvwXyz
+linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 10 AbcdefghijklmnopqrstuvwXyz
+End of testfile
+
+/*
+ * HEre is a NEW .c file
+ */
+/*
+ * HEre is a new .c file
+ */
+start of tEstfile
+linE 2 AbcdefghijklmnopqrstuvwXyz
+linE 3 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 4 AbcdefghijklmnopqrstuvwXyz
+linE 5 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 6 AbcdefghijklmnopqrstuvwXyz
+linE 7 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 8 AbcdefghijklmnopqrstuvwXyz
+linE 9 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+linE 10 AbcdefghijklmnopqrstuvwXyz
+End of testfile
+/*
+ * HEre is a new .c file
+ */
+start of testfiLe
+Line 2 Abcdefghijklmnopqrstuvwxyz
+Line 3 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 4 Abcdefghijklmnopqrstuvwxyz
+Line 5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 6 Abcdefghijklmnopqrstuvwxyz
+Line 7 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 8 Abcdefghijklmnopqrstuvwxyz
+Line 9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
+Line 10 Abcdefghijklmnopqrstuvwxyz
+end of testfiLe
diff --git a/src/testdir/test12.in b/src/testdir/test12.in
new file mode 100644
index 000000000..46e9c45b8
--- /dev/null
+++ b/src/testdir/test12.in
@@ -0,0 +1,52 @@
+Tests for 'directory' option.
+- ".", in same dir as file
+- "./dir", in directory relative to file
+- "dir", in directory relative to current dir
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:set dir=.,~
+:/start of testfile/,/end of testfile/w! Xtest1
+:" do an ls of the current dir to find the swap file (should not be there)
+:if has("unix")
+: !ls .X*.swp >test.out
+:else
+: r !ls X*.swp >test.out
+:endif
+:!echo first line >>test.out
+:e Xtest1
+:if has("unix")
+:" Do an ls of the current dir to find the swap file, remove the leading dot
+:" to make the result the same for all systems.
+: r!ls .X*.swp
+: s/\.*X/X/
+: .w >>test.out
+: undo
+:else
+: !ls X*.swp >>test.out
+:endif
+:!echo under Xtest1.swp >>test.out
+:!mkdir Xtest2
+:set dir=./Xtest2,.,~
+:e Xtest1
+:!ls X*.swp >>test.out
+:!echo under under >>test.out
+:!ls Xtest2 >>test.out
+:!echo under Xtest1.swp >>test.out
+:!mkdir Xtest.je
+:/start of testfile/,/end of testfile/w! Xtest2/Xtest3
+:set dir=Xtest.je,~
+:e Xtest2/Xtest3
+:swap
+:!ls Xtest2 >>test.out
+:!echo under Xtest3 >>test.out
+:!ls Xtest.je >>test.out
+:!echo under Xtest3.swp >>test.out
+:qa!
+ENDTEST
+
+start of testfile
+line 2 Abcdefghij
+line 3 Abcdefghij
+end of testfile
diff --git a/src/testdir/test12.ok b/src/testdir/test12.ok
new file mode 100644
index 000000000..605623b11
--- /dev/null
+++ b/src/testdir/test12.ok
@@ -0,0 +1,10 @@
+first line
+Xtest1.swp
+under Xtest1.swp
+under under
+Xtest1.swp
+under Xtest1.swp
+Xtest3
+under Xtest3
+Xtest3.swp
+under Xtest3.swp
diff --git a/src/testdir/test13.in b/src/testdir/test13.in
new file mode 100644
index 000000000..cb8a6fff8
--- /dev/null
+++ b/src/testdir/test13.in
@@ -0,0 +1,58 @@
+Tests for autocommands on :close command
+
+Write three files and open them, each in a window.
+Then go to next window, with autocommand that deletes the previous one.
+Do this twice, writing the file.
+
+Also test deleting the buffer on a Unload event. If this goes wrong there
+will be the ATTENTION prompt.
+
+Also test changing buffers in a BufDel autocommand. If this goes wrong there
+are ml_line errors and/or a Crash.
+
+STARTTEST
+:so small.vim
+:/^start of testfile/,/^end of testfile/w! Xtestje1
+:/^start of testfile/,/^end of testfile/w! Xtestje2
+:/^start of testfile/,/^end of testfile/w! Xtestje3
+:e Xtestje1
+otestje1
+:w
+:sp Xtestje2
+otestje2
+:w
+:sp Xtestje3
+otestje3
+:w
+
+:au WinLeave Xtestje2 bwipe
+
+:w! test.out
+:au WinLeave Xtestje1 bwipe Xtestje3
+:close
+:w >>test.out
+:e Xtestje1
+:bwipe Xtestje2 Xtestje3 test.out
+:au!
+:au! BufUnload Xtestje1 bwipe
+:e Xtestje3
+:w >>test.out
+:e Xtestje2
+:sp Xtestje1
+:e
+:w >>test.out
+:au!
+:only
+:e Xtestje1
+:bwipe Xtestje2 Xtestje3 test.out test13.in
+:au BufWipeout Xtestje1 buf Xtestje1
+:bwipe
+:w >>test.out
+:qa!
+ENDTEST
+
+start of testfile
+ contents
+ contents
+ contents
+end of testfile
diff --git a/src/testdir/test13.ok b/src/testdir/test13.ok
new file mode 100644
index 000000000..0f1fc347a
--- /dev/null
+++ b/src/testdir/test13.ok
@@ -0,0 +1,30 @@
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje3
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje2
+ contents
+ contents
+ contents
+end of testfile
+start of testfile
+testje1
+ contents
+ contents
+ contents
+end of testfile
diff --git a/src/testdir/test14.in b/src/testdir/test14.in
new file mode 100644
index 000000000..57fb9573f
--- /dev/null
+++ b/src/testdir/test14.in
@@ -0,0 +1,65 @@
+Tests for "vaBiB", end could be wrong.
+Also test ":s/pat/sub/" with different ~s in sub.
+Also test for ^Vxff and ^Vo123 in Insert mode.
+Also test "[m", "]m", "[M" and "]M"
+
+STARTTEST
+:so small.vim
+/Start cursor here
+vaBiBD:?Bug?,/Piece/-2w! test.out
+/^- Bug
+:s/u/~u~/
+:s/i/~u~/
+:s/o/~~~/
+:.w >>test.out
+:if has("ebcdic")
+: let tt = "o\<C-V>193\<C-V>xc2\<C-V>o303 \<C-V>90a\<C-V>xfg\<C-V>o578\<Esc>"
+:else
+: let tt = "o\<C-V>65\<C-V>x42\<C-V>o103 \<C-V>33a\<C-V>xfg\<C-V>o78\<Esc>"
+:endif
+:exe "normal " . tt
+:.w >>test.out
+:set vb
+/^Piece
+2]maA:.w >>test.out
+j]maB:.w >>test.out
+]maC:.w >>test.out
+[maD:.w >>test.out
+k2[maE:.w >>test.out
+3[maF:.w >>test.out
+]MaG:.w >>test.out
+j2]MaH:.w >>test.out
+]M]MaI:.w >>test.out
+2[MaJ:.w >>test.out
+k[MaK:.w >>test.out
+3[MaL:.w >>test.out
+:qa!
+ENDTEST
+
+- Bug in "vPPPP" on this text (Webb):
+ {
+ cmd;
+ {
+ cmd; /* <-- Start cursor here */
+ {
+ }
+ }
+ }
+
+Piece of Java
+{
+ tt m1 {
+ t1;
+ } e1
+
+ tt m2 {
+ t2;
+ } e2
+
+ tt m3 {
+ if (x)
+ {
+ t3;
+ }
+ } e3
+}
diff --git a/src/testdir/test14.ok b/src/testdir/test14.ok
new file mode 100644
index 000000000..e893ba803
--- /dev/null
+++ b/src/testdir/test14.ok
@@ -0,0 +1,17 @@
+- Bug in "vPPPP" on this text (Webb):
+ {
+ }
+- Bug uuun "vPPPP" uuuuuuuuun this text (Webb):
+ABC !ag8
+ tt m1 {A
+ tt m2 {B
+ tt m3 {C
+ tt m3 {DC
+ tt m1 {EA
+{F
+ }G e1
+ }H e3
+}I
+ }JH e3
+ }K e2
+{LF
diff --git a/src/testdir/test15.in b/src/testdir/test15.in
new file mode 100644
index 000000000..366529a55
--- /dev/null
+++ b/src/testdir/test15.in
@@ -0,0 +1,136 @@
+Tests for :right on text with embedded TAB.
+Also test formatting a paragraph.
+Also test undo after ":%s" and formatting.
+
+STARTTEST
+:so small.vim
+:set tw=65
+
+:/^\s*test for :left/,/^\s*test for :center/ left
+:/^\s*test for :center/,/^\s*test for :right/ center
+:/^\s*test for :right/,/^xxx/-1 right
+:set fo+=tcroql tw=72
+/xxxxxxxx$
+0gq6kk
+:set nocp viminfo+=nviminfo
+:" undo/redo here to make the next undo only work on the following changes
+u
+:map gg :.,.+2s/^/x/<CR>kk:set tw=3<CR>gqq
+/^aa
+ggu
+:?test for :left?,$w! test.out
+:qa!
+ENDTEST
+
+ test for :left
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+asxxdfa a
+
+ test for :center
+ a a
+ fa afd asdf
+ dfa a
+ sdfa afd asdf
+ asdfa a
+ xasdfa asdfasdfasdfasdfasdf
+asxxdfa a
+
+ test for :right
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+ asxxdfa a
+ asxa;ofa a
+ asdfaqwer a
+ a ax
+ fa ax
+ dfa ax
+ sdfa ax
+ asdfa ax
+ xasdfa ax
+ asxxdfa ax
+ asxa;ofa ax
+ asdfaqwer ax
+ a axx
+ fa axx
+ dfa axx
+ sdfa axx
+ asdfa axx
+ xasdfa axx
+ asxxdfa axx
+ asxa;ofa axx
+ asdfaqwer axx
+ a axxx
+ fa axxx
+ dfa axxx
+ sdfa axxx
+ asdfa axxx
+ xasdfa axxx
+ asxxdfa axxx
+ asxa;ofa axxx
+ asdfaqwer axxx
+ a axxxo
+ fa axxxo
+ dfa axxxo
+ sdfa axxxo
+ asdfa axxxo
+ xasdfa axxxo
+ asxxdfa axxxo
+ asxa;ofa axxxo
+ asdfaqwer axxxo
+ a axxxoi
+ fa axxxoi
+ dfa axxxoi
+ sdfa axxxoi
+ asdfa axxxoi
+ xasdfa axxxoi
+ asxxdfa axxxoi
+ asxa;ofa axxxoi
+ asdfaqwer axxxoi
+ a axxxoik
+ fa axxxoik
+ dfa axxxoik
+ sdfa axxxoik
+ asdfa axxxoik
+ xasdfa axxxoik
+ asxxdfa axxxoik
+ asxa;ofa axxxoik
+ asdfaqwer axxxoik
+ a axxxoike
+ fa axxxoike
+ dfa axxxoike
+ sdfa axxxoike
+ asdfa axxxoike
+ xasdfa axxxoike
+ asxxdfa axxxoike
+ asxa;ofa axxxoike
+ asdfaqwer axxxoike
+ a axxxoikey
+ fa axxxoikey
+ dfa axxxoikey
+ sdfa axxxoikey
+ asdfa axxxoikey
+ xasdfa axxxoikey
+ asxxdfa axxxoikey
+ asxa;ofa axxxoikey
+ asdfaqwer axxxoikey
+
+xxxxx xx xxxxxx
+xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx
+xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx
+xx xxxxxxx. xxxx xxxx.
+
+> xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx
+> xxxxxx xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx
+
+aa aa aa aa
+bb bb bb bb
+cc cc cc cc
diff --git a/src/testdir/test15.ok b/src/testdir/test15.ok
new file mode 100644
index 000000000..bc09f5e7d
--- /dev/null
+++ b/src/testdir/test15.ok
@@ -0,0 +1,111 @@
+test for :left
+a a
+fa a
+dfa a
+sdfa a
+asdfa a
+xasdfa a
+asxxdfa a
+
+ test for :center
+ a a
+ fa afd asdf
+ dfa a
+ sdfa afd asdf
+ asdfa a
+ xasdfa asdfasdfasdfasdfasdf
+ asxxdfa a
+
+ test for :right
+ a a
+ fa a
+ dfa a
+ sdfa a
+ asdfa a
+ xasdfa a
+ asxxdfa a
+ asxa;ofa a
+ asdfaqwer a
+ a ax
+ fa ax
+ dfa ax
+ sdfa ax
+ asdfa ax
+ xasdfa ax
+ asxxdfa ax
+ asxa;ofa ax
+ asdfaqwer ax
+ a axx
+ fa axx
+ dfa axx
+ sdfa axx
+ asdfa axx
+ xasdfa axx
+ asxxdfa axx
+ asxa;ofa axx
+ asdfaqwer axx
+ a axxx
+ fa axxx
+ dfa axxx
+ sdfa axxx
+ asdfa axxx
+ xasdfa axxx
+ asxxdfa axxx
+ asxa;ofa axxx
+ asdfaqwer axxx
+ a axxxo
+ fa axxxo
+ dfa axxxo
+ sdfa axxxo
+ asdfa axxxo
+ xasdfa axxxo
+ asxxdfa axxxo
+ asxa;ofa axxxo
+ asdfaqwer axxxo
+ a axxxoi
+ fa axxxoi
+ dfa axxxoi
+ sdfa axxxoi
+ asdfa axxxoi
+ xasdfa axxxoi
+ asxxdfa axxxoi
+ asxa;ofa axxxoi
+ asdfaqwer axxxoi
+ a axxxoik
+ fa axxxoik
+ dfa axxxoik
+ sdfa axxxoik
+ asdfa axxxoik
+ xasdfa axxxoik
+ asxxdfa axxxoik
+ asxa;ofa axxxoik
+ asdfaqwer axxxoik
+ a axxxoike
+ fa axxxoike
+ dfa axxxoike
+ sdfa axxxoike
+ asdfa axxxoike
+ xasdfa axxxoike
+ asxxdfa axxxoike
+ asxa;ofa axxxoike
+ asdfaqwer axxxoike
+ a axxxoikey
+ fa axxxoikey
+ dfa axxxoikey
+ sdfa axxxoikey
+ asdfa axxxoikey
+ xasdfa axxxoikey
+ asxxdfa axxxoikey
+ asxa;ofa axxxoikey
+ asdfaqwer axxxoikey
+
+xxxxx xx xxxxxx xxxxxxx xxxxxxxxx xxx xxxx xxxxx xxxxx xxx xx
+xxxxxxxxxxxxxxxxxx xxxxx xxxx, xxxx xxxx xxxx xxxx xxx xx xx xx xxxxxxx.
+xxxx xxxx.
+
+> xx xx, xxxx xxxx xxx xxxx xxx xxxxx xxx xxx xxxxxxx xxx xxxxx xxxxxx
+> xxxxxxx: xxxx xxxxxxx, xx xxxxxx xxxx xxxxxxxxxx
+
+aa aa aa aa
+bb bb bb bb
+cc cc cc cc
diff --git a/src/testdir/test16.in b/src/testdir/test16.in
new file mode 100644
index 000000000..7fc0d50cf
--- /dev/null
+++ b/src/testdir/test16.in
@@ -0,0 +1,10 @@
+Tests for resetting "secure" flag after GUI has started.
+
+STARTTEST
+:set exrc secure
+:gui -f
+:.,$w! test.out
+:qa!
+ENDTEST
+
+ just some text
diff --git a/src/testdir/test16.ok b/src/testdir/test16.ok
new file mode 100644
index 000000000..25e2eea5c
--- /dev/null
+++ b/src/testdir/test16.ok
@@ -0,0 +1,2 @@
+
+ just some text
diff --git a/src/testdir/test17.in b/src/testdir/test17.in
new file mode 100644
index 000000000..e59144ffb
--- /dev/null
+++ b/src/testdir/test17.in
@@ -0,0 +1,27 @@
+Tests for "gf" on ${VAR}
+
+STARTTEST
+:so small.vim
+:if has("ebcdic")
+: set isfname=@,240-249,/,.,-,_,+,,,$,:,~,{,}
+:else
+: set isfname=@,48-57,/,.,-,_,+,,,$,:,~,{,}
+:endif
+:if has("unix")
+:let $CDIR = "."
+/CDIR
+:else
+:if has("amiga")
+:let $TDIR = "/testdir"
+:else
+:let $TDIR = "."
+:endif
+/TDIR
+:endif
+gf
+:w! test.out
+:qa!
+ENDTEST
+
+ ${CDIR}/test17a.in
+ $TDIR/test17a.in
diff --git a/src/testdir/test17.ok b/src/testdir/test17.ok
new file mode 100644
index 000000000..58c3504ad
--- /dev/null
+++ b/src/testdir/test17.ok
@@ -0,0 +1,3 @@
+This file is just to test "gf" in test 17.
+The contents is not importent.
+Just testing!
diff --git a/src/testdir/test17a.in b/src/testdir/test17a.in
new file mode 100644
index 000000000..58c3504ad
--- /dev/null
+++ b/src/testdir/test17a.in
@@ -0,0 +1,3 @@
+This file is just to test "gf" in test 17.
+The contents is not importent.
+Just testing!
diff --git a/src/testdir/test18.in b/src/testdir/test18.in
new file mode 100644
index 000000000..9bfd92234
--- /dev/null
+++ b/src/testdir/test18.in
@@ -0,0 +1,16 @@
+Tests for not doing smart indenting when it isn't set.
+
+STARTTEST
+:so small.vim
+:set nocin nosi ai
+/some
+2cc#test
+:?start?,$w! test.out
+:qa!
+ENDTEST
+
+start text
+ some test text
+ test text
+test text
+ test text
diff --git a/src/testdir/test18.ok b/src/testdir/test18.ok
new file mode 100644
index 000000000..e71971378
--- /dev/null
+++ b/src/testdir/test18.ok
@@ -0,0 +1,4 @@
+start text
+ #test
+test text
+ test text
diff --git a/src/testdir/test19.in b/src/testdir/test19.in
new file mode 100644
index 000000000..0d9b421a2
--- /dev/null
+++ b/src/testdir/test19.in
@@ -0,0 +1,23 @@
+Tests for "r<Tab>" with 'smarttab' and 'expandtab' set/not set.
+
+STARTTEST
+:set smarttab expandtab ts=8 sw=4
+/some
+r :set noexpandtab
+/other
+r
+:" Test replacing with Tabs and then backspacing to undo it
+0wR 
+:" Test replacing with Tabs
+0wR 
+:?^start?,$w! test.out
+:qa!
+ENDTEST
+
+start text
+ some test text
+test text
+ other test text
+ a cde
+ f ghi
+test text
diff --git a/src/testdir/test19.ok b/src/testdir/test19.ok
new file mode 100644
index 000000000..ba4eb63be
--- /dev/null
+++ b/src/testdir/test19.ok
@@ -0,0 +1,7 @@
+start text
+ ome test text
+test text
+ ther test text
+ a cde
+ hi
+test text
diff --git a/src/testdir/test2.in b/src/testdir/test2.in
new file mode 100644
index 000000000..b7b5a5106
--- /dev/null
+++ b/src/testdir/test2.in
@@ -0,0 +1,29 @@
+
+This is a test if a URL is recognized by "gf", with the cursor before and
+after the "://". Also test ":\\".
+
+STARTTEST
+:so small.vim
+/^first
+/tmp
+:call append(0, expand("<cfile>"))
+/^second
+/URL
+:call append(1, expand("<cfile>"))
+:if has("ebcdic")
+: set isf=@,240-249,/,.,-,_,+,,,$,:,~,\
+:else
+: set isf=@,48-57,/,.,-,_,+,,,$,:,~,\
+:endif
+/^third
+/name
+:call append(2, expand("<cfile>"))
+/^fourth
+/URL
+:call append(3, expand("<cfile>"))
+5GdG:wq! test.out
+ENDTEST
+first test for URL://machine.name/tmp/vimtest2a and other text
+second test for URL://machine.name/tmp/vimtest2b. And other text
+third test for URL:\\machine.name\vimtest2c and other text
+fourth test for URL:\\machine.name\tmp\vimtest2d, and other text
diff --git a/src/testdir/test2.ok b/src/testdir/test2.ok
new file mode 100644
index 000000000..32978825f
--- /dev/null
+++ b/src/testdir/test2.ok
@@ -0,0 +1,4 @@
+URL://machine.name/tmp/vimtest2a
+URL://machine.name/tmp/vimtest2b
+URL:\\machine.name\vimtest2c
+URL:\\machine.name\tmp\vimtest2d
diff --git a/src/testdir/test20.in b/src/testdir/test20.in
new file mode 100644
index 000000000..7201c75c2
--- /dev/null
+++ b/src/testdir/test20.in
@@ -0,0 +1,22 @@
+Tests Blockwise Visual when there are TABs before the text.
+First test for undo working properly when executing commands from a register.
+Also test this in an empty buffer.
+
+STARTTEST
+:so tiny.vim
+G0"ay$k@au
+:new
+@auY:quit!
+GP
+/start here$
+jjlld
+:/here$/,$-1w! test.out
+:qa!
+ENDTEST
+
+test text test tex start here
+ some text
+ test text
+test text
+
+OxjAykdd
diff --git a/src/testdir/test20.ok b/src/testdir/test20.ok
new file mode 100644
index 000000000..2604e7cc8
--- /dev/null
+++ b/src/testdir/test20.ok
@@ -0,0 +1,6 @@
+test text test tex rt here
+ somext
+ tesext
+test text
+
+
diff --git a/src/testdir/test21.in b/src/testdir/test21.in
new file mode 100644
index 000000000..491b9f740
--- /dev/null
+++ b/src/testdir/test21.in
@@ -0,0 +1,19 @@
+Tests for [ CTRL-I with a count and CTRL-W CTRL-I with a count
+
+STARTTEST
+:so small.vim
+/start
+6[ :.w! test.out
+?start here
+6 :.w >>test.out
+:qa!
+ENDTEST
+
+#include test21.in
+
+/* test text test tex start here
+ some text
+ test text
+ start OK if found this line
+ start found wrong line
+test text
diff --git a/src/testdir/test21.ok b/src/testdir/test21.ok
new file mode 100644
index 000000000..d9f1b759c
--- /dev/null
+++ b/src/testdir/test21.ok
@@ -0,0 +1,2 @@
+ start OK if found this line
+ start OK if found this line
diff --git a/src/testdir/test22.in b/src/testdir/test22.in
new file mode 100644
index 000000000..f5cc046c6
--- /dev/null
+++ b/src/testdir/test22.in
@@ -0,0 +1,13 @@
+Tests for file with some lines ending in CTRL-M, some not
+
+STARTTEST
+:set ta tx
+:e!
+:$-3,$w! test.out
+:qa!
+ENDTEST
+
+this lines ends in a
+this one doesn't
+this one does
+and the last one doesn't
diff --git a/src/testdir/test22.ok b/src/testdir/test22.ok
new file mode 100644
index 000000000..38ff89eaf
--- /dev/null
+++ b/src/testdir/test22.ok
@@ -0,0 +1,4 @@
+this lines ends in a
+this one doesn't
+this one does
+and the last one doesn't
diff --git a/src/testdir/test23.in b/src/testdir/test23.in
new file mode 100644
index 000000000..0e0e60553
--- /dev/null
+++ b/src/testdir/test23.in
@@ -0,0 +1,15 @@
+Tests for complicated + argument to :edit command
+
+STARTTEST
+:$-1w! Xfile1
+:$w! Xfile2
+:edit +1|s/|/PIPE/|w Xfile1| e Xfile2|1 | s/\//SLASH/|w
+:w! test.out
+:e Xfile1
+:w >> test.out
+:qa!
+ENDTEST
+
+The result should be in Xfile1: "fooPIPEbar", in Xfile2: "fooSLASHbar"
+foo|bar
+foo/bar
diff --git a/src/testdir/test23.ok b/src/testdir/test23.ok
new file mode 100644
index 000000000..f1930abad
--- /dev/null
+++ b/src/testdir/test23.ok
@@ -0,0 +1,2 @@
+fooSLASHbar
+fooPIPEbar
diff --git a/src/testdir/test24.in b/src/testdir/test24.in
new file mode 100644
index 000000000..84721d992
--- /dev/null
+++ b/src/testdir/test24.in
@@ -0,0 +1,21 @@
+Tests for regexp with backslash and other special characters inside []
+
+STARTTEST
+:set nocompatible viminfo+=nviminfo
+/[\x]
+x/[\t\]]
+x/[]y]
+x/[\]]
+x/[y^]
+x/[$y]
+x:?start?,$w! test.out
+:qa!
+ENDTEST
+
+start
+test \text test text
+test text test text
+test text ]test text
+test ]text test text
+test text te^st text
+test te$xt test text
diff --git a/src/testdir/test24.ok b/src/testdir/test24.ok
new file mode 100644
index 000000000..896b50ae5
--- /dev/null
+++ b/src/testdir/test24.ok
@@ -0,0 +1,7 @@
+start
+test text test text
+test text test text
+test text test text
+test text test text
+test text test text
+test text test text
diff --git a/src/testdir/test25.in b/src/testdir/test25.in
new file mode 100644
index 000000000..4139865da
--- /dev/null
+++ b/src/testdir/test25.in
@@ -0,0 +1,31 @@
+Test for jumping to a tag with 'hidden' set, with symbolic link in path of tag.
+This only works for Unix, because of the symbolic link.
+
+STARTTEST
+:so small.vim
+:set hidden
+:" Create a link from test25.dir to the current directory.
+:!rm -f test25.dir
+:!ln -s . test25.dir
+:" Create tags.text, with the current directory name inserted.
+/tags line
+:r !pwd
+d$/test
+hP:.w! tags.test
+:" Try jumping to a tag in the current file, but with a path that contains a
+:" symbolic link. When wrong, this will give the ATTENTION message. The next
+:" space will then be eaten by hit-return, instead of moving the cursor to 'd'.
+:set tags=tags.test
+G x:.w! test.out
+:!rm -f test25.dir tags.test
+:qa!
+ENDTEST
+
+tags line:
+SECTION_OFF /test25.dir/test25.in /^#define SECTION_OFF 3$/
+
+/*tx.c*/
+#define SECTION_OFF 3
+#define NUM_SECTIONS 3
+
+SECTION_OFF
diff --git a/src/testdir/test25.ok b/src/testdir/test25.ok
new file mode 100644
index 000000000..08fc070b7
--- /dev/null
+++ b/src/testdir/test25.ok
@@ -0,0 +1 @@
+#efine SECTION_OFF 3
diff --git a/src/testdir/test26.in b/src/testdir/test26.in
new file mode 100644
index 000000000..df572c897
--- /dev/null
+++ b/src/testdir/test26.in
@@ -0,0 +1,43 @@
+Test for :execute, :while and :if
+
+STARTTEST
+:so small.vim
+mt:let i = 0
+:while i < 12
+: let i = i + 1
+: if has("ebcdic")
+: execute "normal o" . i . "\047"
+: else
+: execute "normal o" . i . "\033"
+: endif
+: if i % 2
+: normal Ax
+: if i == 9
+: break
+: endif
+: if i == 5
+: continue
+: else
+: let j = 9
+: while j > 0
+: if has("ebcdic")
+: execute "normal" j . "a" . j . "\x27"
+: else
+: execute "normal" j . "a" . j . "\x1b"
+: endif
+: let j = j - 1
+: endwhile
+: endif
+: endif
+: if i == 9
+: if has("ebcdic")
+: execute "normal Az\047"
+: else
+: execute "normal Az\033"
+: endif
+: endif
+:endwhile
+:'t,$w! test.out
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test26.ok b/src/testdir/test26.ok
new file mode 100644
index 000000000..bc4476118
--- /dev/null
+++ b/src/testdir/test26.ok
@@ -0,0 +1,10 @@
+
+1x999999999888888887777777666666555554444333221
+2
+3x999999999888888887777777666666555554444333221
+4
+5x
+6
+7x999999999888888887777777666666555554444333221
+8
+9x
diff --git a/src/testdir/test27.in b/src/testdir/test27.in
new file mode 100644
index 000000000..2df16d9ef
--- /dev/null
+++ b/src/testdir/test27.in
@@ -0,0 +1,20 @@
+Test for expanding file names
+
+STARTTEST
+:!mkdir Xdir1
+:!mkdir Xdir2
+:!mkdir Xdir3
+:cd Xdir3
+:!mkdir Xdir4
+:cd ..
+:w Xdir1/file
+:w Xdir3/Xdir4/file
+:n Xdir?/*/file
+Go%:.w! test.out
+:n! Xdir?/*/nofile
+Go%:.w >>test.out
+:e! xx
+:!rm -rf Xdir1 Xdir2 Xdir3
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test27.ok b/src/testdir/test27.ok
new file mode 100644
index 000000000..c35f2438a
--- /dev/null
+++ b/src/testdir/test27.ok
@@ -0,0 +1,2 @@
+Xdir3/Xdir4/file
+Xdir?/*/nofile
diff --git a/src/testdir/test28.in b/src/testdir/test28.in
new file mode 100644
index 000000000..5542c9266
--- /dev/null
+++ b/src/testdir/test28.in
Binary files differ
diff --git a/src/testdir/test28.ok b/src/testdir/test28.ok
new file mode 100644
index 000000000..911d85465
--- /dev/null
+++ b/src/testdir/test28.ok
@@ -0,0 +1,2 @@
+sd
+map __2 asdsecondsdsd0map __5 asd0fifth
diff --git a/src/testdir/test29.in b/src/testdir/test29.in
new file mode 100644
index 000000000..de93ccc22
--- /dev/null
+++ b/src/testdir/test29.in
@@ -0,0 +1,67 @@
+Test for joining lines with 'joinspaces' set or not
+
+STARTTEST
+:set nojoinspaces
+/firstline/
+jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:set joinspaces
+jJjJjJjJjJjJjJjJjJjJjJjJjJjJ:?firstline?+1,$w! test.out
+:qa!
+ENDTEST
+
+firstline
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf.
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
+asdfasdf
+asdf
diff --git a/src/testdir/test29.ok b/src/testdir/test29.ok
new file mode 100644
index 000000000..076f77c98
--- /dev/null
+++ b/src/testdir/test29.ok
@@ -0,0 +1,28 @@
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf. asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
+asdfasdf asdf
diff --git a/src/testdir/test3.in b/src/testdir/test3.in
new file mode 100644
index 000000000..cd725bffb
--- /dev/null
+++ b/src/testdir/test3.in
@@ -0,0 +1,1217 @@
+/* vim: set cin ts=4 sw=4 : */
+
+Test for 'cindent'
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:edit " read modeline
+/start of AUTO
+=/end of AUTO
+ENDTEST
+
+/* start of AUTO matically checked */
+{
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ }
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ else
+ }
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd;
+ }
+
+ if (test)
+ cmd;
+}
+
+{
+ if (test) {
+ cmd;
+ }
+
+ if (test) cmd;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ cmd3;
+ }
+}
+
+
+/* Test for 'cindent' do/while mixed with if/else: */
+
+{
+ do
+ if (asdf)
+ asdfasd;
+ while (cond);
+
+ do
+ if (asdf)
+ while (asdf)
+ asdf;
+ while (asdf);
+}
+
+/* Test for 'cindent' with two ) on a continuation line */
+{
+ if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
+ aal;sdkjf ( ;asldfkja;sldfk
+ al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
+ line up here;
+}
+
+
+/* C++ tests: */
+
+// foo() these three lines should remain in column 0
+// {
+// }
+
+/* Test for continuation and unterminated lines: */
+{
+ i = 99 + 14325 +
+ 21345 +
+ 21345 +
+ 21345 + ( 21345 +
+ 21345) +
+ 2345 +
+ 1234;
+ c = 1;
+}
+
+/*
+ testje for indent with empty line
+
+ here */
+
+{
+ if (testing &&
+ not a joke ||
+ line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ )line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ line up here))
+ hay;
+}
+
+
+{
+ switch (c)
+ {
+ case xx:
+ do
+ if (asdf)
+ do
+ asdfasdf;
+ while (asdf);
+ else
+ asdfasdf;
+ while (cond);
+ case yy:
+ case xx:
+ case zz:
+ testing;
+ }
+}
+
+{
+ if (cond) {
+ foo;
+ }
+ else
+ {
+ bar;
+ }
+}
+
+{
+ if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
+ alsdkfj (asldk;fj
+ awith cino=(0 ;lf this one goes to below the paren with ==
+ ;laksjfd ;lsakdjf ;alskdf asd)
+ asdfasdf;)))
+ asdfasdf;
+}
+
+ int
+func(a, b)
+ int a;
+ int c;
+{
+ if (c1 && (c2 ||
+ c3))
+ foo;
+ if (c1 &&
+ (c2 || c3)
+ )
+}
+
+{
+ while (asd)
+ {
+ if (asdf)
+ if (test)
+ if (that)
+ {
+ if (asdf)
+ do
+ cdasd;
+ while (as
+ df);
+ }
+ else
+ if (asdf)
+ asdf;
+ else
+ asdf;
+ asdf;
+ }
+}
+
+{
+ s = "/*"; b = ';'
+ s = "/*"; b = ';';
+ a = b;
+}
+
+{
+ switch (a)
+ {
+ case a:
+ switch (t)
+ {
+ case 1:
+ cmd;
+ break;
+ case 2:
+ cmd;
+ break;
+ }
+ cmd;
+ break;
+ case b:
+ {
+ int i;
+ cmd;
+ }
+ break;
+ case c: {
+ int i;
+ cmd;
+ }
+ case d: if (cond &&
+ test) { /* this line doesn't work right */
+ int i;
+ cmd;
+ }
+ break;
+ }
+}
+
+{
+ if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
+ (bp_to->b_p_initialized ||
+ (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
+ return;
+label :
+ asdf = asdf ?
+ asdf : asdf;
+ asdf = asdf ?
+ asdf: asdf;
+}
+
+/* Special Comments : This function has the added complexity (compared */
+/* : to addtolist) of having to check for a detail */
+/* : texture and add that to the list first. */
+
+char *(array[100]) = {
+ "testje",
+ "foo",
+ "bar",
+}
+
+enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+typedef enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+{
+ int a,
+ b;
+}
+
+{
+ struct Type
+ {
+ int i;
+ char *str;
+ } var[] =
+ {
+ 0, "zero",
+ 1, "one",
+ 2, "two",
+ 3, "three"
+ };
+
+ float matrix[3][3] =
+ {
+ {
+ 0,
+ 1,
+ 2
+ },
+ {
+ 3,
+ 4,
+ 5
+ },
+ {
+ 6,
+ 7,
+ 8
+ }
+ };
+}
+
+{
+ /* blah ( blah */
+ /* where does this go? */
+
+ /* blah ( blah */
+ cmd;
+
+ func(arg1,
+ /* comment */
+ arg2);
+ a;
+ {
+ b;
+ {
+ c; /* Hey, NOW it indents?! */
+ }
+ }
+
+ {
+ func(arg1,
+ arg2,
+ arg3);
+ /* Hey, what am I doing here? Is this coz of the ","? */
+ }
+}
+
+main ()
+{
+ if (cond)
+ {
+ a = b;
+ }
+ if (cond) {
+ a = c;
+ }
+ if (cond)
+ a = d;
+ return;
+}
+
+{
+ case 2: if (asdf &&
+ asdfasdf)
+ aasdf;
+ a = 9;
+ case 3: if (asdf)
+ aasdf;
+ a = 9;
+ case 4: x = 1;
+ y = 2;
+
+label: if (asdf)
+ here;
+
+label: if (asdf &&
+ asdfasdf)
+ {
+ }
+
+label: if (asdf &&
+ asdfasdf) {
+ there;
+ }
+
+label: if (asdf &&
+ asdfasdf)
+ there;
+}
+
+{
+ /*
+ hello with ":set comments= cino=c5"
+ */
+
+ /*
+ hello with ":set comments= cino="
+ */
+}
+
+
+{
+ if (a < b) {
+ a = a + 1;
+ } else
+ a = a + 2;
+
+ if (a)
+ do {
+ testing;
+ } while (asdfasdf);
+ a = b + 1;
+ asdfasdf
+}
+
+class bob
+{
+ int foo() {return 1;}
+ int bar;
+}
+
+main()
+{
+while(1)
+if (foo)
+{
+bar;
+}
+else {
+asdf;
+}
+misplacedline;
+}
+
+{
+ if (clipboard.state == SELECT_DONE
+ && ((row == clipboard.start.lnum
+ && col >= clipboard.start.col)
+ || row > clipboard.start.lnum))
+}
+
+{
+if (1) {i += 4;}
+where_am_i;
+return 0;
+}
+
+{
+{
+} // sdf(asdf
+if (asdf)
+asd;
+}
+
+{
+label1:
+label2:
+}
+
+{
+int fooRet = foo(pBar1, false /*fKB*/,
+ true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
+f() {
+for ( i = 0;
+ i < m;
+ /* c */ i++ ) {
+a = b;
+}
+}
+}
+
+{
+ f1(/*comment*/);
+ f2();
+}
+
+{
+do {
+if (foo) {
+} else
+;
+} while (foo);
+foo(); // was wrong
+}
+
+int x; // no extra indent because of the ;
+void func()
+{
+}
+
+char *tab[] = {"aaa",
+ "};", /* }; */ NULL}
+ int indented;
+{}
+
+char *a[] = {"aaa", "bbb",
+ "ccc", NULL};
+// here
+
+char *tab[] = {"aaa",
+ "xx", /* xx */}; /* asdf */
+int not_indented;
+
+{
+ do {
+ switch (bla)
+ {
+ case 1: if (foo)
+ bar;
+ }
+ } while (boo);
+ wrong;
+}
+
+int foo,
+ bar;
+int foo;
+
+#if defined(foo) \
+ && defined(bar)
+char * xx = "asdf\
+ foo\
+ bor";
+int x;
+
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+
+void f()
+{
+#if defined(foo) \
+ && defined(bar)
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ {
+ int i;
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ }
+#endif
+}
+#endif
+
+int y; // comment
+ // comment
+
+ // comment
+
+{
+ Constructor(int a,
+ int b ) : BaseClass(a)
+ {
+ }
+}
+
+void foo()
+{
+ char one,
+ two;
+ struct bla piet,
+ jan;
+ enum foo kees,
+ jannie;
+ static unsigned sdf,
+ krap;
+ unsigned int piet,
+ jan;
+ int
+ kees,
+ jan;
+}
+
+{
+ t(int f,
+ int d); // )
+ d();
+}
+
+Constructor::Constructor(int a,
+ int b
+ ) :
+ BaseClass(a,
+ b,
+ c),
+ mMember(b),
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) :
+ BaseClass(a)
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) /*x*/ : /*x*/ BaseClass(a),
+ member(b)
+{
+}
+
+class CAbc :
+ public BaseClass1,
+ protected BaseClass2
+{
+ int Test() { return FALSE; }
+ int Test1() { return TRUE; }
+
+ CAbc(int a, int b ) :
+ BaseClass(a)
+ {
+ switch(xxx)
+ {
+ case abc:
+ asdf();
+ break;
+
+ case 999:
+ baer();
+ break;
+ }
+ }
+
+public: // <-- this was incoreectly indented before!!
+ void testfall();
+protected:
+ void testfall();
+};
+
+class CAbc : public BaseClass1,
+ protected BaseClass2
+{
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ {
+ 123,
+ 456
+ },
+ {
+ 123,
+ 456
+ }
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ { 123, 456 },
+ { 123, 456 }
+};
+
+void asdf() /* ind_maxparen may cause trouble here */
+{
+ if ((0
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1)) break;
+}
+
+/* end of AUTO */
+
+STARTTEST
+:set tw=0 wm=60 columns=80 noai fo=croq
+/serious/e
+a about life, the universe, and the rest
+ENDTEST
+
+{
+
+/* this is
+ * a real serious important big
+ * comment
+ */
+ /* insert " about life, the universe, and the rest" after "serious" */
+}
+
+STARTTEST
+:set nocin
+/comments
+joabout life/happens
+jothere/below
+oline/this
+Ohello
+ENDTEST
+
+{
+ /*
+ * Testing for comments, without 'cin' set
+ */
+
+/*
+* what happens here?
+*/
+
+ /*
+ the end of the comment, try inserting a line below */
+
+ /* how about
+ this one */
+}
+
+STARTTEST
+:set cin
+/vec2
+==
+ENDTEST
+
+{
+ var = this + that + vec[0] * vec[0]
+ + vec[1] * vec[1]
+ + vec2[2] * vec[2];
+}
+
+STARTTEST
+:set cin
+:set cino=}4
+/testing1
+k2==/testing2
+k2==
+ENDTEST
+
+{
+ asdf asdflkajds f;
+ if (tes & ting) {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing1;
+ if (tes & ting)
+ {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing2;
+}
+
+STARTTEST
+:set cin
+:set cino=(0,)20
+/main
+=][
+ENDTEST
+
+main ( int first_par, /*
+ * Comment for
+ * first par
+ */
+ int second_par /*
+ * Comment for
+ * second par
+ */
+ )
+{
+ func( first_par, /*
+ * Comment for
+ * first par
+ */
+ second_par /*
+ * Comment for
+ * second par
+ */
+ );
+
+}
+
+STARTTEST
+:set cin
+:set cino=
+]]=][
+ENDTEST
+
+{
+ do
+ {
+ if ()
+ {
+ if ()
+ asdf;
+ else
+ asdf;
+ }
+ } while ();
+ cmd; /* this should go under the } */
+}
+
+STARTTEST
+]]=][
+ENDTEST
+
+void f()
+{
+ if ( k() ) {
+ l();
+
+ } else { /* Start (two words) end */
+ m();
+ }
+
+ n();
+}
+
+STARTTEST
+:set cino={s,e-s
+]]=][
+ENDTEST
+
+void f()
+{
+ if ( k() )
+ {
+ l();
+ } else { /* Start (two words) end */
+ m();
+ }
+ n(); /* should be under the if () */
+}
+
+STARTTEST
+:set cino={s,fs
+]]=/ foo
+ENDTEST
+
+void bar(void)
+{
+ static array[2][2] =
+ {
+ { 1, 2 },
+ { 3, 4 },
+ }
+
+ while (a)
+ {
+ foo(&a);
+ }
+
+ {
+ int a;
+ {
+ a = a + 1;
+ }
+ }
+ b = a;
+ }
+
+void func(void)
+ {
+ a = 1;
+ {
+ b = 2;
+ }
+ c = 3;
+ d = 4;
+ }
+/* foo */
+
+STARTTEST
+:set cino=
+/while
+ohere
+ENDTEST
+
+a()
+{
+ do {
+ a = a +
+ a;
+ } while ( a ); /* add text under this line */
+ if ( a )
+ a;
+}
+
+STARTTEST
+:set cino= com=
+/comment
+olabel2: b(); label3 /* post */: /* pre */ label4: f(/*com*/); if (/*com*/) cmd();
+ENDTEST
+
+a()
+{
+label1:
+ /* hmm */
+ // comment
+}
+
+STARTTEST
+:set comments& comments^=s:/*,m:**,ex:*/
+/simple
+=5j
+ENDTEST
+
+/*
+ * A simple comment
+ */
+
+/*
+ ** A different comment
+ */
+
+STARTTEST
+:set cino=c0
+:set comments& comments-=s1:/* comments^=s0:/*
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+
+ /*********
+ A comment.
+*********/
+}
+
+STARTTEST
+:set cino=c0,C1
+:set comments& comments-=s1:/* comments^=s0:/*
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+
+ /*********
+ A comment.
+*********/
+}
+
+STARTTEST
+:set cino=
+]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(s
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(s,U1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+STARTTEST
+:set cino=(0
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+STARTTEST
+:set cino=(0,w1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+STARTTEST
+:set cino=(s
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+STARTTEST
+:set cino=(s,m1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+STARTTEST
+:set cino=b1
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ switch (x)
+ {
+ case 1:
+ a = b;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+}
+
+STARTTEST
+:set cino=(0,W5
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ invokeme(
+ argu,
+ ment);
+ invokeme(
+ argu,
+ ment
+ );
+ invokeme(argu,
+ ment
+ );
+}
+
+STARTTEST
+:set cino=/6
+2kdd]]=][
+ENDTEST
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+STARTTEST
+:set cino=
+2kdd]]/comment 1/+1
+==
+ENDTEST
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+STARTTEST
+:set cino=g0
+2kdd]]=][
+ENDTEST
+
+class CAbc
+{
+ int Test() { return FALSE; }
+
+public: // comment
+ void testfall();
+protected:
+ void testfall();
+};
+
+STARTTEST
+:set cino=(0,W2s
+2kdd]]=][
+ENDTEST
+
+{
+ averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
+ asdasdf,
+ func(asdf,
+ asdfadsf),
+ asdfasdf
+ );
+
+ /* those are ugly, but consequent */
+
+ func()->asd(asdasdf,
+ averylongfunctionname(
+ abc,
+ dec)->averylongfunctionname(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf
+ ),
+ asdasdf
+ );
+
+ averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
+ abc,
+ dec)->asdfasdfasdf(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf),
+ asdasdf
+ );
+}
+
+STARTTEST
+:g/^STARTTEST/.,/^ENDTEST/d
+:1;/start of AUTO/,$wq! test.out
+ENDTEST
diff --git a/src/testdir/test3.ok b/src/testdir/test3.ok
new file mode 100644
index 000000000..570f8f63d
--- /dev/null
+++ b/src/testdir/test3.ok
@@ -0,0 +1,1090 @@
+/* start of AUTO matically checked */
+{
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ }
+}
+
+{
+ if (test)
+ {
+ cmd1;
+ else
+ }
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ cmd2;
+}
+
+{
+ while (this)
+ if (test)
+ cmd1;
+ else
+ cmd2;
+}
+
+{
+ if (test)
+ {
+ cmd;
+ }
+
+ if (test)
+ cmd;
+}
+
+{
+ if (test) {
+ cmd;
+ }
+
+ if (test) cmd;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+}
+
+{
+ cmd1;
+ for (blah)
+ while (this)
+ if (test)
+ cmd2;
+ cmd3;
+
+ if (test)
+ {
+ cmd1;
+ cmd2;
+ cmd3;
+ }
+}
+
+
+/* Test for 'cindent' do/while mixed with if/else: */
+
+{
+ do
+ if (asdf)
+ asdfasd;
+ while (cond);
+
+ do
+ if (asdf)
+ while (asdf)
+ asdf;
+ while (asdf);
+}
+
+/* Test for 'cindent' with two ) on a continuation line */
+{
+ if (asdfasdf;asldkfj asdlkfj as;ldkfj sal;d
+ aal;sdkjf ( ;asldfkja;sldfk
+ al;sdjfka ;slkdf ) sa;ldkjfsa dlk;)
+ line up here;
+}
+
+
+/* C++ tests: */
+
+// foo() these three lines should remain in column 0
+// {
+// }
+
+/* Test for continuation and unterminated lines: */
+{
+ i = 99 + 14325 +
+ 21345 +
+ 21345 +
+ 21345 + ( 21345 +
+ 21345) +
+ 2345 +
+ 1234;
+ c = 1;
+}
+
+/*
+ testje for indent with empty line
+
+ here */
+
+{
+ if (testing &&
+ not a joke ||
+ line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ )line up here)
+ hay;
+ if (testing &&
+ (not a joke || testing
+ line up here))
+ hay;
+}
+
+
+{
+ switch (c)
+ {
+ case xx:
+ do
+ if (asdf)
+ do
+ asdfasdf;
+ while (asdf);
+ else
+ asdfasdf;
+ while (cond);
+ case yy:
+ case xx:
+ case zz:
+ testing;
+ }
+}
+
+{
+ if (cond) {
+ foo;
+ }
+ else
+ {
+ bar;
+ }
+}
+
+{
+ if (alskdfj ;alsdkfjal;skdjf (;sadlkfsa ;dlkf j;alksdfj ;alskdjf
+ alsdkfj (asldk;fj
+ awith cino=(0 ;lf this one goes to below the paren with ==
+ ;laksjfd ;lsakdjf ;alskdf asd)
+ asdfasdf;)))
+ asdfasdf;
+}
+
+ int
+func(a, b)
+ int a;
+ int c;
+{
+ if (c1 && (c2 ||
+ c3))
+ foo;
+ if (c1 &&
+ (c2 || c3)
+ )
+}
+
+{
+ while (asd)
+ {
+ if (asdf)
+ if (test)
+ if (that)
+ {
+ if (asdf)
+ do
+ cdasd;
+ while (as
+ df);
+ }
+ else
+ if (asdf)
+ asdf;
+ else
+ asdf;
+ asdf;
+ }
+}
+
+{
+ s = "/*"; b = ';'
+ s = "/*"; b = ';';
+ a = b;
+}
+
+{
+ switch (a)
+ {
+ case a:
+ switch (t)
+ {
+ case 1:
+ cmd;
+ break;
+ case 2:
+ cmd;
+ break;
+ }
+ cmd;
+ break;
+ case b:
+ {
+ int i;
+ cmd;
+ }
+ break;
+ case c: {
+ int i;
+ cmd;
+ }
+ case d: if (cond &&
+ test) { /* this line doesn't work right */
+ int i;
+ cmd;
+ }
+ break;
+ }
+}
+
+{
+ if (!(vim_strchr(p_cpo, CPO_BUFOPTGLOB) != NULL && entering) &&
+ (bp_to->b_p_initialized ||
+ (!entering && vim_strchr(p_cpo, CPO_BUFOPT) != NULL)))
+ return;
+label :
+ asdf = asdf ?
+ asdf : asdf;
+ asdf = asdf ?
+ asdf: asdf;
+}
+
+/* Special Comments : This function has the added complexity (compared */
+/* : to addtolist) of having to check for a detail */
+/* : texture and add that to the list first. */
+
+char *(array[100]) = {
+ "testje",
+ "foo",
+ "bar",
+}
+
+enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+typedef enum soppie
+{
+ yes = 0,
+ no,
+ maybe
+};
+
+{
+ int a,
+ b;
+}
+
+{
+ struct Type
+ {
+ int i;
+ char *str;
+ } var[] =
+ {
+ 0, "zero",
+ 1, "one",
+ 2, "two",
+ 3, "three"
+ };
+
+ float matrix[3][3] =
+ {
+ {
+ 0,
+ 1,
+ 2
+ },
+ {
+ 3,
+ 4,
+ 5
+ },
+ {
+ 6,
+ 7,
+ 8
+ }
+ };
+}
+
+{
+ /* blah ( blah */
+ /* where does this go? */
+
+ /* blah ( blah */
+ cmd;
+
+ func(arg1,
+ /* comment */
+ arg2);
+ a;
+ {
+ b;
+ {
+ c; /* Hey, NOW it indents?! */
+ }
+ }
+
+ {
+ func(arg1,
+ arg2,
+ arg3);
+ /* Hey, what am I doing here? Is this coz of the ","? */
+ }
+}
+
+main ()
+{
+ if (cond)
+ {
+ a = b;
+ }
+ if (cond) {
+ a = c;
+ }
+ if (cond)
+ a = d;
+ return;
+}
+
+{
+ case 2: if (asdf &&
+ asdfasdf)
+ aasdf;
+ a = 9;
+ case 3: if (asdf)
+ aasdf;
+ a = 9;
+ case 4: x = 1;
+ y = 2;
+
+label: if (asdf)
+ here;
+
+label: if (asdf &&
+ asdfasdf)
+ {
+ }
+
+label: if (asdf &&
+ asdfasdf) {
+ there;
+ }
+
+label: if (asdf &&
+ asdfasdf)
+ there;
+}
+
+{
+ /*
+ hello with ":set comments= cino=c5"
+ */
+
+ /*
+ hello with ":set comments= cino="
+ */
+}
+
+
+{
+ if (a < b) {
+ a = a + 1;
+ } else
+ a = a + 2;
+
+ if (a)
+ do {
+ testing;
+ } while (asdfasdf);
+ a = b + 1;
+ asdfasdf
+}
+
+class bob
+{
+ int foo() {return 1;}
+ int bar;
+}
+
+main()
+{
+ while(1)
+ if (foo)
+ {
+ bar;
+ }
+ else {
+ asdf;
+ }
+ misplacedline;
+}
+
+{
+ if (clipboard.state == SELECT_DONE
+ && ((row == clipboard.start.lnum
+ && col >= clipboard.start.col)
+ || row > clipboard.start.lnum))
+}
+
+{
+ if (1) {i += 4;}
+ where_am_i;
+ return 0;
+}
+
+{
+ {
+ } // sdf(asdf
+ if (asdf)
+ asd;
+}
+
+{
+label1:
+label2:
+}
+
+{
+ int fooRet = foo(pBar1, false /*fKB*/,
+ true /*fPTB*/, 3 /*nT*/, false /*fDF*/);
+ f() {
+ for ( i = 0;
+ i < m;
+ /* c */ i++ ) {
+ a = b;
+ }
+ }
+}
+
+{
+ f1(/*comment*/);
+ f2();
+}
+
+{
+ do {
+ if (foo) {
+ } else
+ ;
+ } while (foo);
+ foo(); // was wrong
+}
+
+int x; // no extra indent because of the ;
+void func()
+{
+}
+
+char *tab[] = {"aaa",
+ "};", /* }; */ NULL}
+ int indented;
+{}
+
+char *a[] = {"aaa", "bbb",
+ "ccc", NULL};
+// here
+
+char *tab[] = {"aaa",
+ "xx", /* xx */}; /* asdf */
+int not_indented;
+
+{
+ do {
+ switch (bla)
+ {
+ case 1: if (foo)
+ bar;
+ }
+ } while (boo);
+ wrong;
+}
+
+int foo,
+ bar;
+int foo;
+
+#if defined(foo) \
+ && defined(bar)
+char * xx = "asdf\
+ foo\
+ bor";
+int x;
+
+char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+
+void f()
+{
+#if defined(foo) \
+ && defined(bar)
+ char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ {
+ int i;
+ char *foo = "asdf\
+ asdf\
+ asdf",
+ *bar;
+ }
+#endif
+}
+#endif
+
+int y; // comment
+// comment
+
+// comment
+
+{
+ Constructor(int a,
+ int b ) : BaseClass(a)
+ {
+ }
+}
+
+void foo()
+{
+ char one,
+ two;
+ struct bla piet,
+ jan;
+ enum foo kees,
+ jannie;
+ static unsigned sdf,
+ krap;
+ unsigned int piet,
+ jan;
+ int
+ kees,
+ jan;
+}
+
+{
+ t(int f,
+ int d); // )
+ d();
+}
+
+Constructor::Constructor(int a,
+ int b
+ ) :
+ BaseClass(a,
+ b,
+ c),
+ mMember(b),
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) :
+ BaseClass(a)
+{
+}
+
+Constructor::Constructor(int a,
+ int b ) /*x*/ : /*x*/ BaseClass(a),
+ member(b)
+{
+}
+
+class CAbc :
+ public BaseClass1,
+ protected BaseClass2
+{
+ int Test() { return FALSE; }
+ int Test1() { return TRUE; }
+
+ CAbc(int a, int b ) :
+ BaseClass(a)
+ {
+ switch(xxx)
+ {
+ case abc:
+ asdf();
+ break;
+
+ case 999:
+ baer();
+ break;
+ }
+ }
+
+ public: // <-- this was incoreectly indented before!!
+ void testfall();
+ protected:
+ void testfall();
+};
+
+class CAbc : public BaseClass1,
+ protected BaseClass2
+{
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ {
+ 123,
+ 456
+ },
+ {
+ 123,
+ 456
+ }
+};
+
+static struct
+{
+ int a;
+ int b;
+} variable[COUNT] =
+{
+ { 123, 456 },
+ { 123, 456 }
+};
+
+void asdf() /* ind_maxparen may cause trouble here */
+{
+ if ((0
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1
+ && 1)) break;
+}
+
+/* end of AUTO */
+
+
+{
+
+/* this is
+ * a real serious
+ * about life, the
+ * universe, and the
+ * rest important big
+ * comment
+ */
+ /* insert " about life, the universe, and the rest" after "serious" */
+}
+
+
+{
+ /*
+ * Testing for comments, without 'cin' set
+ */
+about life
+
+/*
+* what happens here?
+*/
+there
+
+ /*
+ the end of the comment, try inserting a line below */
+line
+
+ /* how about
+hello
+ this one */
+}
+
+
+{
+ var = this + that + vec[0] * vec[0]
+ + vec[1] * vec[1]
+ + vec2[2] * vec[2];
+}
+
+
+{
+ asdf asdflkajds f;
+ if (tes & ting) {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing1;
+ if (tes & ting)
+ {
+ asdf asdf asdf ;
+ asdfa sdf asdf;
+ }
+ testing2;
+}
+
+
+main ( int first_par, /*
+ * Comment for
+ * first par
+ */
+ int second_par /*
+ * Comment for
+ * second par
+ */
+ )
+{
+ func( first_par, /*
+ * Comment for
+ * first par
+ */
+ second_par /*
+ * Comment for
+ * second par
+ */
+ );
+
+}
+
+
+{
+ do
+ {
+ if ()
+ {
+ if ()
+ asdf;
+ else
+ asdf;
+ }
+ } while ();
+ cmd; /* this should go under the } */
+}
+
+
+void f()
+{
+ if ( k() ) {
+ l();
+
+ } else { /* Start (two words) end */
+ m();
+ }
+
+ n();
+}
+
+
+void f()
+ {
+ if ( k() )
+ {
+ l();
+ } else { /* Start (two words) end */
+ m();
+ }
+ n(); /* should be under the if () */
+}
+
+
+void bar(void)
+ {
+ static array[2][2] =
+ {
+ { 1, 2 },
+ { 3, 4 },
+ }
+
+ while (a)
+ {
+ foo(&a);
+ }
+
+ {
+ int a;
+ {
+ a = a + 1;
+ }
+ }
+ b = a;
+ }
+
+void func(void)
+ {
+ a = 1;
+ {
+ b = 2;
+ }
+ c = 3;
+ d = 4;
+ }
+/* foo */
+
+
+a()
+{
+ do {
+ a = a +
+ a;
+ } while ( a ); /* add text under this line */
+ here
+ if ( a )
+ a;
+}
+
+
+a()
+{
+label1:
+ /* hmm */
+ // comment
+label2: b();
+label3 /* post */:
+/* pre */ label4:
+ f(/*com*/);
+ if (/*com*/)
+ cmd();
+}
+
+
+/*
+ * A simple comment
+ */
+
+/*
+** A different comment
+*/
+
+
+void f()
+{
+
+ /*********
+ A comment.
+ *********/
+}
+
+
+void f()
+{
+
+ /*********
+ A comment.
+ *********/
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ c = c1 &&
+ (
+ c2 ||
+ c3
+ ) && c4;
+}
+
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+
+void f()
+{
+ if ( c1
+ && ( c2
+ || c3))
+ foo;
+}
+
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+
+void f()
+{
+ c = c1 && (
+ c2 ||
+ c3
+ ) && c4;
+ if (
+ c1 && c2
+ )
+ foo;
+}
+
+
+void f()
+{
+ switch (x)
+ {
+ case 1:
+ a = b;
+ break;
+ default:
+ a = 0;
+ break;
+ }
+}
+
+
+void f()
+{
+ invokeme(
+ argu,
+ ment);
+ invokeme(
+ argu,
+ ment
+ );
+ invokeme(argu,
+ ment
+ );
+}
+
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+
+void f()
+{
+ statement;
+ // comment 1
+ // comment 2
+}
+
+
+class CAbc
+{
+ int Test() { return FALSE; }
+
+public: // comment
+ void testfall();
+protected:
+ void testfall();
+};
+
+
+{
+ averylongfunctionnamelongfunctionnameaverylongfunctionname()->asd(
+ asdasdf,
+ func(asdf,
+ asdfadsf),
+ asdfasdf
+ );
+
+ /* those are ugly, but consequent */
+
+ func()->asd(asdasdf,
+ averylongfunctionname(
+ abc,
+ dec)->averylongfunctionname(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf
+ ),
+ asdasdf
+ );
+
+ averylongfunctionnameaverylongfunctionnameavery()->asd(fasdf(
+ abc,
+ dec)->asdfasdfasdf(
+ asdfadsf,
+ asdfasdf,
+ asdfasdf,
+ ),
+ func(asdfadf,
+ asdfasdf),
+ asdasdf
+ );
+}
+
diff --git a/src/testdir/test30.in b/src/testdir/test30.in
new file mode 100644
index 000000000..4e92741c8
--- /dev/null
+++ b/src/testdir/test30.in
@@ -0,0 +1,183 @@
+Test for a lot of variations of the 'fileformats' option
+
+STARTTEST
+:so small.vim
+:" first write three test files, one in each format
+:set fileformat=unix
+:set fileformats=
+:/^1/w! XX1
+:/^2/w! XX2
+:/^3/w! XX3
+:/^4/w! XX4
+:/^5/w! XX5
+:/^6/w! XX6
+:/^7/w! XX7
+:/^8/w! XX8
+:/^9/w! XX9
+:/^10/w! XX10
+:/^unix/;/eof/-1w! XXUnix
+:/^dos/;/eof/-1w! XXDos
+:set bin noeol
+:$w! XXMac
+:set nobin eol
+:bwipe XXUnix XXDos XXMac
+:" create mixed format files
+:!cat XXUnix XXDos >XXUxDs
+:!cat XXUnix XXMac >XXUxMac
+:!cat XXDos XXMac >XXDosMac
+:!cat XXUnix XXDos XXMac >XXUxDsMc
+:"
+:" try reading and writing with 'fileformats' empty
+:set fileformat=unix
+:e! XXUnix
+:w! test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX1 >>test.out
+:bwipe XXUnix XXDos XXMac
+:set fileformat=dos
+:e! XXUnix
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX2 >>test.out
+:bwipe XXUnix XXDos XXMac
+:set fileformat=mac
+:e! XXUnix
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXDos
+:w! XXtt
+:!cat XXtt >>test.out
+:e! XXMac
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX3 >>test.out
+:bwipe XXUnix XXDos XXMac
+:"
+:" try reading and writing with 'fileformats' set to one format
+:set fileformats=unix
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX4 >>test.out
+:"
+:" try reading and writing with 'fileformats' set to two formats
+:set fileformats=unix,dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:e! XXUxMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxMac
+:e! XXDosMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXDosMac
+:!cat XX5 >>test.out
+:set fileformats=unix,mac
+:e! XXUxDs
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDs
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:e! XXDosMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXDosMac
+:!cat XX6 >>test.out
+:set fileformats=dos,mac
+:e! XXUxDs
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDs
+:e! XXUxMac
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxMac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX7 >>test.out
+:"
+:" try reading and writing with 'fileformats' set to three formats
+:set fileformats=unix,dos,mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX8 >>test.out
+:set fileformats=mac,dos,unix
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:!cat XX9 >>test.out
+:" try with 'binary' set
+:set fileformats=mac,unix,dos
+:set binary
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=mac
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:bwipe XXUxDsMc
+:set fileformats=dos
+:e! XXUxDsMc
+:w! XXtt
+:!cat XXtt >>test.out
+:!cat XX10 >>test.out
+:" add a newline at the end
+:!cat XXUnix >>test.out
+:qa!
+ENDTEST
+
+1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+
+unix
+unix
+eof
+
+dos
+dos
+eof
+
+mac mac
diff --git a/src/testdir/test30.ok b/src/testdir/test30.ok
new file mode 100644
index 000000000..c294483bd
--- /dev/null
+++ b/src/testdir/test30.ok
@@ -0,0 +1,96 @@
+unix
+unix
+dos
+dos
+mac mac
+1
+unix
+unix
+dos
+dos
+mac mac
+2
+unix
+unix
+ dos
+dos
+ mac mac 3
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+dos
+dos
+mac mac 4
+unix
+unix
+dos
+dos
+mac mac
+unix
+unix
+mac mac
+dos
+dos
+mac mac
+5
+unix
+unix
+dos
+dos
+unix
+unix
+dos
+dos
+mac mac
+dos
+dos
+mac mac 6
+unix
+unix
+dos
+dos
+unix
+unix
+mac mac
+unix
+unix
+dos
+dos
+mac mac
+7
+unix
+unix
+dos
+dos
+mac mac
+8
+unix
+unix
+dos
+dos
+mac mac
+9
+unix
+unix
+dos
+dos
+mac mac unix
+unix
+dos
+dos
+mac mac unix
+unix
+dos
+dos
+mac mac 10
+unix
+unix
diff --git a/src/testdir/test31.in b/src/testdir/test31.in
new file mode 100644
index 000000000..cd4d08e81
--- /dev/null
+++ b/src/testdir/test31.in
@@ -0,0 +1,68 @@
+Test for commands that close windows and/or buffers:
+:quit
+:close
+:hide
+:only
+:sall
+:all
+:ball
+:buf
+:edit
+
+STARTTEST
+:so tiny.vim
+GA 1:$w! Xtest1
+$r2:$w! Xtest2
+$r3:$w! Xtest3
+:n! Xtest1 Xtest2
+A 1:set hidden
+:" test for working :n when hidden set; write "testtext 2"
+:n
+:w! test.out
+:" test for failing :rew when hidden not set; write "testtext 2 2"
+:set nohidden
+A 2:rew
+:w >>test.out
+:" test for working :rew when hidden set; write "testtext 1 1"
+:set hidden
+:rew
+:w >>test.out
+:" test for :all keeping a buffer when it's modified; write "testtext 1 1 1"
+:set nohidden
+A 1:sp
+:n Xtest2 Xtest3
+:all
+:w >>test.out
+:" test abandoning changed buffer, should be unloaded even when 'hidden' set
+:" write "testtext 2 2" twice
+:set hidden
+A 1:q!
+:w >>test.out
+:unhide
+:w >>test.out
+:" test ":hide" hides anyway when 'hidden' not set; write "testtext 3"
+:set nohidden
+A 2:hide
+:w >>test.out
+:" test ":edit" failing in modified buffer when 'hidden' not set
+:" write "testtext 3 3"
+A 3:e Xtest1
+:w >>test.out
+:" test ":edit" working in modified buffer when 'hidden' set; write "testtext 1"
+:set hidden
+:e Xtest1
+:w >>test.out
+:" test ":close" not hiding when 'hidden' not set in modified buffer;
+:" write "testtext 3 3 3"
+:sp Xtest3
+:set nohidden
+A 3:close
+:w >>test.out
+:" test ":close!" does hide when 'hidden' not set in modified buffer;
+:" write "testtext 1"
+A 3:close!
+:w >>test.out
+:qa!
+ENDTEST
+
+testtext
diff --git a/src/testdir/test31.ok b/src/testdir/test31.ok
new file mode 100644
index 000000000..3311ad5df
--- /dev/null
+++ b/src/testdir/test31.ok
@@ -0,0 +1,11 @@
+testtext 2
+testtext 2 2
+testtext 1 1
+testtext 1 1 1
+testtext 2 2
+testtext 2 2
+testtext 3
+testtext 3 3
+testtext 1
+testtext 3 3 3
+testtext 1
diff --git a/src/testdir/test32.in b/src/testdir/test32.in
new file mode 100644
index 000000000..0d5405184
--- /dev/null
+++ b/src/testdir/test32.in
@@ -0,0 +1,56 @@
+Test for insert expansion
+
+:se cpt=.,w
+* add-expands (word from next line) from other window
+* add-expands (current buffer first)
+* Local expansion, ends in an empty line (unless it becomes a global expansion)
+* starts Local and switches to global add-expansion
+:se cpt=.,w,i
+* i-add-expands and switches to local
+* add-expands lines (it would end in an empty line if it didn't ignored it self)
+:se cpt=kXtestfile
+* checks k-expansion, and file expansion (use Xtest11 instead of test11,
+* because TEST11.OUT may match first on DOS)
+:se cpt=w
+* checks make_cyclic in other window
+:se cpt=u nohid
+* checks unloaded buffer expansion
+* checks adding mode abortion
+:se cpt=t,d
+* tag expansion, define add-expansion interrupted
+* t-expansion
+
+STARTTEST
+:so small.vim
+:se nocp viminfo+=nviminfo cpt=.,w ff=unix | $-2,$w!Xtestfile | set ff&
+nO#include "Xtestfile"
+ru
+O
+
+
+:se cpt=.,w,i
+kOM
+  
+:se cpt=kXtestfile
+:w Xtest11.one
+:w Xtest11.two
+OIXA
+:se cpt=w
+OST
+:se cpt=u nohid
+oOEN
+unl
+:se cpt=t,d def=^\\k* tags=Xtestfile notagbsearch
+O
+a
+:wq! test.out
+ENDTEST
+
+start of testfile
+run1
+run2
+end of testfile
+
+test11 36Gepeto /Tag/
+asd test11file 36G
+Makefile to run
diff --git a/src/testdir/test32.ok b/src/testdir/test32.ok
new file mode 100644
index 000000000..afc4463fa
--- /dev/null
+++ b/src/testdir/test32.ok
@@ -0,0 +1,15 @@
+#include "Xtestfile"
+run1 run3
+run3 run3
+
+Makefile to run3
+Makefile to run3
+Makefile to run3
+Xtest11.two
+STARTTEST
+ENDTEST
+unless
+test11file 36Gepeto /Tag/ asd
+asd
+run1 run2
+
diff --git a/src/testdir/test33.in b/src/testdir/test33.in
new file mode 100644
index 000000000..564476040
--- /dev/null
+++ b/src/testdir/test33.in
@@ -0,0 +1,34 @@
+Test for 'lisp'
+If the lisp feature is not enabled, this will fail!
+
+STARTTEST
+:so small.vim
+:set lisp
+/^(defun
+=G:/^(defun/,$w! test.out
+:q!
+ENDTEST
+
+(defun html-file (base)
+(format nil "~(~A~).html" base))
+
+(defmacro page (name title &rest body)
+(let ((ti (gensym)))
+`(with-open-file (*standard-output*
+(html-file ,name)
+:direction :output
+:if-exists :supersede)
+(let ((,ti ,title))
+(as title ,ti)
+(with center
+(as h2 (string-upcase ,ti)))
+(brs 3)
+,@body))))
+
+;;; Utilities for generating links
+
+(defmacro with-link (dest &rest body)
+`(progn
+(format t "<a href=\"~A\">" (html-file ,dest))
+,@body
+(princ "</a>")))
diff --git a/src/testdir/test33.ok b/src/testdir/test33.ok
new file mode 100644
index 000000000..cd1d87a14
--- /dev/null
+++ b/src/testdir/test33.ok
@@ -0,0 +1,23 @@
+(defun html-file (base)
+ (format nil "~(~A~).html" base))
+
+(defmacro page (name title &rest body)
+ (let ((ti (gensym)))
+ `(with-open-file (*standard-output*
+ (html-file ,name)
+ :direction :output
+ :if-exists :supersede)
+ (let ((,ti ,title))
+ (as title ,ti)
+ (with center
+ (as h2 (string-upcase ,ti)))
+ (brs 3)
+ ,@body))))
+
+;;; Utilities for generating links
+
+(defmacro with-link (dest &rest body)
+ `(progn
+ (format t "<a href=\"~A\">" (html-file ,dest))
+ ,@body
+ (princ "</a>")))
diff --git a/src/testdir/test34.in b/src/testdir/test34.in
new file mode 100644
index 000000000..676070075
--- /dev/null
+++ b/src/testdir/test34.in
@@ -0,0 +1,31 @@
+Test for user functions
+
+STARTTEST
+:so small.vim
+:function Table(title, ...)
+: let ret = a:title
+: let idx = 1
+: while idx <= a:0
+: exe "let ret = ret . a:" . idx
+: let idx = idx + 1
+: endwhile
+: return ret
+:endfunction
+:function Compute(n1, n2, divname)
+: if a:n2 == 0
+: return "fail"
+: endif
+: exe "let g:" . a:divname . " = ". a:n1 / a:n2
+: return "ok"
+:endfunction
+:let retval = "nop"
+/^here
+C=Table("xxx", 4, "asdf")
+ =Compute(45, 0, "retval")
+ =retval
+ =Compute(45, 5, "retval")
+ =retval
+:.wq! test.out
+ENDTEST
+
+here
diff --git a/src/testdir/test34.ok b/src/testdir/test34.ok
new file mode 100644
index 000000000..6dab52f1d
--- /dev/null
+++ b/src/testdir/test34.ok
@@ -0,0 +1 @@
+xxx4asdf fail nop ok 9
diff --git a/src/testdir/test35.in b/src/testdir/test35.in
new file mode 100644
index 000000000..ba97911a1
--- /dev/null
+++ b/src/testdir/test35.in
@@ -0,0 +1,21 @@
+Test Ctrl-A and Ctrl-X, which increment and decrement decimal, hexadecimal,
+and octal numbers.
+
+STARTTEST
+/^start-here
+:set nrformats=octal,hex
+j102ll64128$
+:set nrformats=octal
+0102l2w65129blx6lD
+:set nrformats=hex
+0101l257Txldt   
+:set nrformats=
+0200l100w78k
+:$-3,$wq! test.out
+ENDTEST
+
+start-here
+100 0x100 077 0
+100 0x100 077
+100 0x100 077 0xfF 0xFf
+100 0x100 077
diff --git a/src/testdir/test35.ok b/src/testdir/test35.ok
new file mode 100644
index 000000000..093ad958a
--- /dev/null
+++ b/src/testdir/test35.ok
@@ -0,0 +1,4 @@
+0 0x0ff 0000 -1
+0 1x100 0777777
+-1 0x0 078 0xFE 0xfe
+-100 -100x100 000
diff --git a/src/testdir/test36.in b/src/testdir/test36.in
new file mode 100644
index 000000000..4c3b6b42f
--- /dev/null
+++ b/src/testdir/test36.in
@@ -0,0 +1,40 @@
+Test character classes in regexp
+
+STARTTEST
+/^start-here
+j:s/\d//g
+j:s/\D//g
+j:s/\o//g
+j:s/\O//g
+j:s/\x//g
+j:s/\X//g
+j:s/\w//g
+j:s/\W//g
+j:s/\h//g
+j:s/\H//g
+j:s/\a//g
+j:s/\A//g
+j:s/\l//g
+j:s/\L//g
+j:s/\u//g
+j:s/\U//g
+:/^start-here/+1,$wq! test.out
+ENDTEST
+
+start-here
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
diff --git a/src/testdir/test36.ok b/src/testdir/test36.ok
new file mode 100644
index 000000000..5f70fc205
--- /dev/null
+++ b/src/testdir/test36.ok
@@ -0,0 +1,16 @@
+ !"#$%&'()#+'-./:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+0123456789
+ !"#$%&'()#+'-./89:;<=>?@ABCDEFGHIXYZ[\]^_`abcdefghiwxyz{|}~
+01234567
+ !"#$%&'()#+'-./:;<=>?@GHIXYZ[\]^_`ghiwxyz{|}~
+0123456789ABCDEFabcdef
+ !"#$%&'()#+'-./:;<=>?@[\]^`{|}~
+0123456789ABCDEFGHIXYZ_abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^`{|}~
+ABCDEFGHIXYZ_abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`{|}~
+ABCDEFGHIXYZabcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@ABCDEFGHIXYZ[\]^_`{|}~
+abcdefghiwxyz
+ !"#$%&'()#+'-./0123456789:;<=>?@[\]^_`abcdefghiwxyz{|}~
+ABCDEFGHIXYZ
diff --git a/src/testdir/test37.in b/src/testdir/test37.in
new file mode 100644
index 000000000..daaea32d0
--- /dev/null
+++ b/src/testdir/test37.in
@@ -0,0 +1,116 @@
+Test for 'scrollbind'. <eralston@computer.org>
+STARTTEST
+:so small.vim
+:set noscrollbind
+:set scrollopt=ver,jump
+:set scrolloff=2
+:set nowrap
+:set noequalalways
+:set splitbelow
+:" TEST using two windows open to one buffer, one extra empty window
+:split
+:new
+t:
+:resize 8
+/^start of window 1$/
+zt:
+:set scrollbind
+j:
+:resize 7
+/^start of window 2$/
+zt:
+:set scrollbind
+:" -- start of tests --
+:" TEST scrolling down
+L5jHyybpr0tHyybpr1tL6jHyybpr2kHyybpr3:
+:" TEST scrolling up
+tH4kjHtHyybpr4kHyybpr5k3ktHjHyybpr6tHyybpr7:
+:" TEST horizontal scrolling
+:set scrollopt+=hor
+gg"zyyG"zpGt015zly$bp"zpGky$bp"zpG:
+k10jH7zhg0y$bp"zpGtHg0y$bp"zpG:
+:set scrollopt-=hor
+:" ****** tests using two different buffers *****
+tj:
+:close
+t:
+:set noscrollbind
+:/^start of window 2$/,/^end of window 2$/y
+:new
+tj4"zpGp:
+t/^start of window 1$/
+zt:
+:set scrollbind
+j:
+/^start of window 2$/
+zt:
+:set scrollbind
+:" -- start of tests --
+:" TEST scrolling down
+L5jHyybpr0tHyybpr1tL6jHyybpr2kHyybpr3:
+:" TEST scrolling up
+tH4kjHtHyybpr4kHyybpr5k3ktHjHyybpr6tHyybpr7:
+:" TEST horizontal scrolling
+:set scrollopt+=hor
+gg"zyyG"zpGt015zly$bp"zpGky$bp"zpG:
+k10jH7zhg0y$bp"zpGtHg0y$bp"zpG:
+:set scrollopt-=hor
+:" TEST syncbind
+t:set noscb
+ggLj:set noscb
+ggL:set scb
+t:set scb
+GjG:syncbind
+HktHjHyybptyybp:
+t:set noscb
+ggLj:set noscb
+ggL:set scb
+t:set scb
+tGjGt:syncbind
+HkjHtHyybptjyybp:
+tH3kjHtHyybptjyybp:
+:" ***** done with tests *****
+:w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+
+start of window 1
+. line 01 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 01
+. line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+. line 03 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 03
+. line 04 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 04
+. line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+. line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+. line 07 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 07
+. line 08 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 08
+. line 09 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 09
+. line 10 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 10
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+. line 12 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 12
+. line 13 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 13
+. line 14 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 14
+. line 15 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 15
+end of window 1
+
+
+start of window 2
+. line 01 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 01
+. line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+. line 03 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 03
+. line 04 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 04
+. line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+. line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+. line 07 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 07
+. line 08 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 08
+. line 09 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 09
+. line 10 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 10
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 12 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 12
+. line 13 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 13
+. line 14 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 14
+. line 15 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 15
+. line 16 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 16
+end of window 2
+
+end of test37.in (please don't delete this line)
diff --git a/src/testdir/test37.ok b/src/testdir/test37.ok
new file mode 100644
index 000000000..a9092a402
--- /dev/null
+++ b/src/testdir/test37.ok
@@ -0,0 +1,33 @@
+
+0 line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+1 line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+2 line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+3 line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+4 line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+5 line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+6 line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+UTSRQPONMLKJIHGREDCBA9876543210 02
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+
+0 line 05 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 05
+1 line 05 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 05
+2 line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+3 line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+4 line 06 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 06
+5 line 06 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 06
+6 line 02 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 02
+7 line 02 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+56789ABCDEFGHIJKLMNOPQRSTUVWXYZ 02
+UTSRQPONMLKJIHGREDCBA9876543210 02
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
+. line 11 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ 11
+
+. line 16 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 16
+:set scrollbind
+zt:
+. line 15 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 15
+:set scrollbind
+. line 11 ZYXWVUTSRQPONMLKJIHGREDCBA9876543210 11
diff --git a/src/testdir/test38.in b/src/testdir/test38.in
new file mode 100644
index 000000000..885bd0967
--- /dev/null
+++ b/src/testdir/test38.in
@@ -0,0 +1,33 @@
+
+Test Virtual replace mode.
+
+STARTTEST
+:so small.vim
+ggdGa
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+gg:set ai
+:set bs=2
+gR0 1
+A
+BCDEFGHIJ
+ KL
+MNO
+PQRG:ka
+o0
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+'ajgR0 1
+A
+BCDEFGHIJ
+ KL
+MNO
+PQR:$
+iab cdefghi jkl0gRAB......CDEFGHI.Jo:
+iabcdefghijklmnopqrst0gRAB IJKLMNO QR:wq! test.out
+ENDTEST
+
diff --git a/src/testdir/test38.ok b/src/testdir/test38.ok
new file mode 100644
index 000000000..e10209667
--- /dev/null
+++ b/src/testdir/test38.ok
@@ -0,0 +1,13 @@
+ 1
+ A
+ BCDEFGHIJ
+ KL
+ MNO
+ PQR
+ 1
+abcdefghi
+jk lmn
+ opq rst
+uvwxyz
+AB......CDEFGHI.Jkl
+AB IJKLMNO QRst
diff --git a/src/testdir/test39.in b/src/testdir/test39.in
new file mode 100644
index 000000000..d7f294b3c
--- /dev/null
+++ b/src/testdir/test39.in
@@ -0,0 +1,24 @@
+
+Test Visual block mode commands
+
+STARTTEST
+:so small.vim
+/^abcde
+:" Test shift-right of a block
+jlllljj>wlljlll>
+:" Test shift-left of a block
+G$hhhhkk<
+:" Test block-insert
+GklkkkIxyz
+:" Test block-replace
+Gllllkkklllrq
+:" Test block-change
+G$khhhhhkkcmno
+:$-4,$wq! test.out
+ENDTEST
+
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
+abcdefghijklm
diff --git a/src/testdir/test39.ok b/src/testdir/test39.ok
new file mode 100644
index 000000000..6fa2867eb
--- /dev/null
+++ b/src/testdir/test39.ok
@@ -0,0 +1,5 @@
+axyzbcdefghijklm
+axyzqqqq mno ghijklm
+axyzqqqqef mno ghijklm
+axyzqqqqefgmnoklm
+abcdqqqqijklm
diff --git a/src/testdir/test4.in b/src/testdir/test4.in
new file mode 100644
index 000000000..4aa2fe5a8
--- /dev/null
+++ b/src/testdir/test4.in
@@ -0,0 +1,31 @@
+Test for autocommand that changes current buffer on BufEnter event.
+Check if modelines are interpreted for the correct buffer.
+
+STARTTEST
+:so small.vim
+:set nocompatible viminfo+=nviminfo
+:au BufEnter Xxx brew
+/start of
+:.,/end of/w! Xxx " write test file Xxx
+:set ai modeline modelines=3
+:sp Xxx " split to Xxx, autocmd will do :brew
+G?this is a
+othis should be auto-indented
+: " Append text with autoindent to this file
+:au! BufEnter Xxx
+:buf Xxx " go to Xxx, no autocmd anymore
+G?this is a
+othis should be in column 1:wq " append text without autoindent to Xxx
+G:r Xxx " include Xxx in the current file
+:?startstart?,$w! test.out
+:qa!
+ENDTEST
+
+startstart
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test4.ok b/src/testdir/test4.ok
new file mode 100644
index 000000000..dffecda4d
--- /dev/null
+++ b/src/testdir/test4.ok
@@ -0,0 +1,17 @@
+startstart
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+ this should be auto-indented
+end of test file Xxx
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+this should be in column 1
+end of test file Xxx
diff --git a/src/testdir/test40.in b/src/testdir/test40.in
new file mode 100644
index 000000000..f6fb61245
--- /dev/null
+++ b/src/testdir/test40.in
@@ -0,0 +1,63 @@
+Test for "*Cmd" autocommands
+
+STARTTEST
+:so small.vim
+:/^start/,$w! Xxx " write lines below to Xxx
+:au BufReadCmd testA 0r Xxx|$del
+:e testA " will read text of Xxd instead
+:au BufWriteCmd testA call append(line("$"), "write")
+:w " will append a line to the file
+:r testA " should not read anything
+: " now we have:
+: " 1 start of Xxx
+: " 2 test40
+: " 3 end of Xxx
+: " 4 write
+:au FileReadCmd testB '[r Xxx
+:2r testB " will read Xxx below line 2 instead
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test40
+: " 5 end of Xxx
+: " 6 end of Xxx
+: " 7 write
+:au FileWriteCmd testC '[,']copy $
+4GA1
+:4,5w testC " will copy lines 4 and 5 to the end
+:r testC " should not read anything
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test401
+: " 5 end of Xxx
+: " 6 end of Xxx
+: " 7 write
+: " 8 test401
+: " 9 end of Xxx
+:au FILEAppendCmd testD '[,']w! test.out
+:w >>testD " will write all lines to test.out
+:$r testD " should not read anything
+:$w >>test.out " append "end of Xxx" to test.out
+:au BufReadCmd testE 0r test.out|$del
+:sp testE " split window with test.out
+5Goasdf:"
+:au BufWriteCmd testE w! test.out
+:wall " will write other window to test.out
+: " 1 start of Xxx
+: " 2 test40
+: " 3 start of Xxx
+: " 4 test401
+: " 5 end of Xxx
+: " 6 asdf
+: " 7 end of Xxx
+: " 8 write
+: " 9 test401
+: " 10 end of Xxx
+: " 11 end of Xxx
+:qa!
+ENDTEST
+
+start of Xxx
+ test40
+end of Xxx
diff --git a/src/testdir/test40.ok b/src/testdir/test40.ok
new file mode 100644
index 000000000..b6501394f
--- /dev/null
+++ b/src/testdir/test40.ok
@@ -0,0 +1,11 @@
+start of Xxx
+ test40
+start of Xxx
+ test401
+end of Xxx
+asdf
+end of Xxx
+write
+ test401
+end of Xxx
+end of Xxx
diff --git a/src/testdir/test41.in b/src/testdir/test41.in
new file mode 100644
index 000000000..2d294cae0
--- /dev/null
+++ b/src/testdir/test41.in
@@ -0,0 +1,24 @@
+Test for writing and reading a file of over 100 Kbyte
+
+1 line: "This is the start"
+3001 lines: "This is the leader"
+1 line: "This is the middle"
+3001 lines: "This is the trailer"
+1 line: "This is the end"
+
+STARTTEST
+:%d
+aThis is the start
+This is the leader
+This is the middle
+This is the trailer
+This is the endkY3000p2GY3000p
+:w! Xtest
+:%d
+:e! Xtest
+:.w! test.out
+3003G:.w >>test.out
+6005G:.w >>test.out
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test41.ok b/src/testdir/test41.ok
new file mode 100644
index 000000000..988e5f24b
--- /dev/null
+++ b/src/testdir/test41.ok
@@ -0,0 +1,3 @@
+This is the start
+This is the middle
+This is the end
diff --git a/src/testdir/test42.in b/src/testdir/test42.in
new file mode 100644
index 000000000..c35569a76
--- /dev/null
+++ b/src/testdir/test42.in
Binary files differ
diff --git a/src/testdir/test42.ok b/src/testdir/test42.ok
new file mode 100644
index 000000000..16f41e46e
--- /dev/null
+++ b/src/testdir/test42.ok
Binary files differ
diff --git a/src/testdir/test43.in b/src/testdir/test43.in
new file mode 100644
index 000000000..26f0e0c9a
--- /dev/null
+++ b/src/testdir/test43.in
@@ -0,0 +1,27 @@
+Tests for regexp with various magic settings.
+
+STARTTEST
+:set nocompatible viminfo+=nviminfo
+/^1
+/a*b\{2}c\+/e
+x/\Md\*e\{2}f\+/e
+x:set nomagic
+/g\*h\{2}i\+/e
+x/\mj*k\{2}l\+/e
+x/\vm*n{2}o+/e
+x/\V^aa$
+x:set magic
+/\v(a)(b)\2\1\1/e
+x/\V[ab]\(\[xy]\)\1
+x:?^1?,$w! test.out
+:qa!
+ENDTEST
+
+1 a aa abb abbccc
+2 d dd dee deefff
+3 g gg ghh ghhiii
+4 j jj jkk jkklll
+5 m mm mnn mnnooo
+6 x ^aa$ x
+7 (a)(b) abbaa
+8 axx [ab]xx
diff --git a/src/testdir/test43.ok b/src/testdir/test43.ok
new file mode 100644
index 000000000..425316b68
--- /dev/null
+++ b/src/testdir/test43.ok
@@ -0,0 +1,8 @@
+1 a aa abb abbcc
+2 d dd dee deeff
+3 g gg ghh ghhii
+4 j jj jkk jkkll
+5 m mm mnn mnnoo
+6 x aa$ x
+7 (a)(b) abba
+8 axx ab]xx
diff --git a/src/testdir/test44.in b/src/testdir/test44.in
new file mode 100644
index 000000000..d90a962d3
--- /dev/null
+++ b/src/testdir/test44.in
@@ -0,0 +1,37 @@
+Tests for regexp with multi-byte encoding and various magic settings.
+
+STARTTEST
+:so mbyte.vim
+:set nocompatible encoding=utf-8 termencoding=latin1 viminfo+=nviminfo
+/^1
+/a*b\{2}c\+/e
+x/\Md\*e\{2}f\+/e
+x:set nomagic
+/g\*h\{2}i\+/e
+x/\mj*k\{2}l\+/e
+x/\vm*n{2}o+/e
+x/\V^aa$
+x:set magic
+/\v(a)(b)\2\1\1/e
+x/\V[ab]\(\[xy]\)\1
+x:" Now search for multi-byte without composing char
+/ม
+x:" Now search for multi-byte with composing char
+/ม่
+x:" find word by change of word class
+/ち\<カヨ\>は
+x:?^1?,$w! test.out
+:qa!
+ENDTEST
+
+1 a aa abb abbccc
+2 d dd dee deefff
+3 g gg ghh ghhiii
+4 j jj jkk jkklll
+5 m mm mnn mnnooo
+6 x ^aa$ x
+7 (a)(b) abbaa
+8 axx [ab]xx
+9 หม่x อมx
+a อมx หม่x
+b ちカヨは
diff --git a/src/testdir/test44.ok b/src/testdir/test44.ok
new file mode 100644
index 000000000..af8507606
--- /dev/null
+++ b/src/testdir/test44.ok
@@ -0,0 +1,11 @@
+1 a aa abb abbcc
+2 d dd dee deeff
+3 g gg ghh ghhii
+4 j jj jkk jkkll
+5 m mm mnn mnnoo
+6 x aa$ x
+7 (a)(b) abba
+8 axx ab]xx
+9 หม่x อx
+a อมx หx
+b カヨは
diff --git a/src/testdir/test45.in b/src/testdir/test45.in
new file mode 100644
index 000000000..58537f33d
--- /dev/null
+++ b/src/testdir/test45.in
@@ -0,0 +1,72 @@
+Tests for folding. vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:" We also need the +syntax feature here.
+:if !has("syntax")
+ e! test.ok
+ w! test.out
+ qa!
+:endif
+:" basic test if a fold can be created, opened, moving to the end and closed
+/^1
+zf2j:call append("$", "manual " . getline(foldclosed(".")))
+zo:call append("$", foldclosed("."))
+]z:call append("$", getline("."))
+zc:call append("$", getline(foldclosed(".")))
+:" test folding with markers.
+:set fdm=marker fdl=1 fdc=3
+/^5
+:call append("$", "marker " . foldlevel("."))
+[z:call append("$", foldlevel("."))
+jo{{ r{jj:call append("$", foldlevel("."))
+kYpj:call append("$", foldlevel("."))
+:" test folding with indent
+:set fdm=indent sw=2
+/^2 b
+i jI :call append("$", "indent " . foldlevel("."))
+k:call append("$", foldlevel("."))
+:" test syntax folding
+:set fdm=syntax fdl=0
+:syn region Hup start="dd" end="hh" fold
+Gzk:call append("$", "folding " . getline("."))
+k:call append("$", getline("."))
+:" test expression folding
+:fun Flvl()
+ let l = getline(v:lnum)
+ if l =~ "bb$"
+ return 2
+ elseif l =~ "gg$"
+ return "s1"
+ elseif l =~ "ii$"
+ return ">2"
+ elseif l =~ "kk$"
+ return "0"
+ endif
+ return "="
+endfun
+:set fdm=expr fde=Flvl()
+/bb$
+:call append("$", "expr " . foldlevel("."))
+/hh$
+:call append("$", foldlevel("."))
+/ii$
+:call append("$", foldlevel("."))
+/kk$
+:call append("$", foldlevel("."))
+:/^last/+1,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+2 bb
+3 cc
+4 dd {{{
+5 ee {{{ }}}
+6 ff }}}
+7 gg
+8 hh
+9 ii
+a jj
+b kk
+last
diff --git a/src/testdir/test45.ok b/src/testdir/test45.ok
new file mode 100644
index 000000000..f5a1380e5
--- /dev/null
+++ b/src/testdir/test45.ok
@@ -0,0 +1,16 @@
+manual 1 aa
+-1
+3 cc
+1 aa
+marker 2
+1
+1
+0
+indent 2
+1
+folding 8 hh
+ 3 cc
+expr 2
+1
+2
+0
diff --git a/src/testdir/test46.in b/src/testdir/test46.in
new file mode 100644
index 000000000..9a9db74d6
--- /dev/null
+++ b/src/testdir/test46.in
@@ -0,0 +1,27 @@
+Tests for multi-line regexps with ":s". vim: set ft=vim :
+
+STARTTEST
+:" test if replacing a line break works with a back reference
+:/^1/,/^2/s/\n\(.\)/ \1/
+:" test if inserting a line break works with a back reference
+:/^3/,/^4/s/\(.\)$/\r\1/
+:" test if replacing a line break with another line break works
+:/^5/,/^6/s/\(\_d\{3}\)/x\1x/
+:/^1/,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+bb
+cc
+2 dd
+ee
+3 ef
+gh
+4 ij
+5 a8
+8b c9
+9d
+6 e7
+77f
+xxxxx
diff --git a/src/testdir/test46.ok b/src/testdir/test46.ok
new file mode 100644
index 000000000..71b353df1
--- /dev/null
+++ b/src/testdir/test46.ok
@@ -0,0 +1,13 @@
+1 aa bb cc 2 dd ee
+3 e
+f
+g
+h
+4 i
+j
+5 ax8
+8xb cx9
+9xd
+6 ex7
+7x7f
+xxxxx
diff --git a/src/testdir/test47.in b/src/testdir/test47.in
new file mode 100644
index 000000000..35bb9f260
--- /dev/null
+++ b/src/testdir/test47.in
@@ -0,0 +1,44 @@
+Tests for vertical splits and filler lines in diff mode
+
+STARTTEST
+:so small.vim
+/^1
+yG:new
+pkdd:w! Xtest
+ddGpkkrXoxxx:w! Xtest2
+:file Nop
+ggoyyyjjjozzzz
+:vert diffsplit Xtest
+:vert diffsplit Xtest2
+:" jump to second window for a moment to have filler line appear at start of
+:" first window
+ggpgg:let one = winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+j:let one = one . "-" . winline()
+gg:let two = winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+j:let two = two . "-" . winline()
+gg:let three = winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+j:let three = three . "-" . winline()
+:call append("$", one)
+:call append("$", two)
+:call append("$", three)
+:$-2,$w! test.out
+:qa!
+ENDTEST
+
+1 aa
+2 bb
+3 cc
+4 dd
+5 ee
diff --git a/src/testdir/test47.ok b/src/testdir/test47.ok
new file mode 100644
index 000000000..3307b934e
--- /dev/null
+++ b/src/testdir/test47.ok
@@ -0,0 +1,3 @@
+2-4-5-6-8-9
+1-2-4-5-8
+2-3-4-5-6-7-8
diff --git a/src/testdir/test48.in b/src/testdir/test48.in
new file mode 100644
index 000000000..2179fe664
--- /dev/null
+++ b/src/testdir/test48.in
@@ -0,0 +1,74 @@
+This is a test of 'virtualedit'.
+
+STARTTEST
+:so small.vim
+:set noswf
+:set ve=all
+-dgg
+:"
+:" Insert "keyword keyw", ESC, C CTRL-N, shows "keyword ykeyword".
+:" Repeating CTRL-N fixes it. (Mary Ellen Foster)
+2/w
+C
+:"
+:" Using "C" then then <CR> moves the last remaining character to the next
+:" line. (Mary Ellen Foster)
+j^/are
+C are belong to vim
+:"
+:" When past the end of a line that ends in a single character "b" skips
+:" that word.
+^$15lbC7
+:"
+:" Make sure 'i' works
+$4li<-- should be 3 ' '
+:"
+:" Make sure 'C' works
+$4lC<-- should be 3 ' '
+:"
+:" Make sure 'a' works
+$4la<-- should be 4 ' '
+:"
+:" Make sure 'A' works
+$4lA<-- should be 0 ' '
+:"
+:" Make sure 'D' works
+$4lDi<-- 'D' should be intact
+:"
+:" Test for yank bug reported by Mark Waggoner.
+:set ve=block
+^2w3jyGp
+:"
+:" Test "r" beyond the end of the line
+:set ve=all
+/^"r"
+$5lrxa<-- should be 'x'
+:"
+:" Test to make sure 'x' can delete control characters
+:set display=uhex
+^xxxxxxi[This line should contain only the text between the brackets.]
+:set display=
+:"
+:" Test for ^Y/^E due to bad w_virtcol value, reported by
+:" Roy <royl@netropolis.net>.
+^O3li4li4li <-- should show the name of a noted text editor
+^o4li4li4li <-- and its version number-dd
+:"
+:wq! test.out
+ENDTEST
+keyword keyw
+all your base are belong to us
+1 2 3 4 5 6
+'i'
+'C'
+'a'
+'A'
+'D'
+this is a test
+this is a test
+this is a test
+"r"
+ab sd
+abcv6efi.him0kl
+
+
diff --git a/src/testdir/test48.ok b/src/testdir/test48.ok
new file mode 100644
index 000000000..4fcbe5086
--- /dev/null
+++ b/src/testdir/test48.ok
@@ -0,0 +1,21 @@
+keyword keyword
+all your base
+are belong to vim
+1 2 3 4 5 7
+'i' <-- should be 3 ' '
+'C' <-- should be 3 ' '
+'a' <-- should be 4 ' '
+'A'<-- should be 0 ' '
+'D' <-- 'D' should be intact
+this is a test
+this is a test
+this is a test
+"r" x<-- should be 'x'
+[This line should contain only the text between the brackets.]
+ v i m <-- should show the name of a noted text editor
+ 6 . 0 <-- and its version number
+
+a
+a
+a
+
diff --git a/src/testdir/test49.in b/src/testdir/test49.in
new file mode 100644
index 000000000..ec17d2134
--- /dev/null
+++ b/src/testdir/test49.in
@@ -0,0 +1,13 @@
+This is a test of the script language.
+
+If after adding a new test, the test output doesn't appear properly in
+test49.failed, try to add one ore more "G"s at the line before ENDTEST.
+
+STARTTEST
+:so small.vim
+:se nocp nomore viminfo+=nviminfo
+:so test49.vim
+GGGGGGGGGG"rp:.-,$wq! test.out
+ENDTEST
+
+Results of test49.vim:
diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok
new file mode 100644
index 000000000..1842af259
--- /dev/null
+++ b/src/testdir/test49.ok
@@ -0,0 +1,92 @@
+Results of test49.vim:
+*** Test 1: OK (34695)
+*** Test 2: OK (34695)
+*** Test 3: OK (1384648195)
+*** Test 4: OK (32883)
+*** Test 5: OK (32883)
+*** Test 6: OK (603978947)
+*** Test 7: OK (90563)
+*** Test 8: OK (562493431)
+*** Test 9: OK (363)
+*** Test 10: OK (559615)
+*** Test 11: OK (2049)
+*** Test 12: OK (352256)
+*** Test 13: OK (145)
+*** Test 14: OK (42413)
+*** Test 15: OK (42413)
+*** Test 16: OK (8722)
+*** Test 17: OK (285127993)
+*** 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 25: OK (260177811)
+*** Test 26: OK (1681500476)
+*** Test 27: OK (1996459)
+*** Test 28: OK (1996459)
+*** Test 29: OK (170428555)
+*** Test 30: OK (190905173)
+*** Test 31: OK (190905173)
+*** Test 32: OK (354833067)
+--- Test 33: sum = 178275600 (ok)
+*** Test 33: OK (1216907538)
+*** 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 41: OK (3076095)
+*** Test 42: OK (1505155949)
+*** Test 43: OK (1157763329)
+*** Test 44: OK (1031761407)
+*** Test 45: OK (1157763329)
+*** Test 46: OK (739407)
+*** Test 47: OK (371213935)
+*** Test 48: OK (756255461)
+*** Test 49: OK (179000669)
+*** Test 50: OK (363550045)
+*** Test 51: OK (40744667)
+*** Test 52: OK (1247112011)
+*** Test 53: OK (131071)
+*** Test 54: OK (2047)
+*** Test 55: OK (1023)
+*** Test 56: OK (511)
+*** Test 57: OK (2147450880)
+*** Test 58: OK (624945)
+*** Test 59: OK (2038431743)
+*** Test 60: OK (311511339)
+*** Test 61: OK (374889517)
+*** Test 62: OK (286331153)
+*** Test 63: OK (236978127)
+*** Test 64: OK (1499645335)
+*** Test 65: OK (70187)
+*** Test 66: OK (5464)
+*** Test 67: OK (212514423)
+*** Test 68: OK (212514423)
+*** Test 69: OK (8995471)
+*** Test 70: OK (69544277)
+*** Test 71: OK (34886997)
+*** Test 72: OK (1789569365)
+*** Test 73: OK (9032615)
+*** Test 74: OK (224907669)
+*** Test 75: OK (2000403408)
+*** Test 76: OK (1610087935)
+*** Test 77: OK (1388671)
+*** Test 78: OK (134217728)
+*** Test 79: OK (70288929)
+*** Test 80: OK (17895765)
+*** Test 81: OK (387)
+*** Test 82: OK (8454401)
+*** Test 83: OK (2835)
+*** Test 84: OK (934782101)
+*** Test 85: OK (198689)
+--- Test 86: All tests were run with throwing exceptions on error.
+ The $VIMNOERRTHROW control is not configured.
+--- Test 86: All tests were run with throwing exceptions on interrupt.
+ The $VIMNOINTTHROW control is not configured.
+*** Test 86: OK (50443995)
diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim
new file mode 100644
index 000000000..e742a9622
--- /dev/null
+++ b/src/testdir/test49.vim
@@ -0,0 +1,9666 @@
+" Vim script language tests
+" Author: Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
+" Last Change: 2004 Apr 03
+
+"-------------------------------------------------------------------------------
+" Test environment {{{1
+"-------------------------------------------------------------------------------
+
+
+" Adding new tests easily. {{{2
+"
+" Writing new tests is eased considerably with the following functions and
+" abbreviations (see "Commands for recording the execution path", "Automatic
+" argument generation").
+"
+" To get the abbreviations, execute the command
+"
+" :let test49_set_env = 1 | source test49.vim
+"
+" To get them always (from src/testdir), put a line
+"
+" au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
+"
+" into the local .vimrc file in the src/testdir directory.
+"
+if exists("test49_set_env") && test49_set_env
+
+ " Automatic argument generation for the test environment commands.
+
+ function! Xsum()
+ let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
+ " Evaluate arithmetic expression.
+ if addend != ""
+ exec "let g:Xsum = g:Xsum + " . addend
+ endif
+ endfunction
+
+ function! Xcheck()
+ let g:Xsum=0
+ ?XpathINIT?,.call Xsum()
+ exec "norm A "
+ return g:Xsum
+ endfunction
+
+ iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
+
+ function! Xcomment(num)
+ let str = ""
+ let tabwidth = &sts ? &sts : &ts
+ let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
+ while tabs > 0
+ let str = str . "\t"
+ let tabs = tabs - 1
+ endwhile
+ let str = str . '" X:'
+ return str
+ endfunction
+
+ function! Xloop()
+ let back = line(".") . "|norm" . virtcol(".") . "|"
+ norm 0
+ let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
+ exec back
+ let theline = getline(last)
+ if theline =~ 'X\(loop\|path\)INIT'
+ let num = 1
+ else
+ let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
+ endif
+ ?X\(loop\|path\)INIT?
+ \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
+ exec back
+ exec "norm a "
+ return num . Xcomment(strlen(num))
+ endfunction
+
+ iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
+
+ function! Xpath(loopinit)
+ let back = line(".") . "|norm" . virtcol(".") . "|"
+ norm 0
+ let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
+ exec back
+ let theline = getline(last)
+ if theline =~ 'XpathINIT'
+ let num = 1
+ elseif theline =~ 'Xpath\>'
+ let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
+ else
+ let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
+ let num = substitute(theline, pattern, '\1', "")
+ let factor = substitute(theline, pattern, '\2', "")
+ " The "<C-O>x" from the "Xpath" iab and the character triggering its
+ " expansion are in the input buffer. Save and clear typeahead so
+ " that it is not read away by the call to "input()" below. Restore
+ " afterwards.
+ call inputsave()
+ let loops = input("Number of iterations in previous loop? ")
+ call inputrestore()
+ while (loops > 0)
+ let num = num * factor
+ let loops = loops - 1
+ endwhile
+ endif
+ exec "norm a "
+ if a:loopinit
+ return num . " 1"
+ endif
+ return num . Xcomment(strlen(num))
+ endfunction
+
+ iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
+ iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
+
+ " Also useful (see ExtraVim below):
+ aug ExtraVim
+ au!
+ au BufEnter <sfile> syn region ExtraVim
+ \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
+ \ transparent keepend
+ au BufEnter <sfile> syn match ExtraComment /^"/
+ \ contained containedin=ExtraVim
+ au BufEnter <sfile> hi link ExtraComment vimComment
+ aug END
+
+ aug Xpath
+ au BufEnter <sfile> syn keyword Xpath
+ \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
+ au BufEnter <sfile> hi link Xpath Special
+ aug END
+
+ do BufEnter <sfile>
+
+ " Do not execute the tests when sourcing this file for getting the functions
+ " and abbreviations above, which are intended for easily adding new test
+ " cases; they are not needed for test execution. Unlet the variable
+ " controlling this so that an explicit ":source" command for this file will
+ " execute the tests.
+ unlet test49_set_env
+ finish
+
+endif
+
+
+" Commands for recording the execution path. {{{2
+"
+" The Xpath/Xloop commands can be used for computing the eXecution path by
+" adding (different) powers of 2 from those script lines, for which the
+" execution should be checked. Xloop provides different addends for each
+" execution of a loop. Permittable values are 2^0 to 2^30, so that 31 execution
+" points (multiply counted inside loops) can be tested.
+"
+" Note that the arguments of the following commands can be generated
+" automatically, see below.
+"
+" Usage: {{{3
+"
+" - Use XpathINIT at the beginning of the test.
+"
+" - Use Xpath to check if a line is executed.
+" Argument: power of 2 (decimal).
+"
+" - To check multiple execution of loops use Xloop for automatically
+" computing Xpath values:
+"
+" - Use XloopINIT before the loop.
+" Two arguments:
+" - the first Xpath value (power of 2) to be used (Xnext),
+" - factor for computing a new Xnext value when reexecuting a loop
+" (by a ":continue" or ":endwhile"); this should be 2^n where
+" n is the number of Xloop commands inside the loop.
+" If XloopINIT! is used, the first execution of XloopNEXT is
+" a no-operation.
+"
+" - Use Xloop inside the loop:
+" One argument:
+" The argument and the Xnext value are multiplied to build the
+" next Xpath value. No new Xnext value is prepared. The argument
+" should be 2^(n-1) for the nth Xloop command inside the loop.
+" If the loop has only one Xloop command, the argument can be
+" ommitted (default: 1).
+"
+" - Use XloopNEXT before ":continue" and ":endwhile". This computes a new
+" Xnext value for the next execution of the loop by multiplying the old
+" one with the factor specified in the XloopINIT command. No Argument.
+" Alternatively, when XloopINIT! is used, a single XloopNEXT at the
+" beginning of the loop can be used.
+"
+" Nested loops are not supported.
+"
+" - Use Xcheck at end of each test. It prints the test number, the expected
+" execution path value, the test result ("OK" or "FAIL"), and, if the tests
+" fails, the actual execution path.
+" One argument:
+" Expected Xpath/Xloop sum for the correct execution path.
+" In order that this value can be computed automatically, do the
+" following: For each line in the test with an Xpath and Xloop
+" command, add a comment starting with "X:" and specifying an
+" expression that evaluates to the value contributed by this line to
+" the correct execution path. (For copying an Xpath argument of at
+" least two digits into the comment, press <C-P>.) At the end of the
+" test, just type "Xcheck" and press <Esc>.
+"
+" - In order to add additional information to the test output file, use the
+" Xout command. Argument(s) like ":echo".
+"
+" Automatic argument generation: {{{3
+"
+" The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
+" generated automatically, so that new tests can easily be written without
+" mental arithmetic. The Xcheck argument is computed from the "X:" comments
+" of the preceding Xpath and Xloop commands. See the commands and
+" abbreviations at the beginning of this file.
+"
+" Implementation: {{{3
+" XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
+"
+" The variants for existing g:ExtraVimResult are needed when executing a script
+" in an extra Vim process, see ExtraVim below.
+
+" EXTRA_VIM_START - do not change or remove this line.
+
+com! XpathINIT let g:Xpath = 0
+
+if exists("g:ExtraVimResult")
+ com! -count -bar Xpath exec "!echo <count> >>" . g:ExtraVimResult
+else
+ com! -count -bar Xpath let g:Xpath = g:Xpath + <count>
+endif
+
+com! -count -nargs=1 -bang
+ \ XloopINIT let g:Xnext = <count> |
+ \ let g:Xfactor = <args> |
+ \ let g:Xskip = strlen("<bang>")
+
+if exists("g:ExtraVimResult")
+ com! -count=1 -bar Xloop exec "!echo " . (g:Xnext * <count>) . " >>" .
+ \ g:ExtraVimResult
+else
+ com! -count=1 -bar Xloop let g:Xpath = g:Xpath + g:Xnext * <count>
+endif
+
+com! XloopNEXT let g:Xnext = g:Xnext *
+ \ (g:Xskip ? 1 : g:Xfactor) |
+ \ let g:Xskip = 0
+
+let @r = ""
+let Xtest = 1
+com! -count Xcheck let Xresult = "*** Test " .
+ \ (Xtest<10?" ":Xtest<100?" ":"") .
+ \ Xtest . ": " . (
+ \ (Xpath==<count>) ? "OK (".Xpath.")" :
+ \ "FAIL (".Xpath." instead of <count>)"
+ \ ) |
+ \ let @R = Xresult . "\n" |
+ \ echo Xresult |
+ \ let Xtest = Xtest + 1
+
+if exists("g:ExtraVimResult")
+ com! -nargs=+ Xout exec "exec \"!echo @R:'\" ."
+ \ 'substitute(substitute("' . <args> .
+ \ '", "' . "'" . '", ' . "'" . '&\\&&' . "'"
+ \ . ', "g"), "\n", "@NL@", "g")'
+ \ ". \"' >>\" . g:ExtraVimResult"
+else
+ com! -nargs=+ Xout exec 'let @R = "--- Test ' .
+ \ (g:Xtest<10?" ":g:Xtest<100?" ":"") .
+ \ g:Xtest . ": " .
+ \ '" . substitute("' . <args> .
+ \ '", "\n", "&\t ", "g") . "\n"'
+endif
+
+" Switch off storing of lines for undoing changes. Speeds things up a little.
+set undolevels=-1
+
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" ExtraVim() - Run a script file in an extra Vim process. {{{2
+"
+" This is useful for testing immediate abortion of the script processing due to
+" an error in a command dynamically enclosed by a :try/:tryend region or when an
+" exception is thrown but not caught or when an interrupt occurs. It can also
+" be used for testing :finish.
+"
+" An interrupt location can be specified by an "INTERRUPT" comment. A number
+" telling how often this location is reached (in a loop or in several function
+" calls) should be specified as argument. When missing, once per script
+" invocation or function call is assumed. INTERRUPT locations are tested by
+" setting a breakpoint in that line and using the ">quit" debug command when
+" the breakpoint is reached. A function for which an INTERRUPT location is
+" specified must be defined before calling it (or executing it as a script by
+" using ExecAsScript below).
+"
+" This function is only called in normal modus ("g:ExtraVimResult" undefined).
+"
+" Tests to be executed as an extra script should be written as follows:
+"
+" column 1 column 1
+" | |
+" v v
+"
+" XpathINIT XpathINIT
+" if ExtraVim() if ExtraVim()
+" ... " ...
+" ... " ...
+" endif endif
+" Xcheck <number> Xcheck <number>
+"
+" Double quotes in column 1 are removed before the script is executed.
+" They should be used if the test has unbalanced conditionals (:if/:endif,
+" :while:/endwhile, :try/:endtry) or for a line with a syntax error. The
+" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
+"
+" A file name may be specified as argument. All messages of the extra Vim
+" process are then redirected to the file. An existing file is overwritten.
+"
+let ExtraVimCount = 0
+let ExtraVimBase = expand("<sfile>")
+let ExtraVimTestEnv = ""
+"
+function! ExtraVim(...)
+ " Count how often this function is called.
+ let g:ExtraVimCount = g:ExtraVimCount + 1
+
+ " Disable folds to prevent that the ranges in the ":write" commands below
+ " are extended up to the end of a closed fold. This also speeds things up
+ " considerably.
+ set nofoldenable
+
+ " Open a buffer for this test script and copy the test environment to
+ " a temporary file. Take account of parts relevant for the extra script
+ " execution only.
+ let current_buffnr = bufnr("%")
+ execute "view +1" g:ExtraVimBase
+ if g:ExtraVimCount == 1
+ let g:ExtraVimTestEnv = tempname()
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
+ \ g:ExtraVimTestEnv "|']+"
+ endif
+
+ " Start the extra Vim script with a ":source" command for the test
+ " environment. The source line number where the extra script will be
+ " appended, needs to be passed as variable "ExtraVimBegin" to the script.
+ let extra_script = tempname()
+ exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
+ let extra_begin = 1
+
+ " Starting behind the test environment, skip over the first g:ExtraVimCount
+ " occurrences of "if ExtraVim()" and copy the following lines up to the
+ " matching "endif" to the extra Vim script.
+ execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
+ exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
+ execute ".,/^endif/-write >>" . extra_script
+
+ " Open a buffer for the extra Vim script, delete all ^", and write the
+ " script if was actually modified.
+ execute "edit +" . (extra_begin + 1) extra_script
+ ,$s/^"//e
+ update
+
+ " Count the INTERRUPTs and build the breakpoint and quit commands.
+ let breakpoints = ""
+ let debug_quits = ""
+ let in_func = 0
+ exec extra_begin
+ while search(
+ \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
+ \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
+ \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
+ \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
+ \ "W") > 0
+ let theline = getline(".")
+ if theline =~ '^\s*fu'
+ " Function definition.
+ let in_func = 1
+ let func_start = line(".")
+ let func_name = substitute(theline,
+ \ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
+ let func_conts = 0
+ elseif theline =~ '^\s*\\'
+ if in_func
+ let func_conts = func_conts + 1
+ endif
+ elseif theline =~ '^\s*endf'
+ " End of function definition.
+ let in_func = 0
+ else
+ let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
+ \ '\1', "")
+ if finding =~ '^"\s*INTERRUPT\h\@!'
+ " Interrupt comment. Compose as many quit commands as
+ " specified.
+ let cnt = substitute(finding,
+ \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
+ let quits = ""
+ while cnt > 0
+ " Use "\r" rather than "\n" to separate the quit commands.
+ " "\r" is not interpreted as command separator by the ":!"
+ " command below but works to separate commands in the
+ " external vim.
+ let quits = quits . "q\r"
+ let cnt = cnt - 1
+ endwhile
+ if in_func
+ " Add the function breakpoint and note the number of quits
+ " to be used, if specified, or one for every call else.
+ let breakpoints = breakpoints . " -c 'breakadd func " .
+ \ (line(".") - func_start - func_conts) . " " .
+ \ func_name . "'"
+ if quits != ""
+ let debug_quits = debug_quits . quits
+ elseif !exists("quits{func_name}")
+ let quits{func_name} = "q\r"
+ else
+ let quits{func_name} = quits{func_name} . "q\r"
+ endif
+ else
+ " Add the file breakpoint and the quits to be used for it.
+ let breakpoints = breakpoints . " -c 'breakadd file " .
+ \ line(".") . " " . extra_script . "'"
+ if quits == ""
+ let quits = "q\r"
+ endif
+ let debug_quits = debug_quits . quits
+ endif
+ else
+ " Add the quits to be used for calling the function or executing
+ " it as script file.
+ if finding =~ '^ExecAsScript'
+ " Sourcing function as script.
+ let finding = substitute(finding,
+ \ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
+ else
+ " Function call.
+ let finding = substitute(finding,
+ \ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
+ endif
+ if exists("quits{finding}")
+ let debug_quits = debug_quits . quits{finding}
+ endif
+ endif
+ endif
+ endwhile
+
+ " Close the buffer for the script and create an (empty) resultfile.
+ bwipeout
+ let resultfile = tempname()
+ exec "!>" . resultfile
+
+ " Run the script in an extra vim. Switch to extra modus by passing the
+ " resultfile in ExtraVimResult. Redirect messages to the file specified as
+ " argument if any. Use ":debuggreedy" so that the commands provided on the
+ " pipe are consumed at the debug prompt. Use "-N" to enable command-line
+ " contiunation ("C" in 'cpo'). Add "nviminfo" to 'viminfo' to avoid
+ " messing up the user's viminfo file.
+ let redirect = a:0 ?
+ \ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
+ exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect .
+ \ " -c 'debuggreedy|set viminfo+=nviminfo'" .
+ \ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
+ \ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
+ \ " -S " . extra_script
+
+ " Build the resulting sum for resultfile and add it to g:Xpath. Add Xout
+ " information provided by the extra Vim process to the test output.
+ let sum = 0
+ exec "edit" resultfile
+ let line = 1
+ while line <= line("$")
+ let theline = getline(line)
+ if theline =~ '^@R:'
+ exec 'Xout "' . substitute(substitute(
+ \ escape(escape(theline, '"'), '\"'),
+ \ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
+ else
+ let sum = sum + getline(line)
+ endif
+ let line = line + 1
+ endwhile
+ bwipeout
+ let g:Xpath = g:Xpath + sum
+
+ " Delete the extra script and the resultfile.
+ call delete(extra_script)
+ call delete(resultfile)
+
+ " Switch back to the buffer that was active when this function was entered.
+ exec "buffer" current_buffnr
+
+ " Return 0. This protects extra scripts from being run in the main Vim
+ " process.
+ return 0
+endfunction
+
+
+" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script {{{2
+"
+" Evaluates v:throwpoint and returns the throwpoint relativ to the beginning of
+" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! ExtraVimThrowpoint()
+ if !exists("g:ExtraVimBegin")
+ Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
+ return v:throwpoint
+ endif
+
+ if v:throwpoint =~ '^function\>'
+ return v:throwpoint
+ endif
+
+ return "line " .
+ \ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
+ \ " of ExtraVim() script"
+endfunction
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" MakeScript() - Make a script file from a function. {{{2
+"
+" Create a script that consists of the body of the function a:funcname.
+" Replace any ":return" by a ":finish", any argument variable by a global
+" variable, and and every ":call" by a ":source" for the next following argument
+" in the variable argument list. This function is useful if similar tests are
+" to be made for a ":return" from a function call or a ":finish" in a script
+" file.
+"
+" In order to execute a function specifying an INTERRUPT location (see ExtraVim)
+" as a script file, use ExecAsScript below.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! MakeScript(funcname, ...)
+ let script = tempname()
+ execute "redir! >" . script
+ execute "function" a:funcname
+ redir END
+ execute "edit" script
+ " Delete the "function" and the "endfunction" lines. Do not include the
+ " word "function" in the pattern since it might be translated if LANG is
+ " set. When MakeScript() is being debugged, this deletes also the debugging
+ " output of its line 3 and 4.
+ exec '1,/.*' . a:funcname . '(.*)/d'
+ /^\d*\s*endfunction\>/,$d
+ %s/^\d*//e
+ %s/return/finish/e
+ %s/\<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
+endfunction
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" 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.
+"
+" When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
+" location specified in the function.
+"
+" EXTRA_VIM_START - do not change or remove this line.
+function! ExecAsScript(funcname)
+ " Make a script from the function passed as argument.
+ let script = MakeScript(a:funcname)
+
+ " When running in an extra Vim process, add a file breakpoint for each
+ " function breakpoint set when the extra Vim process was invoked by
+ " ExtraVim().
+ if exists("g:ExtraVimResult")
+ let bplist = tempname()
+ execute "redir! >" . bplist
+ breaklist
+ redir END
+ execute "edit" bplist
+ " Get the line number from the function breakpoint. Works also when
+ " LANG is set.
+ execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
+ %s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
+ let cnt = 0
+ while cnt < line("$")
+ let cnt = cnt + 1
+ if getline(cnt) != ""
+ execute "breakadd file" getline(cnt) script
+ endif
+ endwhile
+ bwipeout!
+ call delete(bplist)
+ endif
+
+ " Source and delete the script.
+ exec "source" script
+ call delete(script)
+endfunction
+
+com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
+" EXTRA_VIM_STOP - do not change or remove this line.
+
+
+" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
+
+
+"-------------------------------------------------------------------------------
+" Test 1: :endwhile in function {{{1
+"
+" Detect if a broken loop is (incorrectly) reactivated by the
+" :endwhile. Use a :return to prevent an endless loop, and make
+" this test first to get a meaningful result on an error before other
+" tests will hang.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ Xpath 1 " X: 1
+ let first = 1
+ XloopINIT 2 8
+ while 1
+ Xloop 1 " X: 2 + 0 * 16
+ if first
+ Xloop 2 " X: 4 + 0 * 32
+ let first = 0
+ XloopNEXT
+ break
+ else
+ Xloop 4 " X: 0 + 0 * 64
+ return
+ endif
+ endwhile
+endfunction
+
+call F()
+Xpath 128 " X: 128
+
+function! G()
+ Xpath 256 " X: 256 + 0 * 2048
+ let first = 1
+ XloopINIT 512 8
+ while 1
+ Xloop 1 " X: 512 + 0 * 4096
+ if first
+ Xloop 2 " X: 1024 + 0 * 8192
+ let first = 0
+ XloopNEXT
+ break
+ else
+ Xloop 4 " X: 0 + 0 * 16384
+ return
+ endif
+ if 1 " unmatched :if
+ endwhile
+endfunction
+
+call G()
+Xpath 32768 " X: 32768
+
+Xcheck 34695
+
+" Leave F and G for execution as scripts in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 2: :endwhile in script {{{1
+"
+" Detect if a broken loop is (incorrectly) reactivated by the
+" :endwhile. Use a :finish to prevent an endless loop, and place
+" this test before others that might hang to get a meaningful result
+" on an error.
+"
+" This test executes the bodies of the functions F and G from the
+" previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+ExecAsScript F " X: 1 + 2 + 4
+Xpath 128 " X: 128
+
+ExecAsScript G " X: 256 + 512 + 1024
+Xpath 32768 " X: 32768
+
+unlet first
+delfunction F
+delfunction G
+
+Xcheck 34695
+
+
+"-------------------------------------------------------------------------------
+" Test 3: :if, :elseif, :while, :continue, :break {{{1
+"-------------------------------------------------------------------------------
+
+XpathINIT
+if 1
+ Xpath 1 " X: 1
+ let loops = 3
+ XloopINIT 2 512
+ while loops > -1 " main loop: loops == 3, 2, 1 (which breaks)
+ if loops <= 0
+ let break_err = 1
+ let loops = -1
+ else " 3: 2: 1:
+ Xloop 1 " X: 2 + 2*512 + 2*512*512
+ endif
+ if (loops == 2)
+ while loops == 2 " dummy loop
+ Xloop 2 " X: 4*512
+ let loops = loops - 1
+ continue " stop dummy loop
+ Xloop 4 " X: 0
+ endwhile
+ XloopNEXT
+ continue " continue main loop
+ Xloop 8 " X: 0
+ elseif (loops == 1)
+ let p = 1
+ while p " dummy loop
+ Xloop 16 " X: 32*512*512
+ let p = 0
+ break " break dummy loop
+ Xloop 32 " X: 0
+ endwhile
+ Xloop 64 " X: 128*512*512
+ unlet p
+ break " break main loop
+ Xloop 128 " X: 0
+ endif
+ if (loops > 0)
+ Xloop 256 " X: 512
+ endif
+ while loops == 3 " dummy loop
+ let loops = loops - 1
+ endwhile " end dummy loop
+ XloopNEXT
+ endwhile " end main loop
+ Xpath 268435456 " X: 1024*512*512
+else
+ Xpath 536870912 " X: 0
+endif
+Xpath 1073741824 " X: 4096*512*512
+if exists("break_err")
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ unlet break_err
+endif
+
+unlet loops
+
+Xcheck 1384648195
+
+
+"-------------------------------------------------------------------------------
+" Test 4: :return {{{1
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ if 1
+ Xpath 1 " X: 1
+ let loops = 3
+ XloopINIT 2 16
+ while loops > 0 " 3: 2: 1:
+ Xloop 1 " X: 2 + 2*16 + 0*16*16
+ if (loops == 2)
+ Xloop 2 " X: 4*16
+ return
+ Xloop 4 " X: 0
+ endif
+ Xloop 8 " X: 16
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 8192 " X: 0
+ else
+ Xpath 16384 " X: 0
+ endif
+endfunction
+
+call F()
+Xpath 32768 " X: 8*16*16*16
+
+Xcheck 32883
+
+" Leave F for execution as a script in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 5: :finish {{{1
+"
+" This test executes the body of the function F from the previous test
+" as a script file (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+ExecAsScript F " X: 1 + 2 + 2*16 + 4*16 + 16
+Xpath 32768 " X: 32768
+
+unlet loops
+delfunction F
+
+Xcheck 32883
+
+
+"-------------------------------------------------------------------------------
+" Test 6: Defining functions in :while loops {{{1
+"
+" Functions can be defined inside other functions. An inner function
+" gets defined when the outer function is executed. Functions may
+" also be defined inside while loops. Expressions in braces for
+" defining the function name are allowed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ " The command CALL collects the argument of all its invocations in "calls"
+ " when used from a function (that is, when the global variable "calls" needs
+ " the "g:" prefix). This is to check that the function code is skipped when
+ " the function is defined. For inner functions, do so only if the outer
+ " function is not being executed.
+ "
+ let calls = ""
+ com! -nargs=1 CALL
+ \ if !exists("calls") && !exists("outer") |
+ \ let g:calls = g:calls . <args> |
+ \ endif
+
+
+ XloopINIT! 1 16
+
+ let i = 0
+ while i < 3
+
+ XloopNEXT
+ let i = i + 1
+
+ if i == 1
+ Xloop 1 " X: 1
+ function! F1(arg)
+ CALL a:arg
+ let outer = 1
+
+ XloopINIT! 4096 4
+ let j = 0
+ while j < 1
+ XloopNEXT
+ Xloop 1 " X: 4096
+ let j = j + 1
+ function! G1(arg)
+ CALL a:arg
+ endfunction
+ Xloop 2 " X: 8192
+ endwhile
+ endfunction
+ Xloop 2 " X: 2
+
+ continue
+ endif
+
+ Xloop 4 " X: 4 * (16 + 256)
+ function! F{i}(i, arg)
+ CALL a:arg
+ let outer = 1
+
+ XloopINIT! 16384 4
+ if a:i == 3
+ XloopNEXT
+ XloopNEXT
+ XloopNEXT
+ endif
+ let k = 0
+ while k < 3
+ XloopNEXT
+ Xloop 1 " X: 16384*(1+4+16+64+256+1024)
+ let k = k + 1
+ function! G{a:i}{k}(arg)
+ CALL a:arg
+ endfunction
+ Xloop 2 " X: 32768*(1+4+16+64+256+1024)
+ endwhile
+ endfunction
+ Xloop 8 " X: 8 * (16 + 256)
+
+ endwhile
+
+ if exists("*G1")
+ Xpath 67108864 " X: 0
+ endif
+ if exists("*F1")
+ call F1("F1")
+ if exists("*G1")
+ call G1("G1")
+ endif
+ endif
+
+ if exists("G21") || exists("G21") || exists("G21")
+ Xpath 134217728 " X: 0
+ endif
+ if exists("*F2")
+ call F2(2, "F2")
+ if exists("*G21")
+ call G21("G21")
+ endif
+ if exists("*G22")
+ call G22("G22")
+ endif
+ if exists("*G23")
+ call G23("G23")
+ endif
+ endif
+
+ if exists("G31") || exists("G31") || exists("G31")
+ Xpath 268435456 " X: 0
+ endif
+ if exists("*F3")
+ call F3(3, "F3")
+ if exists("*G31")
+ call G31("G31")
+ endif
+ if exists("*G32")
+ call G32("G32")
+ endif
+ if exists("*G33")
+ call G33("G33")
+ endif
+ endif
+
+ Xpath 536870912 " X: 536870912
+
+ if calls != "F1G1F2G21G22G23F3G31G32G33"
+ Xpath 1073741824 " X: 0
+ Xout "calls is" calls
+ endif
+
+ delfunction F1
+ delfunction G1
+ delfunction F2
+ delfunction G21
+ delfunction G22
+ delfunction G23
+ delfunction G31
+ delfunction G32
+ delfunction G33
+
+endif
+
+Xcheck 603978947
+
+
+"-------------------------------------------------------------------------------
+" Test 7: Continuing on errors outside functions {{{1
+"
+" On an error outside a function, the script processing continues
+" at the line following the outermost :endif or :endwhile. When not
+" inside an :if or :while, the script processing continues at the next
+" line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ asdf
+ Xpath 4 " X: 0
+ break
+ endwhile | Xpath 8 " X: 0
+ Xpath 16 " X: 0
+endif | Xpath 32 " X: 0
+Xpath 64 " X: 64
+
+while 1
+ Xpath 128 " X: 128
+ if 1
+ Xpath 256 " X: 256
+ asdf
+ Xpath 512 " X: 0
+ endif | Xpath 1024 " X: 0
+ Xpath 2048 " X: 0
+ break
+endwhile | Xpath 4096 " X: 0
+Xpath 8192 " X: 8192
+
+asdf
+Xpath 16384 " X: 16384
+
+asdf | Xpath 32768 " X: 0
+Xpath 65536 " X: 65536
+
+Xcheck 90563
+
+
+"-------------------------------------------------------------------------------
+" Test 8: Aborting and continuing on errors inside functions {{{1
+"
+" On an error inside a function without the "abort" attribute, the
+" script processing continues at the next line (unless the error was
+" in a :return command). On an error inside a function with the
+" "abort" attribute, the function is aborted and the script processing
+" continues after the function call; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ asdf
+ Xpath 4 " X: 4
+ asdf | Xpath 8 " X: 0
+ Xpath 16 " X: 16
+ break
+ endwhile
+ Xpath 32 " X: 32
+ endif | Xpath 64 " X: 64
+ Xpath 128 " X: 128
+
+ while 1
+ Xpath 256 " X: 256
+ if 1
+ Xpath 512 " X: 512
+ asdf
+ Xpath 1024 " X: 1024
+ asdf | Xpath 2048 " X: 0
+ Xpath 4096 " X: 4096
+ endif
+ Xpath 8192 " X: 8192
+ break
+ endwhile | Xpath 16384 " X: 16384
+ Xpath 32768 " X: 32768
+
+ return novar " returns (default return value 0)
+ Xpath 65536 " X: 0
+ return 1 " not reached
+endfunction
+
+function! G() abort
+ if 1
+ Xpath 131072 " X: 131072
+ while 1
+ Xpath 262144 " X: 262144
+ asdf " returns -1
+ Xpath 524288 " X: 0
+ break
+ endwhile
+ Xpath 1048576 " X: 0
+ endif | Xpath 2097152 " X: 0
+ Xpath Xpath 4194304 " X: 0
+
+ return -4 " not reached
+endfunction
+
+function! H() abort
+ while 1
+ Xpath 8388608 " X: 8388608
+ if 1
+ Xpath 16777216 " X: 16777216
+ asdf " returns -1
+ Xpath 33554432 " X: 0
+ endif
+ Xpath 67108864 " X: 0
+ break
+ endwhile | Xpath 134217728 " X: 0
+ Xpath 268435456 " X: 0
+
+ return -4 " not reached
+endfunction
+
+" Aborted functions (G and H) return -1.
+let sum = (F() + 1) - 4*G() - 8*H()
+Xpath 536870912 " X: 536870912
+if sum != 13
+ Xpath 1073741824 " X: 0
+ Xout "sum is" sum
+endif
+
+unlet sum
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 562493431
+
+
+"-------------------------------------------------------------------------------
+" Test 9: Continuing after aborted functions {{{1
+"
+" When a function with the "abort" attribute is aborted due to an
+" error, the next function back in the call hierarchy without an
+" "abort" attribute continues; the value -1 is returned then.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F() abort
+ Xpath 1 " X: 1
+ let result = G() " not aborted
+ Xpath 2 " X: 2
+ if result != 2
+ Xpath 4 " X: 0
+ endif
+ return 1
+endfunction
+
+function! G() " no abort attribute
+ Xpath 8 " X: 8
+ if H() != -1 " aborted
+ Xpath 16 " X: 0
+ endif
+ Xpath 32 " X: 32
+ return 2
+endfunction
+
+function! H() abort
+ Xpath 64 " X: 64
+ call I() " aborted
+ Xpath 128 " X: 0
+ return 4
+endfunction
+
+function! I() abort
+ Xpath 256 " X: 256
+ asdf " error
+ Xpath 512 " X: 0
+ return 8
+endfunction
+
+if F() != 1
+ Xpath 1024 " X: 0
+endif
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 363
+
+
+"-------------------------------------------------------------------------------
+" Test 10: :if, :elseif, :while argument parsing {{{1
+"
+" A '"' or '|' in an argument expression must not be mixed up with
+" a comment or a next command after a bar. Parsing errors should
+" be recognized.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+if 1 || strlen("\"") | Xpath 1 " X: 1
+ Xpath 2 " X: 2
+endif
+Xpath 4 " X: 4
+
+if 0
+elseif 1 || strlen("\"") | Xpath 8 " X: 8
+ Xpath 16 " X: 16
+endif
+Xpath 32 " X: 32
+
+while 1 || strlen("\"") | Xpath 64 " X: 64
+ Xpath 128 " X: 128
+ break
+endwhile
+Xpath 256 " X: 256
+
+let v:errmsg = ""
+if 1 ||| strlen("\"") | Xpath 512 " X: 0
+ Xpath 1024 " X: 0
+endif
+Xpath 2048 " X: 2048
+if !MSG('E15', "Invalid expression")
+ Xpath 4096 " X: 0
+endif
+
+let v:errmsg = ""
+if 0
+elseif 1 ||| strlen("\"") | Xpath 8192 " X: 0
+ Xpath 16384 " X: 0
+endif
+Xpath 32768 " X: 32768
+if !MSG('E15', "Invalid expression")
+ Xpath 65536 " X: 0
+endif
+
+let v:errmsg = ""
+while 1 ||| strlen("\"") | Xpath 131072 " X: 0
+ Xpath 262144 " X: 0
+ break
+endwhile
+Xpath 524288 " X: 524288
+if !MSG('E15', "Invalid expression")
+ Xpath 1048576 " X: 0
+endif
+
+delfunction MSG
+
+Xcheck 559615
+
+
+"-------------------------------------------------------------------------------
+" Test 11: :if, :elseif, :while argument evaluation after abort {{{1
+"
+" When code is skipped over due to an error, the boolean argument to
+" an :if, :elseif, or :while must not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let calls = 0
+
+function! P(num)
+ let g:calls = g:calls + a:num " side effect on call
+ return 0
+endfunction
+
+if 1
+ Xpath 1 " X: 1
+ asdf " error
+ Xpath 2 " X: 0
+ if P(1) " should not be called
+ Xpath 4 " X: 0
+ elseif !P(2) " should not be called
+ Xpath 8 " X: 0
+ else
+ Xpath 16 " X: 0
+ endif
+ Xpath 32 " X: 0
+ while P(4) " should not be called
+ Xpath 64 " X: 0
+ endwhile
+ Xpath 128 " X: 0
+endif
+
+if calls % 2
+ Xpath 256 " X: 0
+endif
+if (calls/2) % 2
+ Xpath 512 " X: 0
+endif
+if (calls/4) % 2
+ Xpath 1024 " X: 0
+endif
+Xpath 2048 " X: 2048
+
+unlet calls
+delfunction P
+
+Xcheck 2049
+
+
+"-------------------------------------------------------------------------------
+" Test 12: Expressions in braces in skipped code {{{1
+"
+" In code skipped over due to an error or inactive conditional,
+" an expression in braces as part of a variable or function name
+" should not be evaluated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 8
+
+function! NULL()
+ Xloop 1 " X: 0
+ return 0
+endfunction
+
+function! ZERO()
+ Xloop 2 " X: 0
+ return 0
+endfunction
+
+function! F0()
+ Xloop 4 " X: 0
+endfunction
+
+function! F1(arg)
+ Xpath 4096 " X: 0
+endfunction
+
+let V0 = 1
+
+Xpath 8192 " X: 8192
+echo 0 ? F{NULL() + V{ZERO()}}() : 1
+XloopNEXT
+
+Xpath 16384 " X: 16384
+if 0
+ Xpath 32768 " X: 0
+ call F{NULL() + V{ZERO()}}()
+endif
+XloopNEXT
+
+Xpath 65536 " X: 65536
+if 1
+ asdf " error
+ Xpath 131072 " X: 0
+ call F1(F{NULL() + V{ZERO()}}())
+endif
+XloopNEXT
+
+Xpath 262144 " X: 262144
+if 1
+ asdf " error
+ Xpath 524288 " X: 0
+ call F{NULL() + V{ZERO()}}()
+endif
+
+Xcheck 352256
+
+
+"-------------------------------------------------------------------------------
+" Test 13: Failure in argument evaluation for :while {{{1
+"
+" A failure in the expression evaluation for the condition of a :while
+" causes the whole :while loop until the matching :endwhile being
+" ignored. Continuation is at the next following line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+Xpath 1 " X: 1
+while asdf
+ Xpath 2 " X: 0
+ while 1
+ Xpath 4 " X: 0
+ break
+ endwhile
+ Xpath 8 " X: 0
+ break
+endwhile
+Xpath 16 " X: 16
+
+while asdf | Xpath 32 | endwhile | Xpath 64 " X: 0
+Xpath 128 " X: 128
+
+Xcheck 145
+
+
+"-------------------------------------------------------------------------------
+" Test 14: Failure in argument evaluation for :if {{{1
+"
+" A failure in the expression evaluation for the condition of an :if
+" does not cause the corresponding :else or :endif being matched to
+" a previous :if/:elseif. Neither of both branches of the failed :if
+" are executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+XloopINIT 1 256
+
+function! F()
+ Xloop 1 " X: 1 + 256 * 1
+ let x = 0
+ if x " false
+ Xloop 2 " X: 0 + 256 * 0
+ elseif !x " always true
+ Xloop 4 " X: 4 + 256 * 4
+ let x = 1
+ if g:boolvar " possibly undefined
+ Xloop 8 " X: 8 + 256 * 0
+ else
+ Xloop 16 " X: 0 + 256 * 0
+ endif
+ Xloop 32 " X: 32 + 256 * 32
+ elseif x " never executed
+ Xloop 64 " X: 0 + 256 * 0
+ endif
+ Xloop 128 " X: 128 + 256 * 128
+endfunction
+
+let boolvar = 1
+call F()
+
+XloopNEXT
+unlet boolvar
+call F()
+
+delfunction F
+
+Xcheck 42413
+
+
+"-------------------------------------------------------------------------------
+" Test 15: Failure in argument evaluation for :if (bar) {{{1
+"
+" Like previous test, except that the failing :if ... | ... | :endif
+" is in a single line.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+XloopINIT 1 256
+
+function! F()
+ Xloop 1 " X: 1 + 256 * 1
+ let x = 0
+ if x " false
+ Xloop 2 " X: 0 + 256 * 0
+ elseif !x " always true
+ Xloop 4 " X: 4 + 256 * 4
+ let x = 1
+ if g:boolvar | Xloop 8 | else | Xloop 16 | endif " X: 8
+ Xloop 32 " X: 32 + 256 * 32
+ elseif x " never executed
+ Xloop 64 " X: 0 + 256 * 0
+ endif
+ Xloop 128 " X: 128 + 256 * 128
+endfunction
+
+let boolvar = 1
+call F()
+
+XloopNEXT
+unlet boolvar
+call F()
+
+delfunction F
+
+Xcheck 42413
+
+
+"-------------------------------------------------------------------------------
+" Test 16: Double :else or :elseif after :else {{{1
+"
+" Multiple :elses or an :elseif after an :else are forbidden.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F() abort
+ if 0
+ Xpath 1 " X: 0
+ else
+ Xpath 2 " X: 2
+ else " aborts function
+ Xpath 4 " X: 0
+ endif
+endfunction
+
+function! G() abort
+ if 0
+ Xpath 8 " X: 0
+ else
+ Xpath 16 " X: 16
+ elseif 1 " aborts function
+ Xpath 32 " X: 0
+ else
+ Xpath 64 " X: 0
+ endif
+endfunction
+
+function! H() abort
+ if 0
+ Xpath 128 " X: 0
+ elseif 0
+ Xpath 256 " X: 0
+ else
+ Xpath 512 " X: 512
+ else " aborts function
+ Xpath 1024 " X: 0
+ endif
+endfunction
+
+function! I() abort
+ if 0
+ Xpath 2048 " X: 0
+ elseif 0
+ Xpath 4096 " X: 0
+ else
+ Xpath 8192 " X: 8192
+ elseif 1 " aborts function
+ Xpath 16384 " X: 0
+ else
+ Xpath 32768 " X: 0
+ endif
+endfunction
+
+call F()
+call G()
+call H()
+call I()
+
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 8722
+
+
+"-------------------------------------------------------------------------------
+" Test 17: Nesting of unmatched :if or :endif inside a :while {{{1
+"
+" The :while/:endwhile takes precedence in nesting over an unclosed
+" :if or an unopened :endif.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+let messages = ""
+
+" While loops inside a function are continued on error.
+function! F()
+ let v:errmsg = ""
+ XloopINIT 1 16
+ let loops = 3
+ while loops > 0
+ let loops = loops - 1 " 2: 1: 0:
+ Xloop 1 " X: 1 + 1*16 + 1*16*16
+ if (loops == 1)
+ Xloop 2 " X: 2*16
+ XloopNEXT
+ continue
+ elseif (loops == 0)
+ Xloop 4 " X: 4*16*16
+ break
+ elseif 1
+ Xloop 8 " X: 8
+ XloopNEXT
+ " endif missing!
+ endwhile " :endwhile after :if 1
+ Xpath 4096 " X: 16*16*16
+ if MSG('E171', "Missing :endif")
+ let g:messages = g:messages . "A"
+ endif
+
+ let v:errmsg = ""
+ XloopINIT! 8192 4
+ let loops = 2
+ while loops > 0 " 2: 1:
+ XloopNEXT
+ let loops = loops - 1
+ Xloop 1 " X: 8192 + 8192*4
+ if 0
+ Xloop 2 " X: 0
+ " endif missing
+ endwhile " :endwhile after :if 0
+ Xpath 131072 " X: 8192*4*4
+ if MSG('E171', "Missing :endif")
+ let g:messages = g:messages . "B"
+ endif
+
+ let v:errmsg = ""
+ XloopINIT 262144 4
+ let loops = 2
+ while loops > 0 " 2: 1:
+ let loops = loops - 1
+ Xloop 1 " X: 262144 + 262144 * 4
+ " if missing!
+ endif " :endif without :if in while
+ Xloop 2 " X: 524288 + 524288 * 4
+ XloopNEXT
+ endwhile
+ Xpath 4194304 " X: 262144*4*4
+ if MSG('E580', ":endif without :if")
+ let g:messages = g:messages . "C"
+ endif
+endfunction
+
+call F()
+
+" Error continuation outside a function is at the outermost :endwhile or :endif.
+let v:errmsg = ""
+XloopINIT! 8388608 4
+let loops = 2
+while loops > 0 " 2: 1:
+ XloopNEXT
+ let loops = loops - 1
+ Xloop 1 " X: 8388608 + 0 * 4
+ if 0
+ Xloop 2 " X: 0
+ " endif missing! Following :endwhile fails.
+endwhile | Xpath 134217728 " X: 0
+Xpath 268435456 " X: 2*8388608*4*4
+if MSG('E171', "Missing :endif")
+ let messages = g:messages . "D"
+endif
+
+if messages != "ABCD"
+ Xpath 536870912 " X: 0
+ Xout "messages is" messages "instead of ABCD"
+endif
+
+unlet loops messages
+delfunction F
+delfunction MSG
+
+Xcheck 285127993
+
+
+"-------------------------------------------------------------------------------
+" Test 18: Interrupt (Ctrl-C pressed) {{{1
+"
+" On an interrupt, the script processing is terminated immediately.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ if 1
+ Xpath 1 " X: 1
+ while 1
+ Xpath 2 " X: 2
+ if 1
+ Xpath 4 " X: 4
+ "INTERRUPT
+ Xpath 8 " X: 0
+ break
+ finish
+ endif | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+ endwhile | Xpath 64 " X: 0
+ Xpath 128 " X: 0
+ endif | Xpath 256 " X: 0
+ Xpath 512 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 1024 " X: 1024
+ "INTERRUPT
+ Xpath 2048 " X: 0
+ endtry | Xpath 4096 " X: 0
+ Xpath 8192 " X: 0
+endif
+
+if ExtraVim()
+ function! F()
+ if 1
+ Xpath 16384 " X: 16384
+ while 1
+ Xpath 32768 " X: 32768
+ if 1
+ Xpath 65536 " X: 65536
+ "INTERRUPT
+ Xpath 131072 " X: 0
+ break
+ return
+ endif | Xpath 262144 " X: 0
+ Xpath Xpath 524288 " X: 0
+ endwhile | Xpath 1048576 " X: 0
+ Xpath Xpath 2097152 " X: 0
+ endif | Xpath Xpath 4194304 " X: 0
+ Xpath Xpath 8388608 " X: 0
+ endfunction
+
+ call F() | Xpath 16777216 " X: 0
+ Xpath 33554432 " X: 0
+endif
+
+if ExtraVim()
+ function! G()
+ try
+ Xpath 67108864 " X: 67108864
+ "INTERRUPT
+ Xpath 134217728 " X: 0
+ endtry | Xpath 268435456 " X: 0
+ Xpath 536870912 " X: 0
+ endfunction
+
+ call G() | Xpath 1073741824 " X: 0
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ " X: 0
+endif
+
+Xcheck 67224583
+
+
+"-------------------------------------------------------------------------------
+" Test 19: Aborting on errors inside :try/:endtry {{{1
+"
+" An error in a command dynamically enclosed in a :try/:endtry region
+" aborts script processing immediately. It does not matter whether
+" the failing command is outside or inside a function and whether a
+" function has an "abort" attribute.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! F() abort
+ Xpath 1 " X: 1
+ asdf
+ Xpath 2 " X: 0
+ endfunction
+
+ try
+ Xpath 4 " X: 4
+ call F()
+ Xpath 8 " X: 0
+ endtry | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+endif
+
+if ExtraVim()
+ function! G()
+ Xpath 64 " X: 64
+ asdf
+ Xpath 128 " X: 0
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ call G()
+ Xpath 512 " X: 0
+ endtry | Xpath 1024 " X: 0
+ Xpath 2048 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 4096 " X: 4096
+ asdf
+ Xpath 8192 " X: 0
+ endtry | Xpath 16384 " X: 0
+ Xpath 32768 " X: 0
+endif
+
+if ExtraVim()
+ if 1
+ try
+ Xpath 65536 " X: 65536
+ asdf
+ Xpath 131072 " X: 0
+ endtry | Xpath 262144 " X: 0
+ endif | Xpath 524288 " X: 0
+ Xpath 1048576 " X: 0
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 2097152 " X: 2097152
+ asdf
+ Xpath 4194304 " X: 0
+ endtry | Xpath 8388608 " X: 0
+ endwhile | Xpath 16777216 " X: 0
+ Xpath 33554432 " X: 0
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+" try
+ Xpath 67108864 " X: 67108864
+ endwhile | Xpath 134217728 " X: 0
+ Xpath 268435456 " X: 0
+endif
+
+Xcheck 69275973
+"-------------------------------------------------------------------------------
+" Test 20: Aborting on errors after :try/:endtry {{{1
+"
+" When an error occurs after the last active :try/:endtry region has
+" been left, termination behavior is as if no :try/:endtry has been
+" seen.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 1 " X: 1
+ endtry
+ asdf
+ endwhile | Xpath 2 " X: 0
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 8 " X: 8
+ break
+ Xpath 16 " X: 0
+ endtry
+ endwhile
+ Xpath 32 " X: 32
+ asdf
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 128 " X: 128
+ break
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ endtry
+ endwhile
+ Xpath 1024 " X: 1024
+ asdf
+ Xpath 2048 " X: 2048
+endif
+
+if ExtraVim()
+ while 1
+ try
+ Xpath 4096 " X: 4096
+ finally
+ Xpath 8192 " X: 8192
+ break
+ Xpath 16384 " X: 0
+ endtry
+ endwhile
+ Xpath 32768 " X: 32768
+ asdf
+ Xpath 65536 " X: 65536
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 131072 " X: 131072
+ continue
+ Xpath 262144 " X: 0
+ endtry
+ endwhile
+ Xpath 524288 " X: 524288
+ asdf
+ Xpath 1048576 " X: 1048576
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 2097152 " X: 2097152
+ continue
+ Xpath 4194304 " X: 0
+ finally
+ Xpath 8388608 " X: 8388608
+ endtry
+ endwhile
+ Xpath 16777216 " X: 16777216
+ asdf
+ Xpath 33554432 " X: 33554432
+endif
+
+if ExtraVim()
+ let p = 1
+ while p
+ let p = 0
+ try
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ continue
+ Xpath 268435456 " X: 0
+ endtry
+ endwhile
+ Xpath 536870912 " X: 536870912
+ asdf
+ Xpath 1073741824 " X: 1073741824
+endif
+
+Xcheck 1874575085
+
+
+"-------------------------------------------------------------------------------
+" Test 21: :finally for :try after :continue/:break/:return/:finish {{{1
+"
+" If a :try conditional stays inactive due to a preceding :continue,
+" :break, :return, or :finish, its :finally clause should not be
+" executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function F()
+ let loops = 2
+ XloopINIT! 1 256
+ while loops > 0
+ XloopNEXT
+ let loops = loops - 1
+ try
+ if loops == 1
+ Xloop 1 " X: 1
+ continue
+ Xloop 2 " X: 0
+ elseif loops == 0
+ Xloop 4 " X: 4*256
+ break
+ Xloop 8 " X: 0
+ endif
+
+ try " inactive
+ Xloop 16 " X: 0
+ finally
+ Xloop 32 " X: 0
+ endtry
+ finally
+ Xloop 64 " X: 64 + 64*256
+ endtry
+ Xloop 128 " X: 0
+ endwhile
+
+ try
+ Xpath 65536 " X: 65536
+ return
+ Xpath 131072 " X: 0
+ try " inactive
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 0
+ endtry
+ finally
+ Xpath 1048576 " X: 1048576
+ endtry
+ Xpath 2097152 " X: 0
+ endfunction
+
+ try
+ Xpath 4194304 " X: 4194304
+ call F()
+ Xpath 8388608 " X: 8388608
+ finish
+ Xpath 16777216 " X: 0
+ try " inactive
+ Xpath 33554432 " X: 0
+ finally
+ Xpath 67108864 " X: 0
+ endtry
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+ Xpath 268435456 " X: 0
+endif
+
+Xcheck 147932225
+
+
+"-------------------------------------------------------------------------------
+" Test 22: :finally for a :try after an error/interrupt/:throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding error or
+" interrupt or :throw, its :finally clause should not be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! Error()
+ try
+ asdf " aborting error, triggering error exception
+ endtry
+ endfunction
+
+ Xpath 1 " X: 1
+ call Error()
+ Xpath 2 " X: 0
+
+ if 1 " not active due to error
+ try " not active since :if inactive
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 0
+ endtry
+ endif
+
+ try " not active due to error
+ Xpath 16 " X: 0
+ finally
+ Xpath 32 " X: 0
+ endtry
+endif
+
+if ExtraVim()
+ function! Interrupt()
+ try
+ "INTERRUPT " triggering interrupt exception
+ endtry
+ endfunction
+
+ Xpath 64 " X: 64
+ call Interrupt()
+ Xpath 128 " X: 0
+
+ if 1 " not active due to interrupt
+ try " not active since :if inactive
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 0
+ endtry
+ endif
+
+ try " not active due to interrupt
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 0
+ endtry
+endif
+
+if ExtraVim()
+ function! Throw()
+ throw "xyz"
+ endfunction
+
+ Xpath 4096 " X: 4096
+ call Throw()
+ Xpath 8192 " X: 0
+
+ if 1 " not active due to :throw
+ try " not active since :if inactive
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 0
+ endtry
+ endif
+
+ try " not active due to :throw
+ Xpath 65536 " X: 0
+ finally
+ Xpath 131072 " X: 0
+ endtry
+endif
+
+Xcheck 4161
+
+
+"-------------------------------------------------------------------------------
+" Test 23: :catch clauses for a :try after a :throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding :throw,
+" none of its :catch clauses should be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ throw "xyz"
+ Xpath 2 " X: 0
+
+ if 1 " not active due to :throw
+ try " not active since :if inactive
+ Xpath 4 " X: 0
+ catch /xyz/
+ Xpath 8 " X: 0
+ endtry
+ endif
+ catch /xyz/
+ Xpath 16 " X: 16
+ endtry
+
+ Xpath 32 " X: 32
+ throw "abc"
+ Xpath 64 " X: 0
+
+ try " not active due to :throw
+ Xpath 128 " X: 0
+ catch /abc/
+ Xpath 256 " X: 0
+ endtry
+endif
+
+Xcheck 49
+
+
+"-------------------------------------------------------------------------------
+" Test 24: :endtry for a :try after a :throw {{{1
+"
+" If a :try conditional stays inactive due to a preceding :throw,
+" its :endtry should not rethrow the exception to the next surrounding
+" active :try conditional.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try " try 1
+ try " try 2
+ Xpath 1 " X: 1
+ throw "xyz" " makes try 2 inactive
+ Xpath 2 " X: 0
+
+ try " try 3
+ Xpath 4 " X: 0
+ endtry " no rethrow to try 1
+ catch /xyz/ " should catch although try 2 inactive
+ Xpath 8 " X: 8
+ endtry
+ catch /xyz/ " try 1 active, but exception already caught
+ Xpath 16 " X: 0
+ endtry
+ Xpath 32 " X: 32
+endif
+
+Xcheck 41
+
+
+"-------------------------------------------------------------------------------
+" Test 25: Executing :finally clauses on normal control flow {{{1
+"
+" Control flow in a :try conditional should always fall through to its
+" :finally clause. A :finally clause of a :try conditional inside an
+" inactive conditional should never be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ let loops = 3
+ XloopINIT 1 256
+ while loops > 0 " 3: 2: 1:
+ Xloop 1 " X: 1 + 1*256 + 1*256*256
+ if loops >= 2
+ try
+ Xloop 2 " X: 2 + 2*256
+ if loops == 2
+ try
+ Xloop 4 " X: 4*256
+ finally
+ Xloop 8 " X: 8*256
+ endtry
+ endif
+ finally
+ Xloop 16 " X: 16 + 16*256
+ if loops == 2
+ try
+ Xloop 32 " X: 32*256
+ finally
+ Xloop 64 " X: 64*256
+ endtry
+ endif
+ endtry
+ endif
+ Xloop 128 " X: 128 + 128*256 + 128*256*256
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 16777216 " X: 16777216
+endfunction
+
+if 1
+ try
+ Xpath 33554432 " X: 33554432
+ call F()
+ Xpath 67108864 " X: 67108864
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry
+else
+ try
+ Xpath 268435456 " X: 0
+ finally
+ Xpath 536870912 " X: 0
+ endtry
+endif
+
+delfunction F
+
+Xcheck 260177811
+
+
+"-------------------------------------------------------------------------------
+" Test 26: Executing :finally clauses after :continue or :break {{{1
+"
+" For a :continue or :break dynamically enclosed in a :try/:endtry
+" region inside the next surrounding :while/:endwhile, if the
+" :continue/:break is before the :finally, the :finally clause is
+" executed first. If the :continue/:break is after the :finally, the
+" :finally clause is broken (like an :if/:endif region).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ let loops = 3
+ XloopINIT! 1 32
+ while loops > 0
+ XloopNEXT
+ try
+ try
+ if loops == 2 " 3: 2: 1:
+ Xloop 1 " X: 1*32
+ let loops = loops - 1
+ continue
+ elseif loops == 1
+ Xloop 2 " X: 2*32*32
+ break
+ finish
+ endif
+ Xloop 4 " X: 4
+ endtry
+ finally
+ Xloop 8 " X: 8 + 8*32 + 8*32*32
+ endtry
+ Xloop 16 " X: 16
+ let loops = loops - 1
+ endwhile
+ Xpath 32768 " X: 32768
+finally
+ Xpath 65536 " X: 65536
+ let loops = 3
+ XloopINIT 131072 16
+ while loops > 0
+ try
+ finally
+ try
+ if loops == 2
+ Xloop 1 " X: 131072*16
+ let loops = loops - 1
+ XloopNEXT
+ continue
+ elseif loops == 1
+ Xloop 2 " X: 131072*2*16*16
+ break
+ finish
+ endif
+ endtry
+ Xloop 4 " X: 131072*4
+ endtry
+ Xloop 8 " X: 131072*8
+ let loops = loops - 1
+ XloopNEXT
+ endwhile
+ Xpath 536870912 " X: 536870912
+endtry
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1681500476
+
+
+"-------------------------------------------------------------------------------
+" Test 27: Executing :finally clauses after :return {{{1
+"
+" For a :return command dynamically enclosed in a :try/:endtry region,
+" :finally clauses are executed and the called function is ended.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ return
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 8
+ endtry
+ Xpath 16 " X: 0
+ finally
+ Xpath 32 " X: 32
+ endtry
+ Xpath 64 " X: 0
+endfunction
+
+function! G()
+ try
+ Xpath 128 " X: 128
+ return
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ call F()
+ Xpath 1024 " X: 1024
+ endtry
+ Xpath 2048 " X: 0
+endfunction
+
+function! H()
+ try
+ Xpath 4096 " X: 4096
+ call G()
+ Xpath 8192 " X: 8192
+ finally
+ Xpath 16384 " X: 16384
+ return
+ Xpath 32768 " X: 0
+ endtry
+ Xpath 65536 " X: 0
+endfunction
+
+try
+ Xpath 131072 " X: 131072
+ call H()
+ Xpath 262144 " X: 262144
+finally
+ Xpath 524288 " X: 524288
+endtry
+Xpath 1048576 " X: 1048576
+
+Xcheck 1996459
+
+" Leave F, G, and H for execution as scripts in the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 28: Executing :finally clauses after :finish {{{1
+"
+" For a :finish command dynamically enclosed in a :try/:endtry region,
+" :finally clauses are executed and the sourced file is finished.
+"
+" This test executes the bodies of the functions F, G, and H from the
+" previous test as script files (:return replaced by :finish).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let scriptF = MakeScript("F") " X: 1 + 2 + 8 + 32
+let scriptG = MakeScript("G", scriptF) " X: 128 + 512 + 1024
+let scriptH = MakeScript("H", scriptG) " X: 4096 + 8192 + 16384
+
+try
+ Xpath 131072 " X: 131072
+ exec "source" scriptH
+ Xpath 262144 " X: 262144
+finally
+ Xpath 524288 " X: 524288
+endtry
+Xpath 1048576 " X: 1048576
+
+call delete(scriptF)
+call delete(scriptG)
+call delete(scriptH)
+unlet scriptF scriptG scriptH
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 1996459
+
+
+"-------------------------------------------------------------------------------
+" Test 29: Executing :finally clauses on errors {{{1
+"
+" After an error in a command dynamically enclosed in a :try/:endtry
+" region, :finally clauses are executed and the script processing is
+" terminated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ function! F()
+ while 1
+ try
+ Xpath 1 " X: 1
+ while 1
+ try
+ Xpath 2 " X: 2
+ asdf " error
+ Xpath 4 " X: 0
+ finally
+ Xpath 8 " X: 8
+ endtry | Xpath 16 " X: 0
+ Xpath 32 " X: 0
+ break
+ endwhile
+ Xpath 64 " X: 0
+ finally
+ Xpath 128 " X: 128
+ endtry | Xpath 256 " X: 0
+ Xpath 512 " X: 0
+ break
+ endwhile
+ Xpath 1024 " X: 0
+ endfunction
+
+ while 1
+ try
+ Xpath 2048 " X: 2048
+ while 1
+ call F()
+ Xpath 4096 " X: 0
+ break
+ endwhile | Xpath 8192 " X: 0
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ endtry | Xpath 65536 " X: 0
+ endwhile | Xpath 131072 " X: 0
+ Xpath 262144 " X: 0
+endif
+
+if ExtraVim()
+ function! G() abort
+ if 1
+ try
+ Xpath 524288 " X: 524288
+ asdf " error
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ endtry | Xpath 4194304 " X: 0
+ endif | Xpath 8388608 " X: 0
+ Xpath 16777216 " X: 0
+ endfunction
+
+ if 1
+ try
+ Xpath 33554432 " X: 33554432
+ call G()
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ endtry | Xpath 268435456 " X: 0
+ endif | Xpath 536870912 " X: 0
+ Xpath 1073741824 " X: 0
+endif
+
+Xcheck 170428555
+
+
+"-------------------------------------------------------------------------------
+" Test 30: Executing :finally clauses on interrupt {{{1
+"
+" After an interrupt in a command dynamically enclosed in
+" a :try/:endtry region, :finally clauses are executed and the
+" script processing is terminated.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ XloopINIT 1 16
+
+ function! F()
+ try
+ Xloop 1 " X: 1 + 1*16
+ "INTERRUPT
+ Xloop 2 " X: 0
+ finally
+ Xloop 4 " X: 4 + 4*16
+ endtry
+ Xloop 8 " X: 0
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ try
+ Xpath 512 " X: 512
+ "INTERRUPT
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ try
+ Xpath 4096 " X: 4096
+ try
+ Xpath 8192 " X: 8192
+ finally
+ Xpath 16384 " X: 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
+
+
+"-------------------------------------------------------------------------------
+" Test 32: Remembering the :return value on :finally {{{1
+"
+" If a :finally clause is executed due to a :return specifying
+" a value, this is the value visible to the caller if not overwritten
+" by a new :return in the :finally clause. A :return without a value
+" in the :finally clause overwrites with value 0.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ return "ABCD"
+ 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 8
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ return 16 + strlen(F())
+ Xpath 1024 " X: 0
+ endtry
+ Xpath 2048 " X: 0
+endfunction
+
+function! H()
+ try
+ Xpath 4096 " X: 4096
+ return 32
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ return
+ Xpath 32768 " X: 0
+ endtry
+ Xpath 65536 " X: 0
+endfunction
+
+function! I()
+ try
+ Xpath 131072 " X: 131072
+ finally
+ Xpath 262144 " X: 262144
+ return G() + H() + 64
+ Xpath 524288 " X: 0
+ endtry
+ Xpath 1048576 " X: 0
+endfunction
+
+let retcode = I()
+Xpath 2097152 " X: 2097152
+
+if retcode < 0
+ Xpath 4194304 " X: 0
+endif
+if retcode % 4
+ Xpath 8388608 " X: 0
+endif
+if (retcode/4) % 2
+ Xpath 16777216 " X: 16777216
+endif
+if (retcode/8) % 2
+ Xpath 33554432 " X: 0
+endif
+if (retcode/16) % 2
+ Xpath 67108864 " X: 67108864
+endif
+if (retcode/32) % 2
+ Xpath 134217728 " X: 0
+endif
+if (retcode/64) % 2
+ Xpath 268435456 " X: 268435456
+endif
+if retcode/128
+ Xpath 536870912 " X: 0
+endif
+
+unlet retcode
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+
+Xcheck 354833067
+
+
+"-------------------------------------------------------------------------------
+" Test 33: :return under :execute or user command and :finally {{{1
+"
+" A :return command may be executed under an ":execute" or from
+" a user command. Executing of :finally clauses and passing through
+" the return code works also then.
+"-------------------------------------------------------------------------------
+XpathINIT
+
+command! -nargs=? RETURN
+ \ try | return <args> | finally | return <args> * 2 | endtry
+
+function! F()
+ try
+ RETURN 8
+ Xpath 1 " X: 0
+ finally
+ Xpath 2 " X: 2
+ endtry
+ Xpath 4 " X: 0
+endfunction
+
+function! G()
+ try
+ RETURN 32
+ Xpath 8 " X: 0
+ finally
+ Xpath 16 " X: 16
+ RETURN 128
+ Xpath 32 " X: 0
+ endtry
+ Xpath 64 " X: 0
+endfunction
+
+function! H()
+ try
+ execute "try | return 512 | finally | return 1024 | endtry"
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ endtry
+ Xpath 512 " X: 0
+endfunction
+
+function! I()
+ try
+ execute "try | return 2048 | finally | return 4096 | endtry"
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ execute "try | return 8192 | finally | return 16384 | endtry"
+ Xpath 4096 " X: 0
+ endtry
+ Xpath 8192 " X: 0
+endfunction
+
+function! J()
+ try
+ RETURN 32768
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ return
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+endfunction
+
+function! K()
+ try
+ execute "try | return 131072 | finally | return 262144 | endtry"
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 524288
+ execute "try | return 524288 | finally | return | endtry"
+ Xpath 1048576 " X: 0
+ endtry
+ Xpath 2097152 " X: 0
+endfunction
+
+function! L()
+ try
+ return
+ Xpath 4194304 " X: 0
+ finally
+ Xpath 8388608 " X: 8388608
+ RETURN 1048576
+ Xpath 16777216 " X: 0
+ endtry
+ Xpath 33554432 " X: 0
+endfunction
+
+function! M()
+ try
+ return
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ execute "try | return 4194304 | finally | return 8388608 | endtry"
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+endfunction
+
+function! N()
+ RETURN 16777216
+endfunction
+
+function! O()
+ execute "try | return 67108864 | finally | return 134217728 | endtry"
+endfunction
+
+let sum = F() + G() + H() + I() + J() + K() + L() + M()
+let expected = 16 + 256 + 1024 + 16384 + 0 + 0 + 2097152 + 8388608
+let sum = sum + N() + O()
+let expected = expected + 33554432 + 134217728
+
+if sum == expected
+ Xout "sum = " . sum . " (ok)"
+else
+ Xout "sum = " . sum . ", expected: " . expected
+endif
+
+Xpath 1073741824 " X: 1073741824
+
+if sum != expected
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+endif
+
+unlet sum expected
+delfunction F
+delfunction G
+delfunction H
+delfunction I
+delfunction J
+delfunction K
+delfunction L
+delfunction M
+delfunction N
+delfunction O
+
+Xcheck 1216907538
+
+
+"-------------------------------------------------------------------------------
+" 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
+
+
+"-------------------------------------------------------------------------------
+" Test 41: Skipped :throw finding next command {{{1
+"
+" A :throw in an inactive conditional must not hide a following
+" command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F()
+ Xpath 1 " X: 1
+ if 0 | throw "never" | endif | Xpath 2 " X: 2
+ Xpath 4 " X: 4
+endfunction
+
+function! G()
+ Xpath 8 " X: 8
+ while 0 | throw "never" | endwhile | Xpath 16 " X: 16
+ Xpath 32 " X: 32
+endfunction
+
+function H()
+ Xpath 64 " X: 64
+ if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128
+ Xpath 256 " X: 256
+endfunction
+
+Xpath 512 " X: 512
+
+try
+ Xpath 1024 " X: 1024
+ call F()
+ Xpath 2048 " X: 2048
+catch /.*/
+ Xpath 4096 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 8192 " X: 8192
+
+try
+ Xpath 16384 " X: 16384
+ call G()
+ Xpath 32768 " X: 32768
+catch /.*/
+ Xpath 65536 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 131072 " X: 131072
+
+try
+ Xpath 262144 " X: 262144
+ call H()
+ Xpath 524288 " X: 524288
+catch /.*/
+ Xpath 1048576 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 2097152 " X: 2097152
+
+delfunction F
+delfunction G
+delfunction H
+
+Xcheck 3076095
+
+
+"-------------------------------------------------------------------------------
+" Test 42: Catching number and string exceptions {{{1
+"
+" When a number is thrown, it is converted to a string exception.
+" Numbers and strings may be caught by specifying a regular exception
+" as argument to the :catch command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+
+ try
+ Xpath 1 " X: 1
+ throw 4711
+ Xpath 2 " X: 0
+ catch /4711/
+ Xpath 4 " X: 4
+ endtry
+
+ try
+ Xpath 8 " X: 8
+ throw 4711
+ Xpath 16 " X: 0
+ catch /^4711$/
+ Xpath 32 " X: 32
+ endtry
+
+ try
+ Xpath 64 " X: 64
+ throw 4711
+ Xpath 128 " X: 0
+ catch /\d/
+ Xpath 256 " X: 256
+ endtry
+
+ try
+ Xpath 512 " X: 512
+ throw 4711
+ Xpath 1024 " X: 0
+ catch /^\d\+$/
+ Xpath 2048 " X: 2048
+ endtry
+
+ try
+ Xpath 4096 " X: 4096
+ throw "arrgh"
+ Xpath 8192 " X: 0
+ catch /arrgh/
+ Xpath 16384 " X: 16384
+ endtry
+
+ try
+ Xpath 32768 " X: 32768
+ throw "arrgh"
+ Xpath 65536 " X: 0
+ catch /^arrgh$/
+ Xpath 131072 " X: 131072
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ throw "arrgh"
+ Xpath 524288 " X: 0
+ catch /\l/
+ Xpath 1048576 " X: 1048576
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ throw "arrgh"
+ Xpath 4194304 " X: 0
+ catch /^\l\+$/
+ Xpath 8388608 " X: 8388608
+ endtry
+
+ try
+ try
+ Xpath 16777216 " X: 16777216
+ throw "ARRGH"
+ Xpath 33554432 " X: 0
+ catch /^arrgh$/
+ Xpath 67108864 " X: 0
+ endtry
+ catch /^\carrgh$/
+ Xpath 134217728 " X: 134217728
+ endtry
+
+ try
+ Xpath 268435456 " X: 268435456
+ throw ""
+ Xpath 536870912 " X: 0
+ catch /^$/
+ Xpath 1073741824 " X: 1073741824
+ endtry
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xcheck 1505155949
+
+
+"-------------------------------------------------------------------------------
+" Test 43: Selecting the correct :catch clause {{{1
+"
+" When an exception is thrown and there are multiple :catch clauses,
+" the first matching one is taken.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 1024
+let loops = 3
+while loops > 0
+ try
+ if loops == 3
+ Xloop 1 " X: 1
+ throw "a"
+ Xloop 2 " X: 0
+ elseif loops == 2
+ Xloop 4 " X: 4*1024
+ throw "ab"
+ Xloop 8 " X: 0
+ elseif loops == 1
+ Xloop 16 " X: 16*1024*1024
+ throw "abc"
+ Xloop 32 " X: 0
+ endif
+ catch /abc/
+ Xloop 64 " X: 64*1024*1024
+ catch /ab/
+ Xloop 128 " X: 128*1024
+ catch /.*/
+ Xloop 256 " X: 256
+ catch /a/
+ Xloop 512 " X: 0
+ endtry
+
+ let loops = loops - 1
+ XloopNEXT
+endwhile
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1157763329
+
+
+"-------------------------------------------------------------------------------
+" Test 44: Missing or empty :catch patterns {{{1
+"
+" A missing or empty :catch pattern means the same as /.*/, that is,
+" catches everything. To catch only empty exceptions, /^$/ must be
+" used. A :catch with missing, empty, or /.*/ argument also works
+" when followed by another command separated by a bar on the same
+" line. :catch patterns cannot be specified between ||. But other
+" pattern separators can be used instead of //.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ try
+ Xpath 1 " X: 1
+ throw ""
+ catch /^$/
+ Xpath 2 " X: 2
+ endtry
+
+ try
+ Xpath 4 " X: 4
+ throw ""
+ catch /.*/
+ Xpath 8 " X: 8
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ throw ""
+ catch //
+ Xpath 32 " X: 32
+ endtry
+
+ try
+ Xpath 64 " X: 64
+ throw ""
+ catch
+ Xpath 128 " X: 128
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ throw "oops"
+ catch /^$/
+ Xpath 512 " X: 0
+ catch /.*/
+ Xpath 1024 " X: 1024
+ endtry
+
+ try
+ Xpath 2048 " X: 2048
+ throw "arrgh"
+ catch /^$/
+ Xpath 4096 " X: 0
+ catch //
+ Xpath 8192 " X: 8192
+ endtry
+
+ try
+ Xpath 16384 " X: 16384
+ throw "brrr"
+ catch /^$/
+ Xpath 32768 " X: 0
+ catch
+ Xpath 65536 " X: 65536
+ endtry
+
+ try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry
+ " X: 131072 + 262144
+
+ try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry
+ " X: 524288 + 1048576
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ " Extra try level: if ":catch" without arguments below raises
+ " a syntax error because it misinterprets the "Xpath" as a pattern,
+ " let it be caught by the ":catch /.*/" below.
+ try
+ try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | :
+ endtry " X: 2097152 + 4194304
+ endtry
+ catch /.*/
+ let caught = 1
+ Xout v:exception "in" v:throwpoint
+ finally
+ if $VIMNOERRTHROW && v:errmsg != ""
+ Xout v:errmsg
+ endif
+ if caught || $VIMNOERRTHROW && v:errmsg != ""
+ Xpath 8388608 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ let cologne = 4711
+ try
+ try
+ Xpath 16777216 " X: 16777216
+ throw "throw cologne"
+ " Next lines catches all and throws 4711:
+ catch |throw cologne|
+ Xpath 33554432 " X: 0
+ endtry
+ catch /4711/
+ Xpath 67108864 " X: 67108864
+ endtry
+
+ try
+ Xpath 134217728 " X: 134217728
+ throw "plus"
+ catch +plus+
+ Xpath 268435456 " X: 268435456
+ endtry
+
+ Xpath 536870912 " X: 536870912
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! caught cologne
+
+Xcheck 1031761407
+
+
+"-------------------------------------------------------------------------------
+" Test 45: Catching exceptions from nested :try blocks {{{1
+"
+" When :try blocks are nested, an exception is caught by the innermost
+" try conditional that has a matching :catch clause.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 1024
+let loops = 3
+while loops > 0
+ try
+ try
+ try
+ try
+ if loops == 3
+ Xloop 1 " X: 1
+ throw "a"
+ Xloop 2 " X: 0
+ elseif loops == 2
+ Xloop 4 " X: 4*1024
+ throw "ab"
+ Xloop 8 " X: 0
+ elseif loops == 1
+ Xloop 16 " X: 16*1024*1024
+ throw "abc"
+ Xloop 32 " X: 0
+ endif
+ catch /abc/
+ Xloop 64 " X: 64*1024*1024
+ endtry
+ catch /ab/
+ Xloop 128 " X: 128*1024
+ endtry
+ catch /.*/
+ Xloop 256 " X: 256
+ endtry
+ catch /a/
+ Xloop 512 " X: 0
+ endtry
+
+ let loops = loops - 1
+ XloopNEXT
+endwhile
+Xpath 1073741824 " X: 1073741824
+
+unlet loops
+
+Xcheck 1157763329
+
+
+"-------------------------------------------------------------------------------
+" Test 46: Executing :finally after a :throw in nested :try {{{1
+"
+" When an exception is thrown from within nested :try blocks, the
+" :finally clauses of the non-catching try conditionals should be
+" executed before the matching :catch of the next surrounding :try
+" gets the control. If this also has a :finally clause, it is
+" executed afterwards.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let sum = 0
+
+try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ try
+ Xpath 4 " X: 4
+ try
+ Xpath 8 " X: 8
+ throw "ABC"
+ Xpath 16 " X: 0
+ catch /xyz/
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ if sum != 0
+ Xpath 128 " X: 0
+ endif
+ let sum = sum + 1
+ endtry
+ Xpath 256 " X: 0
+ catch /123/
+ Xpath 512 " X: 0
+ catch /321/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if sum != 1
+ Xpath 4096 " X: 0
+ endif
+ let sum = sum + 2
+ endtry
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ if sum != 3
+ Xpath 32768 " X: 0
+ endif
+ let sum = sum + 4
+ endtry
+ Xpath 65536 " X: 0
+catch /ABC/
+ Xpath 131072 " X: 131072
+ if sum != 7
+ Xpath 262144 " X: 0
+ endif
+ let sum = sum + 8
+finally
+ Xpath 524288 " X: 524288
+ if sum != 15
+ Xpath 1048576 " X: 0
+ endif
+ let sum = sum + 16
+endtry
+Xpath 65536 " X: 65536
+if sum != 31
+ Xpath 131072 " X: 0
+endif
+
+unlet sum
+
+Xcheck 739407
+
+
+"-------------------------------------------------------------------------------
+" Test 47: Throwing exceptions from a :catch clause {{{1
+"
+" When an exception is thrown from a :catch clause, it should not be
+" caught by a :catch of the same :try conditional. After executing
+" the :finally clause (if present), surrounding try conditionals
+" should be checked for a matching :catch.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+Xpath 1 " X: 1
+try
+ Xpath 2 " X: 2
+ try
+ Xpath 4 " X: 4
+ try
+ Xpath 8 " X: 8
+ throw "x1"
+ Xpath 16 " X: 0
+ catch /x1/
+ Xpath 32 " X: 32
+ try
+ Xpath 64 " X: 64
+ throw "x2"
+ Xpath 128 " X: 0
+ catch /x1/
+ Xpath 256 " X: 0
+ catch /x2/
+ Xpath 512 " X: 512
+ try
+ Xpath 1024 " X: 1024
+ throw "x3"
+ Xpath 2048 " X: 0
+ catch /x1/
+ Xpath 4096 " X: 0
+ catch /x2/
+ Xpath 8192 " X: 0
+ finally
+ Xpath 16384 " X: 16384
+ endtry
+ Xpath 32768 " X: 0
+ catch /x3/
+ Xpath 65536 " X: 0
+ endtry
+ Xpath 131072 " X: 0
+ catch /x1/
+ Xpath 262144 " X: 0
+ catch /x2/
+ Xpath 524288 " X: 0
+ catch /x3/
+ Xpath 1048576 " X: 0
+ finally
+ Xpath 2097152 " X: 2097152
+ endtry
+ Xpath 4194304 " X: 0
+ catch /x1/
+ Xpath 8388608 " X: 0
+ catch /x2/
+ Xpath 16777216 " X: 0
+ catch /x3/
+ Xpath 33554432 " X: 33554432
+ endtry
+ Xpath 67108864 " X: 67108864
+catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 268435456 " X: 268435456
+
+Xcheck 371213935
+
+
+"-------------------------------------------------------------------------------
+" Test 48: Throwing exceptions from a :finally clause {{{1
+"
+" When an exception is thrown from a :finally clause, it should not be
+" caught by a :catch of the same :try conditional. Surrounding try
+" conditionals should be checked for a matching :catch. A previously
+" thrown exception is discarded.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+
+ try
+ try
+ Xpath 1 " X: 1
+ catch /x1/
+ Xpath 2 " X: 0
+ finally
+ Xpath 4 " X: 4
+ throw "x1"
+ Xpath 8 " X: 0
+ endtry
+ Xpath 16 " X: 0
+ catch /x1/
+ Xpath 32 " X: 32
+ endtry
+ Xpath 64 " X: 64
+
+ try
+ try
+ Xpath 128 " X: 128
+ throw "x2"
+ Xpath 256 " X: 0
+ catch /x2/
+ Xpath 512 " X: 512
+ catch /x3/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ throw "x3"
+ Xpath 4096 " X: 0
+ endtry
+ Xpath 8192 " X: 0
+ catch /x2/
+ Xpath 16384 " X: 0
+ catch /x3/
+ Xpath 32768 " X: 32768
+ endtry
+ Xpath 65536 " X: 65536
+
+ try
+ try
+ try
+ Xpath 131072 " X: 131072
+ throw "x4"
+ Xpath 262144 " X: 0
+ catch /x5/
+ Xpath 524288 " X: 0
+ finally
+ Xpath 1048576 " X: 1048576
+ throw "x5" " discards "x4"
+ Xpath 2097152 " X: 0
+ endtry
+ Xpath 4194304 " X: 0
+ catch /x4/
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ endtry
+ Xpath 33554432 " X: 0
+ catch /x5/
+ Xpath 67108864 " X: 67108864
+ endtry
+ Xpath 134217728 " X: 134217728
+
+catch /.*/
+ Xpath 268435456 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+Xpath 536870912 " X: 536870912
+
+Xcheck 756255461
+
+
+"-------------------------------------------------------------------------------
+" Test 49: Throwing exceptions accross 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 accross 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: Throwing exceptions accross :execute and user commands {{{1
+"
+" A :throw command may be executed under an ":execute" or from
+" a user command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+command! -nargs=? THROW1 throw <args> | throw 1
+command! -nargs=? THROW2 try | throw <args> | endtry | throw 2
+command! -nargs=? THROW3 try | throw 3 | catch /3/ | throw <args> | endtry
+command! -nargs=? THROW4 try | throw 4 | finally | throw <args> | endtry
+
+try
+
+ try
+ try
+ Xpath 1 " X: 1
+ THROW1 "A"
+ catch /A/
+ Xpath 2 " X: 2
+ endtry
+ catch /1/
+ Xpath 4 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 8 " X: 8
+ THROW2 "B"
+ catch /B/
+ Xpath 16 " X: 16
+ endtry
+ catch /2/
+ Xpath 32 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 64 " X: 64
+ THROW3 "C"
+ catch /C/
+ Xpath 128 " X: 128
+ endtry
+ catch /3/
+ Xpath 256 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 512 " X: 512
+ THROW4 "D"
+ catch /D/
+ Xpath 1024 " X: 1024
+ endtry
+ catch /4/
+ Xpath 2048 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 4096 " X: 4096
+ execute 'throw "E" | throw 5'
+ catch /E/
+ Xpath 8192 " X: 8192
+ endtry
+ catch /5/
+ Xpath 16384 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 32768 " X: 32768
+ execute 'try | throw "F" | endtry | throw 6'
+ catch /F/
+ Xpath 65536 " X: 65536
+ endtry
+ catch /6/
+ Xpath 131072 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 262144 " X: 262144
+ execute'try | throw 7 | catch /7/ | throw "G" | endtry'
+ catch /G/
+ Xpath 524288 " X: 524288
+ endtry
+ catch /7/
+ Xpath 1048576 " X: 0
+ endtry
+
+ try
+ try
+ Xpath 2097152 " X: 2097152
+ execute 'try | throw 8 | finally | throw "H" | endtry'
+ catch /H/
+ Xpath 4194304 " X: 4194304
+ endtry
+ catch /8/
+ Xpath 8388608 " X: 0
+ endtry
+
+catch /.*/
+ Xpath 16777216 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 33554432 " X: 33554432
+
+delcommand THROW1
+delcommand THROW2
+delcommand THROW3
+delcommand THROW4
+
+Xcheck 40744667
+
+
+"-------------------------------------------------------------------------------
+" Test 52: Uncaught exceptions {{{1
+"
+" When an exception is thrown but not caught, an error message is
+" displayed when the script is terminated. In case of an interrupt
+" or error exception, the normal interrupt or error message(s) are
+" displayed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+function! MESSAGES(...)
+ try
+ exec "edit" g:msgfile
+ catch /^Vim(edit):/
+ return 0
+ endtry
+
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ let match = 1
+ norm gg
+
+ let num = a:0 / 2
+ let cnt = 1
+ while cnt <= num
+ let enr = a:{2*cnt - 1}
+ let emsg= a:{2*cnt}
+ let cnt = cnt + 1
+
+ if enr == ""
+ Xout "TODO: Add message number for:" emsg
+ elseif enr == "INT"
+ let enr = ""
+ endif
+ if enr == "" && !english
+ continue
+ endif
+ let pattern = (enr != "") ? enr . ':.*' : ''
+ if english
+ let pattern = pattern . emsg
+ endif
+ if !search(pattern, "W")
+ let match = 0
+ Xout "No match for:" pattern
+ endif
+ norm $
+ endwhile
+
+ bwipeout!
+ return match
+endfunction
+
+if ExtraVim(msgfile)
+ Xpath 1 " X: 1
+ throw "arrgh"
+endif
+
+Xpath 2 " X: 2
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 4 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 8 " X: 8
+ throw "oops"
+ catch /arrgh/
+ Xpath 16 " X: 0
+ endtry
+ Xpath 32 " X: 0
+endif
+
+Xpath 64 " X: 64
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ function! T()
+ throw "brrr"
+ endfunction
+
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ catch /.*/
+ Xpath 512 " X: 512
+ call T()
+ endtry
+ Xpath 1024 " X: 0
+endif
+
+Xpath 2048 " X: 2048
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 4096 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 8192 " X: 8192
+ throw "arrgh"
+ finally
+ Xpath 16384 " X: 16384
+ throw "brrr"
+ endtry
+ Xpath 32768 " X: 0
+endif
+
+Xpath 65536 " X: 65536
+if !MESSAGES('E605', "Exception not caught")
+ Xpath 131072 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 262144 " X: 262144
+ "INTERRUPT
+ endtry
+ Xpath 524288 " X: 0
+endif
+
+Xpath 1048576 " X: 1048576
+if !MESSAGES('INT', "Interrupted")
+ Xpath 2097152 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 4194304 " X: 4194304
+ let x = novar " error E121/E15; exception: E121
+ catch /E15:/ " should not catch
+ Xpath 8388608 " X: 0
+ endtry
+ Xpath 16777216 " X: 0
+endif
+
+Xpath 33554432 " X: 33554432
+if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression")
+ Xpath 67108864 " X: 0
+endif
+
+if ExtraVim(msgfile)
+ try
+ Xpath 134217728 " X: 134217728
+" unlet novar # " error E108/E488; exception: E488
+ catch /E108:/ " should not catch
+ Xpath 268435456 " X: 0
+ endtry
+ Xpath 536870912 " X: 0
+endif
+
+Xpath 1073741824 " X: 1073741824
+if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters")
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 1247112011
+
+" Leave MESSAGES() for the next tests.
+
+
+"-------------------------------------------------------------------------------
+" Test 53: Nesting errors: :endif/:else/:elseif {{{1
+"
+" For nesting errors of :if conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endif
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" endif
+" endwhile
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" endif
+" endtry
+endif
+if MESSAGES('E580', ":endif without :if")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" else
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" else
+" endwhile
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" else
+" endtry
+endif
+if MESSAGES('E581', ":else without :if")
+ Xpath 512 " X: 512
+endif
+
+if ExtraVim(msgfile)
+" elseif
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 1024 " X: 1024
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" elseif
+" endwhile
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 2048 " X: 2048
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 4096 " X: 4096
+endif
+
+if ExtraVim(msgfile)
+" try
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 8192 " X: 8192
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" elseif
+" endtry
+endif
+if MESSAGES('E582', ":elseif without :if")
+ Xpath 16384 " X: 16384
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" else
+" else
+" endif
+endif
+if MESSAGES('E583', "multiple :else")
+ Xpath 32768 " X: 32768
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" else
+" elseif 1
+" endif
+endif
+if MESSAGES('E584', ":elseif after :else")
+ Xpath 65536 " X: 65536
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 131071
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 54: Nesting errors: :while/:endwhile {{{1
+"
+" For nesting errors of :while conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" endwhile
+" endif
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" if 1
+" endwhile
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" finally
+" endwhile
+endif
+if MESSAGES('E600', "Missing :endtry")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" if 1
+" try
+" finally
+" endwhile
+endif
+if MESSAGES('E600', "Missing :endtry")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" finally
+" if 1
+" endwhile
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" endwhile
+" endtry
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" endwhile
+" endtry
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 512 " X: 512
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" try
+" throw "a"
+" catch /a/
+" endwhile
+" endtry
+" endwhile
+endif
+if MESSAGES('E588', ":endwhile without :while")
+ Xpath 1024 " X: 1024
+endif
+
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 2047
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 55: Nesting errors: :continue/:break {{{1
+"
+" For nesting errors of :continue and :break commands the correct
+" error messages should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" continue
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" continue
+" endif
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" continue
+" endtry
+endif
+if MESSAGES('E586', ":continue without :while")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" break
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" break
+" endif
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 256 " X: 256
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" break
+" endtry
+endif
+if MESSAGES('E587', ":break without :while")
+ Xpath 512 " X: 512
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+Xcheck 1023
+
+" Leave MESSAGES() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 56: Nesting errors: :endtry {{{1
+"
+" For nesting errors of :try conditionals the correct error messages
+" should be given.
+"
+" This test reuses the function MESSAGES() from the previous test.
+" This functions checks the messages in g:msgfile.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let msgfile = tempname()
+
+if ExtraVim(msgfile)
+" endtry
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 1 " X: 1
+endif
+
+if ExtraVim(msgfile)
+" if 1
+" endtry
+" endif
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 2 " X: 2
+endif
+
+if ExtraVim(msgfile)
+" while 1
+" endtry
+" endwhile
+endif
+if MESSAGES('E602', ":endtry without :try")
+ Xpath 4 " X: 4
+endif
+
+if ExtraVim(msgfile)
+" try
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 8 " X: 8
+endif
+
+if ExtraVim(msgfile)
+" try
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 16 " X: 16
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 32 " X: 32
+endif
+
+if ExtraVim(msgfile)
+" try
+" finally
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 64 " X: 64
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" if 1
+" endtry
+endif
+if MESSAGES('E171', "Missing :endif")
+ Xpath 128 " X: 128
+endif
+
+if ExtraVim(msgfile)
+" try
+" throw "a"
+" catch /a/
+" while 1
+" endtry
+endif
+if MESSAGES('E170', "Missing :endwhile")
+ Xpath 256 " X: 256
+endif
+
+call delete(msgfile)
+unlet msgfile
+
+delfunction MESSAGES
+
+Xcheck 511
+
+
+"-------------------------------------------------------------------------------
+" Test 57: v:exception and v:throwpoint for user exceptions {{{1
+"
+" v:exception evaluates to the value of the exception that was caught
+" most recently and is not finished. (A caught exception is finished
+" when the next ":catch", ":finally", or ":endtry" is reached.)
+" v:throwpoint evaluates to the script/function name and line number
+" where that exception has been thrown.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! FuncException()
+ let g:exception = v:exception
+endfunction
+
+function! FuncThrowpoint()
+ let g:throwpoint = v:throwpoint
+endfunction
+
+let scriptException = MakeScript("FuncException")
+let scriptThrowPoint = MakeScript("FuncThrowpoint")
+
+command! CmdException let g:exception = v:exception
+command! CmdThrowpoint let g:throwpoint = v:throwpoint
+
+XloopINIT! 1 2
+
+function! CHECK(n, exception, throwname, throwline)
+ XloopNEXT
+ let error = 0
+ if v:exception != a:exception
+ Xout a:n.": v:exception is" v:exception "instead of" a:exception
+ let error = 1
+ endif
+ if v:throwpoint !~ a:throwname
+ let name = escape(a:throwname, '\')
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name
+ let error = 1
+ endif
+ if v:throwpoint !~ a:throwline
+ let line = escape(a:throwline, '\')
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
+ let error = 1
+ endif
+ if error
+ Xloop 1 " X: 0
+ endif
+endfunction
+
+function! T(arg, line)
+ if a:line == 2
+ throw a:arg " in line 2
+ elseif a:line == 4
+ throw a:arg " in line 4
+ elseif a:line == 6
+ throw a:arg " in line 6
+ elseif a:line == 8
+ throw a:arg " in line 8
+ endif
+endfunction
+
+function! G(arg, line)
+ call T(a:arg, a:line)
+endfunction
+
+function! F(arg, line)
+ call G(a:arg, a:line)
+endfunction
+
+let scriptT = MakeScript("T")
+let scriptG = MakeScript("G", scriptT)
+let scriptF = MakeScript("F", scriptG)
+
+try
+ Xpath 32768 " X: 32768
+ call F("oops", 2)
+catch /.*/
+ Xpath 65536 " X: 65536
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ exec "let exception = v:exception"
+ exec "let throwpoint = v:throwpoint"
+ call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ CmdException
+ CmdThrowpoint
+ call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ call FuncException()
+ call FuncThrowpoint()
+ call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ exec "source" scriptException
+ exec "source" scriptThrowPoint
+ call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ try
+ Xpath 131072 " X: 131072
+ call G("arrgh", 4)
+ catch /.*/
+ Xpath 262144 " X: 262144
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>')
+ try
+ Xpath 524288 " X: 524288
+ let g:arg = "autsch"
+ let g:line = 6
+ exec "source" scriptF
+ catch /.*/
+ Xpath 1048576 " X: 1048576
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ " Symbolic links in tempname()s are not resolved, whereas resolving
+ " is done for v:throwpoint. Resolve the temporary file name for
+ " scriptT, so that it can be matched against v:throwpoint.
+ call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
+ finally
+ Xpath 2097152 " X: 2097152
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>')
+ try
+ Xpath 4194304 " X: 4194304
+ let g:arg = "brrrr"
+ let g:line = 8
+ exec "source" scriptG
+ catch /.*/
+ Xpath 8388608 " X: 8388608
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ " Resolve scriptT for matching it against v:throwpoint.
+ call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
+ finally
+ Xpath 16777216 " X: 16777216
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>')
+ endtry
+ Xpath 33554432 " X: 33554432
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>')
+ endtry
+ Xpath 67108864 " X: 67108864
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>')
+ finally
+ Xpath 134217728 " X: 134217728
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+ endtry
+ Xpath 268435456 " X: 268435456
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
+finally
+ Xpath 536870912 " X: 536870912
+ let exception = v:exception
+ let throwpoint = v:throwpoint
+ call CHECK(15, "", '^$', '^$')
+endtry
+
+Xpath 1073741824 " X: 1073741824
+
+unlet exception throwpoint
+delfunction FuncException
+delfunction FuncThrowpoint
+call delete(scriptException)
+call delete(scriptThrowPoint)
+unlet scriptException scriptThrowPoint
+delcommand CmdException
+delcommand CmdThrowpoint
+delfunction T
+delfunction G
+delfunction F
+call delete(scriptT)
+call delete(scriptG)
+call delete(scriptF)
+unlet scriptT scriptG scriptF
+
+Xcheck 2147450880
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 58: v:exception and v:throwpoint for error/interrupt exceptions {{{1
+"
+" v:exception and v:throwpoint work also for error and interrupt
+" exceptions.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! T(line)
+ if a:line == 2
+ delfunction T " error (function in use) in line 2
+ elseif a:line == 4
+ let dummy = 0 " INTERRUPT1 - interrupt in line 4
+ endif
+ endfunction
+
+ while 1
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ call T(2)
+ catch /.*/
+ let caught = 1
+ if v:exception !~ 'Vim(delfunction):'
+ Xpath 2 " X: 0
+ endif
+ if v:throwpoint !~ '\<T\>'
+ Xpath 4 " X: 0
+ endif
+ if v:throwpoint !~ '\<2\>'
+ Xpath 8 " X: 0
+ endif
+ finally
+ Xpath 16 " X: 16
+ if caught || $VIMNOERRTHROW
+ Xpath 32 " X: 32
+ endif
+ if v:exception != ""
+ Xpath 64 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 128 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 256 " X: 256
+ if v:exception != ""
+ Xpath 512 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 1024 " X: 0
+ endif
+
+ while 1
+ try
+ Xpath 2048 " X: 2048
+ let caught = 0
+ call T(4)
+ catch /.*/
+ let caught = 1
+ if v:exception != 'Vim:Interrupt'
+ Xpath 4096 " X: 0
+ endif
+ if v:throwpoint !~ '\<T\>'
+ Xpath 8192 " X: 0
+ endif
+ if v:throwpoint !~ '\<4\>'
+ Xpath 16384 " X: 0
+ endif
+ finally
+ Xpath 32768 " X: 32768
+ if caught || $VIMNOINTTHROW
+ Xpath 65536 " X: 65536
+ endif
+ if v:exception != ""
+ Xpath 131072 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 262144 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 524288 " X: 524288
+ if v:exception != ""
+ Xpath 1048576 " X: 0
+ endif
+ if v:throwpoint != ""
+ Xpath 2097152 " X: 0
+ endif
+
+endif
+
+Xcheck 624945
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 59: v:exception and v:throwpoint when discarding exceptions {{{1
+"
+" When a :catch clause is left by a ":break" etc or an error or
+" interrupt exception, v:exception and v:throwpoint are reset. They
+" are not affected by an exception that is discarded before being
+" caught.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ XloopINIT! 1 2
+
+ let sfile = expand("<sfile>")
+
+ function! LineNumber()
+ return substitute(substitute(v:throwpoint, g:sfile, '', ""),
+ \ '\D*\(\d*\).*', '\1', "")
+ endfunction
+
+ command! -nargs=1 SetLineNumber
+ \ try | throw "line" | catch /.*/ | let <args> = LineNumber() | endtry
+
+ " Check v:exception/v:throwpoint against second/fourth parameter if
+ " specified, check for being empty else.
+ function! CHECK(n, ...)
+ XloopNEXT
+ let exception = a:0 != 0 ? a:1 : "" " second parameter (optional)
+ let emsg = a:0 != 0 ? a:2 : "" " third parameter (optional)
+ let line = a:0 != 0 ? a:3 : 0 " fourth parameter (optional)
+ let error = 0
+ if emsg != ""
+ " exception is the error number, emsg the english error message text
+ if exception !~ '^E\d\+$'
+ Xout "TODO: Add message number for:" emsg
+ elseif v:lang == "C" || v:lang =~ '^[Ee]n'
+ if exception == "E492" && emsg == "Not an editor command"
+ let exception = '^Vim:' . exception . ': ' . emsg
+ else
+ let exception = '^Vim(\a\+):' . exception . ': ' . emsg
+ endif
+ else
+ if exception == "E492"
+ let exception = '^Vim:' . exception
+ else
+ let exception = '^Vim(\a\+):' . exception
+ endif
+ endif
+ endif
+ if exception == "" && v:exception != ""
+ Xout a:n.": v:exception is set:" v:exception
+ let error = 1
+ elseif exception != "" && v:exception !~ exception
+ Xout a:n.": v:exception (".v:exception.") does not match" exception
+ let error = 1
+ endif
+ if line == 0 && v:throwpoint != ""
+ Xout a:n.": v:throwpoint is set:" v:throwpoint
+ let error = 1
+ elseif line != 0 && v:throwpoint !~ '\<' . line . '\>'
+ Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
+ let error = 1
+ endif
+ if !error
+ Xloop 1 " X: 2097151
+ endif
+ endfunction
+
+ while 1
+ try
+ throw "x1"
+ catch /.*/
+ break
+ endtry
+ endwhile
+ call CHECK(1)
+
+ while 1
+ try
+ throw "x2"
+ catch /.*/
+ break
+ finally
+ call CHECK(2)
+ endtry
+ break
+ endwhile
+ call CHECK(3)
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+ throw "x3"
+ catch /.*/
+ SetLineNumber line_before_error
+ asdf
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(4, 'E492', "Not an editor command",
+ \ line_before_error + 1)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(4)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(5)
+
+ Xpath 2097152 " X: 2097152
+
+ while 1
+ try
+ let intcaught = 0
+ try
+ try
+ throw "x4"
+ catch /.*/
+ SetLineNumber two_lines_before_interrupt
+ "INTERRUPT
+ let dummy = 0
+ endtry
+ catch /.*/
+ let intcaught = 1
+ call CHECK(6, "Vim:Interrupt", '',
+ \ two_lines_before_interrupt + 2)
+ endtry
+ finally
+ if !intcaught && $VIMNOINTTHROW
+ call CHECK(6)
+ endif
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+ call CHECK(7)
+
+ Xpath 4194304 " X: 4194304
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x5"
+ " missing endif
+ catch /.*/
+ Xpath 8388608 " X: 0
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(8)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(9)
+
+ Xpath 16777216 " X: 16777216
+
+ try
+ while 1
+ try
+ throw "x6"
+ finally
+ break
+ endtry
+ break
+ endwhile
+ catch /.*/
+ Xpath 33554432 " X: 0
+ endtry
+ call CHECK(10)
+
+ try
+ while 1
+ try
+ throw "x7"
+ finally
+ break
+ endtry
+ break
+ endwhile
+ catch /.*/
+ Xpath 67108864 " X: 0
+ finally
+ call CHECK(11)
+ endtry
+ call CHECK(12)
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+ throw "x8"
+ finally
+ SetLineNumber line_before_error
+ asdf
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(13, 'E492', "Not an editor command",
+ \ line_before_error + 1)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(13)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(14)
+
+ Xpath 134217728 " X: 134217728
+
+ while 1
+ try
+ let intcaught = 0
+ try
+ try
+ throw "x9"
+ finally
+ SetLineNumber two_lines_before_interrupt
+ "INTERRUPT
+ endtry
+ catch /.*/
+ let intcaught = 1
+ call CHECK(15, "Vim:Interrupt", '',
+ \ two_lines_before_interrupt + 2)
+ endtry
+ finally
+ if !intcaught && $VIMNOINTTHROW
+ call CHECK(15)
+ endif
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+ call CHECK(16)
+
+ Xpath 268435456 " X: 268435456
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x10"
+ " missing endif
+ finally
+ call CHECK(17)
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(18)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(19)
+
+ Xpath 536870912 " X: 536870912
+
+ while 1
+ try
+ let errcaught = 0
+ try
+ try
+" if 1
+ SetLineNumber line_before_throw
+ throw "x11"
+ " missing endif
+ endtry
+ catch /.*/
+ let errcaught = 1
+ call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3)
+ endtry
+ finally
+ if !errcaught && $VIMNOERRTHROW
+ call CHECK(20)
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ call CHECK(21)
+
+ Xpath 1073741824 " X: 1073741824
+
+endif
+
+Xcheck 2038431743
+
+
+"-------------------------------------------------------------------------------
+"
+" Test 60: (Re)throwing v:exception; :echoerr. {{{1
+"
+" A user exception can be rethrown after catching by throwing
+" v:exception. An error or interrupt exception cannot be rethrown
+" because Vim exceptions cannot be faked. A Vim exception using the
+" value of v:exception can, however, be triggered by the :echoerr
+" command.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+try
+ try
+ Xpath 1 " X: 1
+ throw "oops"
+ catch /oops/
+ Xpath 2 " X: 2
+ throw v:exception " rethrow user exception
+ catch /.*/
+ Xpath 4 " X: 0
+ endtry
+catch /^oops$/ " catches rethrown user exception
+ Xpath 8 " X: 8
+catch /.*/
+ Xpath 16 " X: 0
+endtry
+
+function! F()
+ try
+ let caught = 0
+ try
+ Xpath 32 " X: 32
+ write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
+ Xpath 64 " X: 0
+ Xout "did_emsg was reset before executing " .
+ \ "BufWritePost autocommands."
+ catch /^Vim(write):/
+ let caught = 1
+ throw v:exception " throw error: cannot fake Vim exception
+ catch /.*/
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ endtry
+ catch /^Vim(throw):/ " catches throw error
+ let caught = caught + 1
+ catch /.*/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if caught != 2
+ if !caught && !$VIMNOERRTHROW
+ Xpath 4096 " X: 0
+ elseif caught
+ Xpath 8192 " X: 0
+ endif
+ return | " discard error for $VIMNOERRTHROW
+ endif
+ endtry
+endfunction
+
+call F()
+delfunction F
+
+function! G()
+ try
+ let caught = 0
+ try
+ Xpath 16384 " X: 16384
+ asdf
+ catch /^Vim/ " catch error exception
+ let caught = 1
+ " Trigger Vim error exception with value specified after :echoerr
+ let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+ echoerr value
+ catch /.*/
+ Xpath 32768 " X: 0
+ finally
+ Xpath 65536 " X: 65536
+ if !caught
+ if !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ else
+ let value = "Error"
+ echoerr value
+ endif
+ endif
+ endtry
+ catch /^Vim(echoerr):/
+ let caught = caught + 1
+ if v:exception !~ value
+ Xpath 262144 " X: 0
+ endif
+ catch /.*/
+ Xpath 524288 " X: 0
+ finally
+ Xpath 1048576 " X: 1048576
+ if caught != 2
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ elseif caught
+ Xpath 4194304 " X: 0
+ endif
+ return | " discard error for $VIMNOERRTHROW
+ endif
+ endtry
+endfunction
+
+call G()
+delfunction G
+
+unlet! value caught
+
+if ExtraVim()
+ try
+ let errcaught = 0
+ try
+ Xpath 8388608 " X: 8388608
+ let intcaught = 0
+ "INTERRUPT
+ catch /^Vim:/ " catch interrupt exception
+ let intcaught = 1
+ " Trigger Vim error exception with value specified after :echoerr
+ echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
+ catch /.*/
+ Xpath 16777216 " X: 0
+ finally
+ Xpath 33554432 " X: 33554432
+ if !intcaught
+ if !$VIMNOINTTHROW
+ Xpath 67108864 " X: 0
+ else
+ echoerr "Interrupt"
+ endif
+ endif
+ endtry
+ catch /^Vim(echoerr):/
+ let errcaught = 1
+ if v:exception !~ "Interrupt"
+ Xpath 134217728 " X: 0
+ endif
+ finally
+ Xpath 268435456 " X: 268435456
+ if !errcaught && !$VIMNOERRTHROW
+ Xpath 536870912 " X: 0
+ endif
+ endtry
+endif
+
+Xcheck 311511339
+
+
+"-------------------------------------------------------------------------------
+" Test 61: Catching interrupt exceptions {{{1
+"
+" When an interrupt occurs inside a :try/:endtry region, an
+" interrupt exception is thrown and can be caught. Its value is
+" "Vim:Interrupt". If the interrupt occurs after an error or a :throw
+" but before a matching :catch is reached, all following :catches of
+" that try block are ignored, but the interrupt exception can be
+" caught by the next surrounding try conditional. An interrupt is
+" ignored when there is a previous interrupt that has not been caught
+" or causes a :finally clause to be executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ while 1
+ try
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ "INTERRUPT
+ Xpath 2 " X: 0
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 4 " X: 4
+ if caught || $VIMNOINTTHROW
+ Xpath 8 " X: 8
+ endif
+ endtry
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 32 " X: 32
+ asdf
+ Xpath 64 " X: 0
+ catch /do_not_catch/
+ Xpath 128 " X: 0
+ catch /.*/ "INTERRUPT - throw interrupt if !$VIMNOERRTHROW
+ Xpath 256 " X: 0
+ catch /.*/
+ Xpath 512 " X: 0
+ finally "INTERRUPT - throw interrupt if $VIMNOERRTHROW
+ Xpath 1024 " X: 1024
+ endtry
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 2048 " X: 2048
+ if caught || $VIMNOINTTHROW
+ Xpath 4096 " X: 4096
+ endif
+ endtry
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 16384 " X: 16384
+ throw "x"
+ Xpath 32768 " X: 0
+ catch /do_not_catch/
+ Xpath 65536 " X: 0
+ catch /x/ "INTERRUPT
+ Xpath 131072 " X: 0
+ catch /.*/
+ Xpath 262144 " X: 0
+ endtry
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 524288 " X: 524288
+ if caught || $VIMNOINTTHROW
+ Xpath 1048576 " X: 1048576
+ endif
+ endtry
+ catch /.*/
+ Xpath 2097152 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ try
+ Xpath 4194304 " X: 4194304
+ "INTERRUPT
+ Xpath 8388608 " X: 0
+ catch /do_not_catch/ "INTERRUPT
+ Xpath 16777216 " X: 0
+ catch /^Vim:Interrupt$/
+ let caught = 1
+ finally
+ Xpath 33554432 " X: 33554432
+ if caught || $VIMNOINTTHROW
+ Xpath 67108864 " X: 67108864
+ endif
+ endtry
+ catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard interrupt for $VIMNOINTTHROW
+ endtry
+ endwhile
+
+ Xpath 268435456 " X: 268435456
+
+endif
+
+Xcheck 374889517
+
+
+"-------------------------------------------------------------------------------
+" Test 62: Catching error exceptions {{{1
+"
+" An error inside a :try/:endtry region is converted to an exception
+" and can be caught. The error exception has a "Vim(cmdname):" prefix
+" where cmdname is the name of the failing command, or a "Vim:" prefix
+" if no command name is known. The "Vim" prefixes cannot be faked.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+while 1
+ try
+ try
+ let caught = 0
+ unlet novar
+ catch /^Vim(unlet):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
+ finally
+ Xpath 1 " X: 1
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2 " X: 0
+ endif
+ if !MSG('E108', "No such variable")
+ Xpath 4 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ throw novar " error in :throw
+ catch /^Vim(throw):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+ finally
+ Xpath 16 " X: 16
+ if !caught && !$VIMNOERRTHROW
+ Xpath 32 " X: 0
+ endif
+ if caught ? !MSG('E121', "Undefined variable")
+ \ : !MSG('E15', "Invalid expression")
+ Xpath 64 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ throw "Vim:faked" " error: cannot fake Vim exception
+ catch /^Vim(throw):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix")
+ Xpath 1024 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! F()
+ while 1
+ " Missing :endwhile
+endfunction
+
+while 1
+ try
+ try
+ let caught = 0
+ call F()
+ catch /^Vim(endfunction):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if !MSG('E170', "Missing :endwhile")
+ Xpath 16384 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let caught = 0
+ ExecAsScript F
+ catch /^Vim:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+ finally
+ Xpath 65536 " X: 65536
+ if !caught && !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ endif
+ if !MSG('E170', "Missing :endwhile")
+ Xpath 262144 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! G()
+ call G()
+endfunction
+
+while 1
+ try
+ let mfd_save = &mfd
+ set mfd=3
+ try
+ let caught = 0
+ call G()
+ catch /^Vim(call):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
+ finally
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ let &mfd = mfd_save
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+function! H()
+ return H()
+endfunction
+
+while 1
+ try
+ let mfd_save = &mfd
+ set mfd=3
+ try
+ let caught = 0
+ call H()
+ catch /^Vim(return):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
+ finally
+ Xpath 16777216 " X: 16777216
+ if !caught && !$VIMNOERRTHROW
+ Xpath 33554432 " X: 0
+ endif
+ if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
+ Xpath 67108864 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 134217728 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ let &mfd = mfd_save
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+unlet! caught mfd_save
+delfunction F
+delfunction G
+delfunction H
+Xpath 268435456 " X: 268435456
+
+Xcheck 286331153
+
+" Leave MSG() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 63: Suppressing error exceptions by :silent!. {{{1
+"
+" A :silent! command inside a :try/:endtry region suppresses the
+" conversion of errors to an exception and the immediate abortion on
+" error. When the commands executed by the :silent! themselves open
+" a new :try/:endtry region, conversion of errors to exception and
+" immediate abortion is switched on again - until the next :silent!
+" etc. The :silent! has the effect of setting v:errmsg to the error
+" message text (without displaying it) and continuing with the next
+" script line.
+"
+" When a command triggering autocommands is executed by :silent!
+" inside a :try/:endtry, the autocommand execution is not suppressed
+" on error.
+"
+" This test reuses the function MSG() from the previous test.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT! 1 4
+
+let taken = ""
+
+function! S(n) abort
+ XloopNEXT
+ let g:taken = g:taken . "E" . a:n
+ let v:errmsg = ""
+ exec "asdf" . a:n
+
+ " Check that ":silent!" continues:
+ Xloop 1
+
+ " Check that ":silent!" sets "v:errmsg":
+ if MSG('E492', "Not an editor command")
+ Xloop 2
+ endif
+endfunction
+
+function! Foo()
+ while 1
+ try
+ try
+ let caught = 0
+ " This is not silent:
+ call S(3) " X: 0 * 16
+ catch /^Vim:/
+ let caught = 1
+ let errmsg3 = substitute(v:exception, '^Vim:', '', "")
+ silent! call S(4) " X: 3 * 64
+ finally
+ if !caught
+ let errmsg3 = v:errmsg
+ " Do call S(4) here if not executed in :catch.
+ silent! call S(4)
+ endif
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ let v:errmsg = errmsg3
+ if !MSG('E492', "Not an editor command")
+ Xpath 4194304 " X: 0
+ endif
+ silent! call S(5) " X: 3 * 256
+ " Break out of try conds that cover ":silent!". This also
+ " discards the aborting error when $VIMNOERRTHROW is non-zero.
+ break
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+ endwhile
+ " This is a double ":silent!" (see caller).
+ silent! call S(6) " X: 3 * 1024
+endfunction
+
+function! Bar()
+ try
+ silent! call S(2) " X: 3 * 4
+ " X: 3 * 4096
+ silent! execute "call Foo() | call S(7)"
+ silent! call S(8) " X: 3 * 16384
+ endtry " normal end of try cond that covers ":silent!"
+ " This has a ":silent!" from the caller:
+ call S(9) " X: 3 * 65536
+endfunction
+
+silent! call S(1) " X: 3 * 1
+silent! call Bar()
+silent! call S(10) " X: 3 * 262144
+
+let expected = "E1E2E3E4E5E6E7E8E9E10"
+if taken != expected
+ Xpath 16777216 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+endif
+
+augroup TMP
+ autocmd BufWritePost * Xpath 33554432 " X: 33554432
+augroup END
+
+Xpath 67108864 " X: 67108864
+write /i/m/p/o/s/s/i/b/l/e
+Xpath 134217728 " X: 134217728
+
+autocmd! TMP
+unlet! caught errmsg3 taken expected
+delfunction S
+delfunction Foo
+delfunction Bar
+delfunction MSG
+
+Xcheck 236978127
+
+
+"-------------------------------------------------------------------------------
+" Test 64: Error exceptions after error, interrupt or :throw {{{1
+"
+" When an error occurs after an interrupt or a :throw but before
+" a matching :catch is reached, all following :catches of that try
+" block are ignored, but the error exception can be caught by the next
+" surrounding try conditional. Any previous error exception is
+" discarded. An error is ignored when there is a previous error that
+" has not been caught.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ while 1
+ try
+ try
+ Xpath 1 " X: 1
+ let caught = 0
+ while 1
+" if 1
+ " Missing :endif
+ endwhile " throw error exception
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 2 " X: 2
+ if caught || $VIMNOERRTHROW
+ Xpath 4 " X: 4
+ endif
+ endtry
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ Xpath 16 " X: 16
+ let caught = 0
+ try
+" if 1
+ " Missing :endif
+ catch /.*/ " throw error exception
+ Xpath 32 " X: 0
+ catch /.*/
+ Xpath 64 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 128 " X: 128
+ if caught || $VIMNOERRTHROW
+ Xpath 256 " X: 256
+ endif
+ endtry
+ catch /.*/
+ Xpath 512 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 1024 " X: 1024
+ "INTERRUPT
+ catch /do_not_catch/
+ Xpath 2048 " X: 0
+" if 1
+ " Missing :endif
+ catch /.*/ " throw error exception
+ Xpath 4096 " X: 0
+ catch /.*/
+ Xpath 8192 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 16384 " X: 16384
+ if caught || $VIMNOERRTHROW
+ Xpath 32768 " X: 32768
+ endif
+ endtry
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ try
+ Xpath 131072 " X: 131072
+ throw "x"
+ catch /do_not_catch/
+ Xpath 262144 " X: 0
+" if 1
+ " Missing :endif
+ catch /x/ " throw error exception
+ Xpath 524288 " X: 0
+ catch /.*/
+ Xpath 1048576 " X: 0
+ endtry
+ catch /^Vim(/
+ let caught = 1
+ finally
+ Xpath 2097152 " X: 2097152
+ if caught || $VIMNOERRTHROW
+ Xpath 4194304 " X: 4194304
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ try
+ let caught = 0
+ Xpath 16777216 " X: 16777216
+" endif " :endif without :if; throw error exception
+" if 1
+ " Missing :endif
+ catch /do_not_catch/ " ignore new error
+ Xpath 33554432 " X: 0
+ catch /^Vim(endif):/
+ let caught = 1
+ catch /^Vim(/
+ Xpath 67108864 " X: 0
+ finally
+ Xpath 134217728 " X: 134217728
+ if caught || $VIMNOERRTHROW
+ Xpath 268435456 " X: 268435456
+ endif
+ endtry
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ Xpath 1073741824 " X: 1073741824
+
+endif
+
+Xcheck 1499645335
+
+
+"-------------------------------------------------------------------------------
+" Test 65: Errors in the /pattern/ argument of a :catch {{{1
+"
+" On an error in the /pattern/ argument of a :catch, the :catch does
+" not match. Any following :catches of the same :try/:endtry don't
+" match either. Finally clauses are executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ throw "oops"
+ catch /^oops$/
+ Xpath 2 " X: 2
+ catch /\)/ " not checked; exception has already been caught
+ Xpath 4 " X: 0
+ endtry
+ Xpath 8 " X: 8
+catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+function! F()
+ try
+ let caught = 0
+ try
+ try
+ Xpath 32 " X: 32
+ throw "ab"
+ catch /abc/ " does not catch
+ Xpath 64 " X: 0
+ catch /\)/ " error; discards exception
+ Xpath 128 " X: 0
+ catch /.*/ " not checked
+ Xpath 256 " X: 0
+ finally
+ Xpath 512 " X: 512
+ endtry
+ Xpath 1024 " X: 0
+ catch /^ab$/ " checked, but original exception is discarded
+ Xpath 2048 " X: 0
+ catch /^Vim(catch):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if caught ? !MSG('E55', 'Unmatched \\)')
+ \ : !MSG('E475', "Invalid argument")
+ Xpath 16384 " X: 0
+ endif
+ if !caught
+ return | " discard error
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ endtry
+endfunction
+
+call F()
+Xpath 65536 " X: 65536
+
+delfunction MSG
+delfunction F
+unlet! caught
+
+Xcheck 70187
+
+
+"-------------------------------------------------------------------------------
+" Test 66: Stop range :call on error, interrupt, or :throw {{{1
+"
+" When a function which is multiply called for a range since it
+" doesn't handle the range itself has an error in a command
+" dynamically enclosed by :try/:endtry or gets an interrupt or
+" executes a :throw, no more calls for the remaining lines in the
+" range are made. On an error in a command not dynamically enclosed
+" by :try/:endtry, the function is executed again for the remaining
+" lines in the range.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let file = tempname()
+ exec "edit" file
+
+ insert
+line 1
+line 2
+line 3
+.
+
+ XloopINIT! 1 2
+
+ let taken = ""
+ let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
+
+ function! F(reason, n) abort
+ let g:taken = g:taken . "F" . a:n .
+ \ substitute(a:reason, '\(\l\).*', '\u\1', "") .
+ \ "(" . line(".") . ")"
+
+ if a:reason == "error"
+ asdf
+ elseif a:reason == "interrupt"
+ "INTERRUPT
+ let dummy = 0
+ elseif a:reason == "throw"
+ throw "xyz"
+ elseif a:reason == "aborting error"
+ XloopNEXT
+ if g:taken != g:expected
+ Xloop 1 " X: 0
+ Xout "'taken' is" g:taken "instead of" g:expected
+ endif
+ try
+ bwipeout!
+ call delete(file)
+ asdf
+ endtry
+ endif
+ endfunction
+
+ function! G(reason, n)
+ let g:taken = g:taken . "G" . a:n .
+ \ substitute(a:reason, '\(\l\).*', '\u\1', "")
+ 1,3call F(a:reason, a:n)
+ endfunction
+
+ Xpath 8 " X: 8
+ call G("error", 1)
+ try
+ Xpath 16 " X: 16
+ try
+ call G("error", 2)
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ try
+ call G("interrupt", 3)
+ Xpath 128 " X: 0
+ finally
+ Xpath 256 " X: 256
+ try
+ call G("throw", 4)
+ Xpath 512 " X: 0
+ endtry
+ endtry
+ endtry
+ catch /xyz/
+ Xpath 1024 " X: 1024
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 4096 " X: 4096
+ call G("aborting error", 5)
+ Xpath 8192 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+
+endif
+
+Xcheck 5464
+
+
+"-------------------------------------------------------------------------------
+" Test 67: :throw accross :call command {{{1
+"
+" On a call command, an exception might be thrown when evaluating the
+" function name, during evaluation of the arguments, or when the
+" function is being executed. The exception can be caught by the
+" caller.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! THROW(x, n)
+ if a:n == 1
+ Xpath 1 " X: 1
+ elseif a:n == 2
+ Xpath 2 " X: 2
+ elseif a:n == 3
+ Xpath 4 " X: 4
+ endif
+ throw a:x
+endfunction
+
+function! NAME(x, n)
+ if a:n == 1
+ Xpath 8 " X: 0
+ elseif a:n == 2
+ Xpath 16 " X: 16
+ elseif a:n == 3
+ Xpath 32 " X: 32
+ elseif a:n == 4
+ Xpath 64 " X: 64
+ endif
+ return a:x
+endfunction
+
+function! ARG(x, n)
+ if a:n == 1
+ Xpath 128 " X: 0
+ elseif a:n == 2
+ Xpath 256 " X: 0
+ elseif a:n == 3
+ Xpath 512 " X: 512
+ elseif a:n == 4
+ Xpath 1024 " X: 1024
+ endif
+ return a:x
+endfunction
+
+function! F(x, n)
+ if a:n == 2
+ Xpath 2048 " X: 0
+ elseif a:n == 4
+ Xpath 4096 " X: 4096
+ endif
+endfunction
+
+try
+
+ try
+ Xpath 8192 " X: 8192
+ call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+ Xpath 16384 " X: 0
+ catch /^name$/
+ Xpath 32768 " X: 32768
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout "1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 131072 " X: 131072
+ call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+ Xpath 262144 " X: 0
+ catch /^arg$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ call {NAME("THROW", 3)}(ARG("call", 3), 3)
+ Xpath 4194304 " X: 0
+ catch /^call$/
+ Xpath 8388608 " X: 8388608
+ catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout "3:" v:throwpoint
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "3:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ call {NAME("F", 4)}(ARG(4711, 4), 4)
+ Xpath 134217728 " X: 134217728
+ catch /.*/
+ Xpath 268435456 " X: 0
+ Xout "4:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 536870912 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+delfunction F
+
+Xcheck 212514423
+
+" Leave THROW(), NAME(), and ARG() for the next test.
+
+
+"-------------------------------------------------------------------------------
+" Test 68: :throw accross function calls in expressions {{{1
+"
+" On a function call within an expression, an exception might be
+" thrown when evaluating the function name, during evaluation of the
+" arguments, or when the function is being executed. The exception
+" can be caught by the caller.
+"
+" This test reuses the functions THROW(), NAME(), and ARG() from the
+" previous test.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F(x, n)
+ if a:n == 2
+ Xpath 2048 " X: 0
+ elseif a:n == 4
+ Xpath 4096 " X: 4096
+ endif
+ return a:x
+endfunction
+
+unlet! var1 var2 var3 var4
+
+try
+
+ try
+ Xpath 8192 " X: 8192
+ let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
+ Xpath 16384 " X: 0
+ catch /^name$/
+ Xpath 32768 " X: 32768
+ catch /.*/
+ Xpath 65536 " X: 0
+ Xout "1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 131072 " X: 131072
+ let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
+ Xpath 262144 " X: 0
+ catch /^arg$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 2097152 " X: 2097152
+ let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
+ Xpath 4194304 " X: 0
+ catch /^call$/
+ Xpath 8388608 " X: 8388608
+ catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout "3:" v:throwpoint
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "3:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
+ Xpath 134217728 " X: 134217728
+ catch /.*/
+ Xpath 268435456 " X: 0
+ Xout "4:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 536870912 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 1073741824 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+if exists("var1") || exists("var2") || exists("var3") ||
+ \ !exists("var4") || var4 != 4711
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ if exists("var1")
+ Xout "var1 =" var1
+ endif
+ if exists("var2")
+ Xout "var2 =" var2
+ endif
+ if exists("var3")
+ Xout "var3 =" var3
+ endif
+ if !exists("var4")
+ Xout "var4 unset"
+ elseif var4 != 4711
+ Xout "var4 =" var4
+ endif
+endif
+
+unlet! var1 var2 var3 var4
+delfunction THROW
+delfunction NAME
+delfunction ARG
+delfunction F
+
+Xcheck 212514423
+
+
+"-------------------------------------------------------------------------------
+" Test 69: :throw accross :if, :elseif, :while {{{1
+"
+" On an :if, :elseif, or :while command, an exception might be thrown
+" during evaluation of the expression to test. The exception can be
+" caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT! 1 2
+
+function! THROW(x)
+ XloopNEXT
+ Xloop 1 " X: 1 + 2 + 4
+ throw a:x
+endfunction
+
+try
+
+ try
+ Xpath 8 " X: 8
+ if 4711 == THROW("if") + 111
+ Xpath 16 " X: 0
+ else
+ Xpath 32 " X: 0
+ endif
+ Xpath 64 " X: 0
+ catch /^if$/
+ Xpath 128 " X: 128
+ catch /.*/
+ Xpath 256 " X: 0
+ Xout "if:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 512 " X: 512
+ if 4711 == 4 + 7 + 1 + 1
+ Xpath 1024 " X: 0
+ elseif 4711 == THROW("elseif") + 222
+ Xpath 2048 " X: 0
+ else
+ Xpath 4096 " X: 0
+ endif
+ Xpath 8192 " X: 0
+ catch /^elseif$/
+ Xpath 16384 " X: 16384
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout "elseif:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 65536 " X: 65536
+ while 4711 == THROW("while") + 4711
+ Xpath 131072 " X: 0
+ break
+ endwhile
+ Xpath 262144 " X: 0
+ catch /^while$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "while:" v:exception "in" v:throwpoint
+ endtry
+
+catch /^0$/ " default return value
+ Xpath 2097152 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xout v:exception "in" v:throwpoint
+ Xpath 4194304 " X: 0
+endtry
+
+Xpath 8388608 " X: 8388608
+
+delfunction THROW
+
+Xcheck 8995471
+
+
+"-------------------------------------------------------------------------------
+" Test 70: :throw accross :return or :throw {{{1
+"
+" On a :return or :throw command, an exception might be thrown during
+" evaluation of the expression to return or throw, respectively. The
+" exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! F(x, y, n)
+ let g:taken = g:taken . "F" . a:n
+ return a:x + THROW(a:y, a:n)
+endfunction
+
+function! G(x, y, n)
+ let g:taken = g:taken . "G" . a:n
+ throw a:x . THROW(a:y, a:n)
+ return a:x
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ call F(4711, "return", 1)
+ Xpath 2 " X: 0
+ catch /^return$/
+ Xpath 4 " X: 4
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout "return:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ let var = F(4712, "return-var", 2)
+ Xpath 32 " X: 0
+ catch /^return-var$/
+ Xpath 64 " X: 64
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout "return-var:" v:exception "in" v:throwpoint
+ finally
+ unlet! var
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ throw "except1" . THROW("throw1", 3)
+ Xpath 512 " X: 0
+ catch /^except1/
+ Xpath 1024 " X: 0
+ catch /^throw1$/
+ Xpath 2048 " X: 2048
+ catch /.*/
+ Xpath 4096 " X: 0
+ Xout "throw1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 8192 " X: 8192
+ call G("except2", "throw2", 4)
+ Xpath 16384 " X: 0
+ catch /^except2/
+ Xpath 32768 " X: 0
+ catch /^throw2$/
+ Xpath 65536 " X: 65536
+ catch /.*/
+ Xpath 131072 " X: 0
+ Xout "throw2:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ let var = G("except3", "throw3", 5)
+ Xpath 524288 " X: 0
+ catch /^except3/
+ Xpath 1048576 " X: 0
+ catch /^throw3$/
+ Xpath 2097152 " X: 2097152
+ catch /.*/
+ Xpath 4194304 " X: 0
+ Xout "throw3:" v:exception "in" v:throwpoint
+ finally
+ unlet! var
+ endtry
+
+ let expected = "F1T1F2T2T3G4T4G5T5"
+ if taken != expected
+ Xpath 8388608 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /^0$/ " default return value
+ Xpath 16777216 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 33554432 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 67108864 " X: 67108864
+
+unlet taken expected
+delfunction THROW
+delfunction F
+delfunction G
+
+Xcheck 69544277
+
+
+"-------------------------------------------------------------------------------
+" Test 71: :throw accross :echo variants and :execute {{{1
+"
+" On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
+" exception might be thrown during evaluation of the arguments to
+" be displayed or executed as a command, respectively. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! F(n)
+ let g:taken = g:taken . "F" . a:n
+ return "F" . a:n
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ echo "echo" . THROW("echo-except", 1) F(1)
+ Xpath 2 " X: 0
+ catch /^echo-except$/
+ Xpath 4 " X: 4
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout "echo:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 16 " X: 16
+ echon "echon" . THROW("echon-except", 2) F(2)
+ Xpath 32 " X: 0
+ catch /^echon-except$/
+ Xpath 64 " X: 64
+ catch /.*/
+ Xpath 128 " X: 0
+ Xout "echon:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 256 " X: 256
+ echomsg "echomsg" . THROW("echomsg-except", 3) F(3)
+ Xpath 512 " X: 0
+ catch /^echomsg-except$/
+ Xpath 1024 " X: 1024
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout "echomsg:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 4096 " X: 4096
+ echoerr "echoerr" . THROW("echoerr-except", 4) F(4)
+ Xpath 8192 " X: 0
+ catch /^echoerr-except$/
+ Xpath 16384 " X: 16384
+ catch /Vim/
+ Xpath 32768 " X: 0
+ catch /echoerr/
+ Xpath 65536 " X: 0
+ catch /.*/
+ Xpath 131072 " X: 0
+ Xout "echoerr:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 262144 " X: 262144
+ execute "echo 'execute" . THROW("execute-except", 5) F(5) "'"
+ Xpath 524288 " X: 0
+ catch /^execute-except$/
+ Xpath 1048576 " X: 1048576
+ catch /.*/
+ Xpath 2097152 " X: 0
+ Xout "execute:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "T1T2T3T4T5"
+ if taken != expected
+ Xpath 4194304 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /^0$/ " default return value
+ Xpath 8388608 " X: 0
+ Xout v:throwpoint
+catch /.*/
+ Xpath 16777216 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 33554432 " X: 33554432
+
+unlet taken expected
+delfunction THROW
+delfunction F
+
+Xcheck 34886997
+
+
+"-------------------------------------------------------------------------------
+" Test 72: :throw accross :let or :unlet {{{1
+"
+" On a :let command, an exception might be thrown during evaluation
+" of the expression to assign. On an :let or :unlet command, the
+" evaluation of the name of the variable to be assigned or list or
+" deleted, respectively, may throw an exception. Any following
+" arguments are not evaluated, then. The exception can be caught by
+" the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let throwcount = 0
+
+function! THROW(x)
+ let g:throwcount = g:throwcount + 1
+ throw a:x
+endfunction
+
+try
+ try
+ let $VAR = "old_value"
+ Xpath 1 " X: 1
+ let $VAR = "let(" . THROW("var") . ")"
+ Xpath 2 " X: 0
+ catch /^var$/
+ Xpath 4 " X: 4
+ finally
+ if $VAR != "old_value"
+ Xpath 8 " X: 0
+ endif
+ endtry
+
+ try
+ let @a = "old_value"
+ Xpath 16 " X: 16
+ let @a = "let(" . THROW("reg") . ")"
+ Xpath 32 " X: 0
+ catch /^reg$/
+ try
+ Xpath 64 " X: 64
+ let @A = "let(" . THROW("REG") . ")"
+ Xpath 128 " X: 0
+ catch /^REG$/
+ Xpath 256 " X: 256
+ endtry
+ finally
+ if @a != "old_value"
+ Xpath 512 " X: 0
+ endif
+ if @A != "old_value"
+ Xpath 1024 " X: 0
+ endif
+ endtry
+
+ try
+ let saved_gpath = &g:path
+ let saved_lpath = &l:path
+ Xpath 2048 " X: 2048
+ let &path = "let(" . THROW("opt") . ")"
+ Xpath 4096 " X: 0
+ catch /^opt$/
+ try
+ Xpath 8192 " X: 8192
+ let &g:path = "let(" . THROW("gopt") . ")"
+ Xpath 16384 " X: 0
+ catch /^gopt$/
+ try
+ Xpath 32768 " X: 32768
+ let &l:path = "let(" . THROW("lopt") . ")"
+ Xpath 65536 " X: 0
+ catch /^lopt$/
+ Xpath 131072 " X: 131072
+ endtry
+ endtry
+ finally
+ if &g:path != saved_gpath || &l:path != saved_lpath
+ Xpath 262144 " X: 0
+ endif
+ let &g:path = saved_gpath
+ let &l:path = saved_lpath
+ endtry
+
+ unlet! var1 var2 var3
+
+ try
+ Xpath 524288 " X: 524288
+ let var1 = "let(" . THROW("var1") . ")"
+ Xpath 1048576 " X: 0
+ catch /^var1$/
+ Xpath 2097152 " X: 2097152
+ finally
+ if exists("var1")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+
+ try
+ let var2 = "old_value"
+ Xpath 8388608 " X: 8388608
+ let var2 = "let(" . THROW("var2"). ")"
+ Xpath 16777216 " X: 0
+ catch /^var2$/
+ Xpath 33554432 " X: 33554432
+ finally
+ if var2 != "old_value"
+ Xpath 67108864 " X: 0
+ endif
+ endtry
+
+ try
+ Xpath 134217728 " X: 134217728
+ let var{THROW("var3")} = 4711
+ Xpath 268435456 " X: 0
+ catch /^var3$/
+ Xpath 536870912 " X: 536870912
+ endtry
+
+ let addpath = ""
+
+ function ADDPATH(p)
+ let g:addpath = g:addpath . a:p
+ endfunction
+
+ try
+ call ADDPATH("T1")
+ let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3")
+ call ADDPATH("T4")
+ catch /^var4$/
+ call ADDPATH("T5")
+ endtry
+
+ try
+ call ADDPATH("T6")
+ unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8")
+ call ADDPATH("T9")
+ catch /^var5$/
+ call ADDPATH("T10")
+ endtry
+
+ if addpath != "T1T5T6T10" || throwcount != 11
+ throw "addpath: " . addpath . ", throwcount: " . throwcount
+ endif
+
+ Xpath 1073741824 " X: 1073741824
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! var1 var2 var3 addpath throwcount
+delfunction THROW
+
+Xcheck 1789569365
+
+
+"-------------------------------------------------------------------------------
+" Test 73: :throw accross :function, :delfunction {{{1
+"
+" The :function and :delfunction commands may cause an expression
+" specified in braces to be evaluated. During evaluation, an
+" exception might be thrown. The exception can be caught by the
+" script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! EXPR(x, n)
+ let g:taken = g:taken . "E" . a:n
+ if a:n % 2 == 0
+ call THROW(a:x, a:n)
+ endif
+ return 2 - a:n % 2
+endfunction
+
+try
+ try
+ " Define function.
+ Xpath 1 " X: 1
+ function! F0()
+ endfunction
+ Xpath 2 " X: 2
+ function! F{EXPR("function-def-ok", 1)}()
+ endfunction
+ Xpath 4 " X: 4
+ function! F{EXPR("function-def", 2)}()
+ endfunction
+ Xpath 8 " X: 0
+ catch /^function-def-ok$/
+ Xpath 16 " X: 0
+ catch /^function-def$/
+ Xpath 32 " X: 32
+ catch /.*/
+ Xpath 64 " X: 0
+ Xout "def:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ " List function.
+ Xpath 128 " X: 128
+ function F0
+ Xpath 256 " X: 256
+ function F{EXPR("function-lst-ok", 3)}
+ Xpath 512 " X: 512
+ function F{EXPR("function-lst", 4)}
+ Xpath 1024 " X: 0
+ catch /^function-lst-ok$/
+ Xpath 2048 " X: 0
+ catch /^function-lst$/
+ Xpath 4096 " X: 4096
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout "lst:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ " Delete function
+ Xpath 16384 " X: 16384
+ delfunction F0
+ Xpath 32768 " X: 32768
+ delfunction F{EXPR("function-del-ok", 5)}
+ Xpath 65536 " X: 65536
+ delfunction F{EXPR("function-del", 6)}
+ Xpath 131072 " X: 0
+ catch /^function-del-ok$/
+ Xpath 262144 " X: 0
+ catch /^function-del$/
+ Xpath 524288 " X: 524288
+ catch /.*/
+ Xpath 1048576 " X: 0
+ Xout "del:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "E1E2T2E3E4T4E5E6T6"
+ if taken != expected
+ Xpath 2097152 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xpath 8388608 " X: 8388608
+
+unlet taken expected
+delfunction THROW
+delfunction EXPR
+
+Xcheck 9032615
+
+
+"-------------------------------------------------------------------------------
+" Test 74: :throw accross builtin functions and commands {{{1
+"
+" Some functions like exists(), searchpair() take expression
+" arguments, other functions or commands like substitute() or
+" :substitute cause an expression (specified in the regular
+" expression) to be evaluated. During evaluation an exception
+" might be thrown. The exception can be caught by the script.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+let taken = ""
+
+function! THROW(x, n)
+ let g:taken = g:taken . "T" . a:n
+ throw a:x
+endfunction
+
+function! EXPR(x, n)
+ let g:taken = g:taken . "E" . a:n
+ call THROW(a:x . a:n, a:n)
+ return "EXPR"
+endfunction
+
+function! SKIP(x, n)
+ let g:taken = g:taken . "S" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "skip"
+ let g:taken = g:taken . "s)"
+ return 1
+ elseif theline =~ "throw"
+ let g:taken = g:taken . "t)"
+ call THROW(a:x . a:n, a:n)
+ else
+ let g:taken = g:taken . ")"
+ return 0
+ endif
+endfunction
+
+function! SUBST(x, n)
+ let g:taken = g:taken . "U" . a:n . "(" . line(".")
+ let theline = getline(".")
+ if theline =~ "not" " SUBST() should not be called for this line
+ let g:taken = g:taken . "n)"
+ call THROW(a:x . a:n, a:n)
+ elseif theline =~ "throw"
+ let g:taken = g:taken . "t)"
+ call THROW(a:x . a:n, a:n)
+ else
+ let g:taken = g:taken . ")"
+ return "replaced"
+ endif
+endfunction
+
+try
+ try
+ Xpath 1 " X: 1
+ let result = exists('*{EXPR("exists", 1)}')
+ Xpath 2 " X: 0
+ catch /^exists1$/
+ Xpath 4 " X: 4
+ try
+ let result = exists('{EXPR("exists", 2)}')
+ Xpath 8 " X: 0
+ catch /^exists2$/
+ Xpath 16 " X: 16
+ catch /.*/
+ Xpath 32 " X: 0
+ Xout "exists2:" v:exception "in" v:throwpoint
+ endtry
+ catch /.*/
+ Xpath 64 " X: 0
+ Xout "exists1:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ insert
+begin
+ xx
+middle 3
+ xx
+middle 5 skip
+ xx
+middle 7 throw
+ xx
+end
+.
+ normal! gg
+ Xpath 128 " X: 128
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)')
+ Xpath 256 " X: 256
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)')
+ Xpath 512 " X: 0
+ let result =
+ \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)')
+ Xpath 1024 " X: 0
+ catch /^searchpair[35]$/
+ Xpath 2048 " X: 0
+ catch /^searchpair4$/
+ Xpath 4096 " X: 4096
+ catch /.*/
+ Xpath 8192 " X: 0
+ Xout "searchpair:" v:exception "in" v:throwpoint
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ let file = tempname()
+ exec "edit" file
+ insert
+subst 1
+subst 2
+not
+subst 4
+subst throw
+subst 6
+.
+ normal! gg
+ Xpath 16384 " X: 16384
+ 1,2substitute/subst/\=SUBST("substitute", 6)/
+ try
+ Xpath 32768 " X: 32768
+ try
+ let v:errmsg = ""
+ 3substitute/subst/\=SUBST("substitute", 7)/
+ finally
+ if v:errmsg != ""
+ " If exceptions are not thrown on errors, fake the error
+ " exception in order to get the same execution path.
+ throw "faked Vim(substitute)"
+ endif
+ endtry
+ catch /Vim(substitute)/ " Pattern not found ('e' flag missing)
+ Xpath 65536 " X: 65536
+ 3substitute/subst/\=SUBST("substitute", 8)/e
+ Xpath 131072 " X: 131072
+ endtry
+ Xpath 262144 " X: 262144
+ 4,6substitute/subst/\=SUBST("substitute", 9)/
+ Xpath 524288 " X: 0
+ catch /^substitute[678]/
+ Xpath 1048576 " X: 0
+ catch /^substitute9/
+ Xpath 2097152 " X: 2097152
+ finally
+ bwipeout!
+ call delete(file)
+ endtry
+
+ try
+ Xpath 4194304 " X: 4194304
+ let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '')
+ Xpath 8388608 " X: 0
+ catch /substitute()y/
+ Xpath 16777216 " X: 16777216
+ catch /.*/
+ Xpath 33554432 " X: 0
+ Xout "substitute()y:" v:exception "in" v:throwpoint
+ endtry
+
+ try
+ Xpath 67108864 " X: 67108864
+ let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '')
+ Xpath 134217728 " X: 134217728
+ catch /substitute()n/
+ Xpath 268435456 " X: 0
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout "substitute()n:" v:exception "in" v:throwpoint
+ endtry
+
+ let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10"
+ if taken != expected
+ Xpath 1073741824 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ endif
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet result var taken expected
+delfunction THROW
+delfunction EXPR
+delfunction SKIP
+delfunction SUBST
+
+Xcheck 224907669
+
+
+"-------------------------------------------------------------------------------
+" Test 75: Errors in builtin functions. {{{1
+"
+" On an error in a builtin function called inside a :try/:endtry
+" region, the evaluation of the expression calling that function and
+" the command containing that expression are abandoned. The error can
+" be caught as an exception.
+"
+" A simple :call of the builtin function is a trivial case. If the
+" builtin function is called in the argument list of another function,
+" no further arguments are evaluated, and the other function is not
+" executed. If the builtin function is called from the argument of
+" a :return command, the :return command is not executed. If the
+" builtin function is called from the argument of a :throw command,
+" the :throw command is not executed. The evaluation of the
+" expression calling the builtin function is abandoned.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! F1(arg1)
+ Xpath 1 " X: 0
+endfunction
+
+function! F2(arg1, arg2)
+ Xpath 2 " X: 0
+endfunction
+
+function! G()
+ Xpath 4 " X: 0
+endfunction
+
+function! H()
+ Xpath 8 " X: 0
+endfunction
+
+function! R()
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 16 " X: 16
+ return append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 32 " X: 0
+ finally
+ Xpath 64 " X: 64
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 128 " X: 128
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+ Xpath 256 " X: 256
+endfunction
+
+try
+ set noma " let append() fail with "E21"
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 512 " X: 512
+ call append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 1024 " X: 0
+ finally
+ Xpath 2048 " X: 2048
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 4096 " X: 4096
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 8192 " X: 8192
+ call F1('x' . append(1, "s"))
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 16384 " X: 0
+ finally
+ Xpath 32768 " X: 32768
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 65536 " X: 65536
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 131072 " X: 131072
+ call F2('x' . append(1, "s"), G())
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 262144 " X: 0
+ finally
+ Xpath 524288 " X: 524288
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 1048576 " X: 1048576
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ call R()
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 2097152 " X: 2097152
+ throw "T" . append(1, "s")
+ catch /E21/
+ let caught = 1
+ catch /^T.*/
+ Xpath 4194304 " X: 0
+ catch /.*/
+ Xpath 8388608 " X: 0
+ finally
+ Xpath 16777216 " X: 16777216
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 33554432 " X: 33554432
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+
+ while 1
+ try
+ let caught = 0
+ let v:errmsg = ""
+ Xpath 67108864 " X: 67108864
+ let x = "a"
+ let x = x . "b" . append(1, "s") . H()
+ catch /E21/
+ let caught = 1
+ catch /.*/
+ Xpath 134217728 " X: 0
+ finally
+ Xpath 268435456 " X: 268435456
+ if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
+ Xpath 536870912 " X: 536870912
+ endif
+ if x == "a"
+ Xpath 1073741824 " X: 1073741824
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry
+ endwhile
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+finally
+ set ma&
+endtry
+
+unlet! caught x
+delfunction F1
+delfunction F2
+delfunction G
+delfunction H
+delfunction R
+
+Xcheck 2000403408
+
+
+"-------------------------------------------------------------------------------
+" Test 76: Errors, interupts, :throw during expression evaluation {{{1
+"
+" When a function call made during expression evaluation is aborted
+" due to an error inside a :try/:endtry region or due to an interrupt
+" or a :throw, the expression evaluation is aborted as well. No
+" message is displayed for the cancelled expression evaluation. On an
+" error not inside :try/:endtry, the expression evaluation continues.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let taken = ""
+
+ function! ERR(n)
+ let g:taken = g:taken . "E" . a:n
+ asdf
+ endfunction
+
+ function! ERRabort(n) abort
+ let g:taken = g:taken . "A" . a:n
+ asdf
+ endfunction " returns -1
+
+ function! INT(n)
+ let g:taken = g:taken . "I" . a:n
+ "INTERRUPT9
+ let dummy = 0
+ endfunction
+
+ function! THR(n)
+ let g:taken = g:taken . "T" . a:n
+ throw "should not be caught"
+ endfunction
+
+ function! CONT(n)
+ let g:taken = g:taken . "C" . a:n
+ endfunction
+
+ function! MSG(n)
+ let g:taken = g:taken . "M" . a:n
+ if (a:n >= 10 && a:n <= 27) ? v:errmsg != "" : v:errmsg !~ "asdf"
+ let g:taken = g:taken . "x"
+ endif
+ let v:errmsg = ""
+ endfunction
+
+ let v:errmsg = ""
+
+ try
+ let t = 1
+ XloopINIT 1 2
+ while t <= 9
+ Xloop 1 " X: 511
+ try
+ if t == 1
+ let v{ERR(t) + CONT(t)} = 0
+ elseif t == 2
+ let v{ERR(t) + CONT(t)}
+ elseif t == 3
+ let var = exists('v{ERR(t) + CONT(t)}')
+ elseif t == 4
+ unlet v{ERR(t) + CONT(t)}
+ elseif t == 5
+ function F{ERR(t) + CONT(t)}()
+ endfunction
+ elseif t == 6
+ function F{ERR(t) + CONT(t)}
+ elseif t == 7
+ let var = exists('*F{ERR(t) + CONT(t)}')
+ elseif t == 8
+ delfunction F{ERR(t) + CONT(t)}
+ elseif t == 9
+ let var = ERR(t) + CONT(t)
+ endif
+ catch /asdf/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception, '^Vim:', '', "")
+ catch /^Vim\((\a\+)\)\=:/
+ " An error exception has been thrown after the original error.
+ let v:errmsg = ""
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard an aborting error
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 512 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ try
+ let t = 10
+ XloopINIT 1024 2
+ while t <= 18
+ Xloop 1 " X: 1024 * 511
+ try
+ if t == 10
+ let v{INT(t) + CONT(t)} = 0
+ elseif t == 11
+ let v{INT(t) + CONT(t)}
+ elseif t == 12
+ let var = exists('v{INT(t) + CONT(t)}')
+ elseif t == 13
+ unlet v{INT(t) + CONT(t)}
+ elseif t == 14
+ function F{INT(t) + CONT(t)}()
+ endfunction
+ elseif t == 15
+ function F{INT(t) + CONT(t)}
+ elseif t == 16
+ let var = exists('*F{INT(t) + CONT(t)}')
+ elseif t == 17
+ delfunction F{INT(t) + CONT(t)}
+ elseif t == 18
+ let var = INT(t) + CONT(t)
+ endif
+ catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
+ " An error exception has been triggered after the interrupt.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard interrupt
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ try
+ let t = 19
+ XloopINIT 1048576 2
+ while t <= 27
+ Xloop 1 " X: 1048576 * 511
+ try
+ if t == 19
+ let v{THR(t) + CONT(t)} = 0
+ elseif t == 20
+ let v{THR(t) + CONT(t)}
+ elseif t == 21
+ let var = exists('v{THR(t) + CONT(t)}')
+ elseif t == 22
+ unlet v{THR(t) + CONT(t)}
+ elseif t == 23
+ function F{THR(t) + CONT(t)}()
+ endfunction
+ elseif t == 24
+ function F{THR(t) + CONT(t)}
+ elseif t == 25
+ let var = exists('*F{THR(t) + CONT(t)}')
+ elseif t == 26
+ delfunction F{THR(t) + CONT(t)}
+ elseif t == 27
+ let var = THR(t) + CONT(t)
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ " An error exception has been triggered after the :throw.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ call MSG(t)
+ let t = t + 1
+ XloopNEXT
+ continue " discard exception
+ endtry
+ endwhile
+ catch /.*/
+ Xpath 536870912 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ let v{ERR(28) + CONT(28)} = 0
+ call MSG(28)
+ let v{ERR(29) + CONT(29)}
+ call MSG(29)
+ let var = exists('v{ERR(30) + CONT(30)}')
+ call MSG(30)
+ unlet v{ERR(31) + CONT(31)}
+ call MSG(31)
+ function F{ERR(32) + CONT(32)}()
+ endfunction
+ call MSG(32)
+ function F{ERR(33) + CONT(33)}
+ call MSG(33)
+ let var = exists('*F{ERR(34) + CONT(34)}')
+ call MSG(34)
+ delfunction F{ERR(35) + CONT(35)}
+ call MSG(35)
+ let var = ERR(36) + CONT(36)
+ call MSG(36)
+
+ let v{ERRabort(37) + CONT(37)} = 0
+ call MSG(37)
+ let v{ERRabort(38) + CONT(38)}
+ call MSG(38)
+ let var = exists('v{ERRabort(39) + CONT(39)}')
+ call MSG(39)
+ unlet v{ERRabort(40) + CONT(40)}
+ call MSG(40)
+ function F{ERRabort(41) + CONT(41)}()
+ endfunction
+ call MSG(41)
+ function F{ERRabort(42) + CONT(42)}
+ call MSG(42)
+ let var = exists('*F{ERRabort(43) + CONT(43)}')
+ call MSG(43)
+ delfunction F{ERRabort(44) + CONT(44)}
+ call MSG(44)
+ let var = ERRabort(45) + CONT(45)
+ call MSG(45)
+
+ Xpath 1073741824 " X: 1073741824
+
+ let expected = ""
+ \ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
+ \ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
+ \ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
+ \ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
+ \ . "E34C34M34E35C35M35E36C36M36"
+ \ . "A37C37M37A38C38M38A39C39M39A40C40M40A41C41M41A42C42M42"
+ \ . "A43C43M43A44C44M44A45C45M45"
+
+ if taken != expected
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ if substitute(taken,
+ \ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)',
+ \ '\1E3M3\2E30C30M30\3A39C39M39\4',
+ \ "") == expected
+ Xout "Is ++emsg_skip for var with expr_start non-NULL"
+ \ "in f_exists ok?"
+ endif
+ endif
+
+ unlet! var taken expected
+ call delete(WA_t5)
+ call delete(WA_t14)
+ call delete(WA_t23)
+ unlet! WA_t5 WA_t14 WA_t23
+ delfunction WA_t5
+ delfunction WA_t14
+ delfunction WA_t23
+
+endif
+
+Xcheck 1610087935
+
+
+"-------------------------------------------------------------------------------
+" Test 77: Errors, interupts, :throw in name{brace-expression} {{{1
+"
+" When a function call made during evaluation of an expression in
+" braces as part of a function name after ":function" is aborted due
+" to an error inside a :try/:endtry region or due to an interrupt or
+" a :throw, the expression evaluation is aborted as well, and the
+" function definition is ignored, skipping all commands to the
+" ":endfunction". On an error not inside :try/:endtry, the expression
+" evaluation continues and the function gets defined, and can be
+" called and deleted.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 4
+
+function! ERR() abort
+ Xloop 1 " X: 1 + 4 + 16 + 64
+ asdf
+endfunction " returns -1
+
+function! OK()
+ Xloop 2 " X: 2 * (1 + 4 + 16)
+ let v:errmsg = ""
+ return 0
+endfunction
+
+let v:errmsg = ""
+
+Xpath 4096 " X: 4096
+function! F{1 + ERR() + OK()}(arg)
+ " F0 should be defined.
+ if exists("a:arg") && a:arg == "calling"
+ Xpath 8192 " X: 8192
+ else
+ Xpath 16384 " X: 0
+ endif
+endfunction
+if v:errmsg != ""
+ Xpath 32768 " X: 0
+endif
+XloopNEXT
+
+Xpath 65536 " X: 65536
+call F{1 + ERR() + OK()}("calling")
+if v:errmsg != ""
+ Xpath 131072 " X: 0
+endif
+XloopNEXT
+
+Xpath 262144 " X: 262144
+delfunction F{1 + ERR() + OK()}
+if v:errmsg != ""
+ Xpath 524288 " X: 0
+endif
+XloopNEXT
+
+try
+ while 1
+ let caught = 0
+ try
+ Xpath 1048576 " X: 1048576
+ function! G{1 + ERR() + OK()}(arg)
+ " G0 should not be defined, and the function body should be
+ " skipped.
+ if exists("a:arg") && a:arg == "calling"
+ Xpath 2097152 " X: 0
+ else
+ Xpath 4194304 " X: 0
+ endif
+ " Use an unmatched ":finally" to check whether the body is
+ " skipped when an error occurs in ERR(). This works whether or
+ " not the exception is converted to an exception.
+ finally
+ Xpath 8388608 " X: 0
+ Xout "Body of G{1 + ERR() + OK()}() not skipped"
+ " Discard the aborting error or exception, and break the
+ " while loop.
+ break
+ " End the try conditional and start a new one to avoid
+ " ":catch after :finally" errors.
+ endtry
+ try
+ Xpath 16777216 " X: 0
+ endfunction
+
+ " When the function was not defined, this won't be reached - whether
+ " the body was skipped or not. When the function was defined, it
+ " can be called and deleted here.
+ Xpath 33554432 " X: 0
+ Xout "G0() has been defined"
+ XloopNEXT
+ try
+ call G{1 + ERR() + OK()}("calling")
+ catch /.*/
+ Xpath 67108864 " X: 0
+ endtry
+ Xpath 134217728 " X: 0
+ XloopNEXT
+ try
+ delfunction G{1 + ERR() + OK()}
+ catch /.*/
+ Xpath 268435456 " X: 0
+ endtry
+ catch /asdf/
+ " Jumped to when the function is not defined and the body is
+ " skipped.
+ let caught = 1
+ catch /.*/
+ Xpath 536870912 " X: 0
+ finally
+ if !caught && !$VIMNOERRTHROW
+ Xpath 1073741824 " X: 0
+ endif
+ break " discard error for $VIMNOERRTHROW
+ endtry " jumped to when the body is not skipped
+ endwhile
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught"
+ Xout v:exception "in" v:throwpoint
+endtry
+
+Xcheck 1388671
+
+
+"-------------------------------------------------------------------------------
+" Test 78: Messages on parsing errors in expression evaluation {{{1
+"
+" When an expression evaluation detects a parsing error, an error
+" message is given and converted to an exception, and the expression
+" evaluation is aborted.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ let taken = ""
+
+ function! F(n)
+ let g:taken = g:taken . "F" . a:n
+ endfunction
+
+ function! MSG(n, enr, emsg)
+ let g:taken = g:taken . "M" . a:n
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ if v:errmsg == ""
+ Xout "Expr" a:n.": Message missing."
+ let g:taken = g:taken . "x"
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Expr" a:n.": Unexpected message:" v:errmsg
+ let g:taken = g:taken . "X"
+ endif
+ endif
+ endfunction
+
+ function! CONT(n)
+ let g:taken = g:taken . "C" . a:n
+ endfunction
+
+ let v:errmsg = ""
+ XloopINIT 1 2
+
+ try
+ let t = 1
+ while t <= 14
+ let g:taken = g:taken . "T" . t
+ let v:errmsg = ""
+ try
+ let caught = 0
+ if t == 1
+ let v{novar + CONT(t)} = 0
+ elseif t == 2
+ let v{novar + CONT(t)}
+ elseif t == 3
+ let var = exists('v{novar + CONT(t)}')
+ elseif t == 4
+ unlet v{novar + CONT(t)}
+ elseif t == 5
+ function F{novar + CONT(t)}()
+ endfunction
+ elseif t == 6
+ function F{novar + CONT(t)}
+ elseif t == 7
+ let var = exists('*F{novar + CONT(t)}')
+ elseif t == 8
+ delfunction F{novar + CONT(t)}
+ elseif t == 9
+ echo novar + CONT(t)
+ elseif t == 10
+ echo v{novar + CONT(t)}
+ elseif t == 11
+ echo F{novar + CONT(t)}
+ elseif t == 12
+ let var = novar + CONT(t)
+ elseif t == 13
+ let var = v{novar + CONT(t)}
+ elseif t == 14
+ let var = F{novar + CONT(t)}()
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ let caught = 1
+ finally
+ if !caught " no error exceptions ($VIMNOERRTHROW set)
+ if t <= 8 && t != 3
+ call MSG(t, 'E475', 'Invalid argument\>')
+ else
+ call MSG(t, 'E15', "Invalid expression")
+ endif
+ else
+ if t == 2 || t == 4
+ call MSG(t, 'E475', 'Invalid argument\>')
+ else
+ call MSG(t, 'E121', "Undefined variable")
+ endif
+ endif
+ let t = t + 1
+ XloopNEXT
+ continue " discard an aborting error
+ endtry
+ endwhile
+ catch /.*/
+ Xloop 1 " X: 0
+ Xout t.":" v:exception "in" ExtraVimThrowpoint()
+ endtry
+
+ function! T(n, expr, enr, emsg)
+ try
+ let g:taken = g:taken . "T" . a:n
+ let v:errmsg = ""
+ try
+ let caught = 0
+ execute "let var = " . a:expr
+ catch /^Vim\((\a\+)\)\=:/
+ " v:errmsg is not set when the error message is converted to an
+ " exception. Set it to the original error message.
+ let v:errmsg = substitute(v:exception,
+ \ '^Vim\((\a\+)\)\=:', '', "")
+ let caught = 1
+ finally
+ if !caught " no error exceptions ($VIMNOERRTHROW set)
+ call MSG(a:n, 'E15', "Invalid expression")
+ else
+ call MSG(a:n, a:enr, a:emsg)
+ endif
+ XloopNEXT
+ " Discard an aborting error:
+ return
+ endtry
+ catch /.*/
+ Xloop 1 " X: 0
+ Xout a:n.":" v:exception "in" ExtraVimThrowpoint()
+ endtry
+ endfunction
+
+ call T(15, 'Nofunc() + CONT(15)', 'E117', "Unknown function")
+ call T(16, 'F(1 2 + CONT(16))', 'E116', "Invalid arguments")
+ call T(17, 'F(1, 2) + CONT(17)', 'E118', "Too many arguments")
+ call T(18, 'F() + CONT(18)', 'E119', "Not enough arguments")
+ call T(19, '{(1} + CONT(19)', 'E110', "Missing ')'")
+ call T(20, '("abc"[1) + CONT(20)', 'E111', "Missing ']'")
+ call T(21, '(1 +) + CONT(21)', 'E15', "Invalid expression")
+ call T(22, '1 2 + CONT(22)', 'E15', "Invalid expression")
+ call T(23, '(1 ? 2) + CONT(23)', 'E109', "Missing ':' after '?'")
+ call T(24, '("abc) + CONT(24)', 'E114', "Missing quote")
+ call T(25, "('abc) + CONT(25)", 'E115', "Missing quote")
+ call T(26, '& + CONT(26)', 'E112', "Option name missing")
+ call T(27, '&asdf + CONT(27)', 'E113', "Unknown option")
+
+ Xpath 134217728 " X: 134217728
+
+ let expected = ""
+ \ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
+ \ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
+ \ . "T26M26T27M27"
+
+ if taken != expected
+ Xpath 268435456 " X: 0
+ Xout "'taken' is" taken "instead of" expected
+ if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected
+ Xout "Is ++emsg_skip for var with expr_start non-NULL"
+ \ "in f_exists ok?"
+ endif
+ endif
+
+ unlet! var caught taken expected
+ call delete(WA_t5)
+ unlet! WA_t5
+ delfunction WA_t5
+
+endif
+
+Xcheck 134217728
+
+
+"-------------------------------------------------------------------------------
+" Test 79: Throwing one of several errors for the same command {{{1
+"
+" When several errors appear in a row (for instance during expression
+" evaluation), the first as the most specific one is used when
+" throwing an error exception. If, however, a syntax error is
+" detected afterwards, this one is used for the error exception.
+" On a syntax error, the next command is not executed, on a normal
+" error, however, it is (relevant only in a function without the
+" "abort" flag). v:errmsg is not set.
+"
+" If throwing error exceptions is configured off, v:errmsg is always
+" set to the latest error message, that is, to the more general
+" message or the syntax error, respectively.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+XloopINIT 1 2
+
+function! NEXT(cmd)
+ exec a:cmd . " | Xloop 1"
+endfunction
+
+call NEXT('echo novar') " X: 1 * 1 (checks nextcmd)
+XloopNEXT
+call NEXT('let novar #') " X: 0 * 2 (skips nextcmd)
+XloopNEXT
+call NEXT('unlet novar #') " X: 0 * 4 (skips nextcmd)
+XloopNEXT
+call NEXT('let {novar}') " X: 0 * 8 (skips nextcmd)
+XloopNEXT
+call NEXT('unlet{ novar}') " X: 0 * 16 (skips nextcmd)
+
+function! EXEC(cmd)
+ exec a:cmd
+endfunction
+
+function! MATCH(expected, msg, enr, emsg)
+ let msg = a:msg
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let msg = ":" . msg
+ endif
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg)
+ let match = 0
+ if a:expected " no match although expected
+ if a:msg == ""
+ Xout "Message missing."
+ else
+ let msg = escape(msg, '"')
+ Xout "Unexpected message:" msg
+ endif
+ endif
+ else
+ let match = 1
+ if !a:expected " match although not expected
+ let msg = escape(msg, '"')
+ Xout "Unexpected message:" msg
+ endif
+ endif
+ return match
+endfunction
+
+try
+
+ while 1 " dummy loop
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC('echo novar') " normal error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 32 " X: 32
+ if !caught
+ if !$VIMNOERRTHROW
+ Xpath 64 " X: 0
+ endif
+ elseif !MATCH(1, thrmsg, 'E121', "Undefined variable")
+ \ || v:errmsg != ""
+ Xpath 128 " X: 0
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression")
+ Xpath 256 " X: 0
+ endif
+ break " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+ Xpath 512 " X: 512
+ let cmd = "let"
+ XloopINIT 1024 32
+ while cmd != ""
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC(cmd . ' novar #') " normal plus syntax error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xloop 1 " X: 1024 * (1 + 32)
+ if !caught
+ if !$VIMNOERRTHROW
+ Xloop 2 " X: 0
+ endif
+ else
+ if cmd == "let"
+ let match = MATCH(0, thrmsg, 'E106', "Unknown variable")
+ elseif cmd == "unlet"
+ let match = MATCH(0, thrmsg, 'E108', "No such variable")
+ endif
+ if match " normal error
+ Xloop 4 " X: 0
+ endif
+ if !MATCH(1, thrmsg, 'E488', "Trailing characters")
+ \|| v:errmsg != ""
+ " syntax error
+ Xloop 8 " X: 0
+ endif
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters")
+ " last error
+ Xloop 16 " X: 0
+ endif
+ if cmd == "let"
+ let cmd = "unlet"
+ else
+ let cmd = ""
+ endif
+ XloopNEXT
+ continue " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+ Xpath 1048576 " X: 1048576
+ let cmd = "let"
+ XloopINIT 2097152 32
+ while cmd != ""
+ try
+ let v:errmsg = ""
+ let caught = 0
+ let thrmsg = ""
+ call EXEC(cmd . ' {novar}') " normal plus syntax error
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xloop 1 " X: 2097152 * (1 + 32)
+ if !caught
+ if !$VIMNOERRTHROW
+ Xloop 2 " X: 0
+ endif
+ else
+ if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error
+ Xloop 4 " X: 0
+ endif
+ if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>')
+ \ || v:errmsg != "" " syntax error
+ Xloop 8 " X: 0
+ endif
+ endif
+ if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>')
+ " last error
+ Xloop 16 " X: 0
+ endif
+ if cmd == "let"
+ let cmd = "unlet"
+ else
+ let cmd = ""
+ endif
+ XloopNEXT
+ continue " discard error if $VIMNOERRTHROW == 1
+ endtry
+ endwhile
+
+catch /.*/
+ " The Xpath command does not accept 2^31 (negative); add explicitly:
+ let Xpath = Xpath + 2147483648 " X: 0
+ Xout v:exception "in" v:throwpoint
+endtry
+
+unlet! next_command thrmsg match
+delfunction NEXT
+delfunction EXEC
+delfunction MATCH
+
+Xcheck 70288929
+
+
+"-------------------------------------------------------------------------------
+" Test 80: Syntax error in expression for illegal :elseif {{{1
+"
+" If there is a syntax error in the expression after an illegal
+" :elseif, an error message is given (or an error exception thrown)
+" for the illegal :elseif rather than the expression error.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+let v:errmsg = ""
+if 0
+else
+elseif 1 ||| 2
+endif
+Xpath 1 " X: 1
+if !MSG('E584', ":elseif after :else")
+ Xpath 2 " X: 0
+endif
+
+let v:errmsg = ""
+if 1
+else
+elseif 1 ||| 2
+endif
+Xpath 4 " X: 4
+if !MSG('E584', ":elseif after :else")
+ Xpath 8 " X: 0
+endif
+
+let v:errmsg = ""
+elseif 1 ||| 2
+Xpath 16 " X: 16
+if !MSG('E582', ":elseif without :if")
+ Xpath 32 " X: 0
+endif
+
+let v:errmsg = ""
+while 1
+ elseif 1 ||| 2
+endwhile
+Xpath 64 " X: 64
+if !MSG('E582', ":elseif without :if")
+ Xpath 128 " X: 0
+endif
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ if 0
+ else
+ elseif 1 ||| 2
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 256 " X: 256
+ if !caught && !$VIMNOERRTHROW
+ Xpath 512 " X: 0
+ endif
+ if !MSG('E584', ":elseif after :else")
+ Xpath 1024 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ if 1
+ else
+ elseif 1 ||| 2
+ endif
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 4096 " X: 4096
+ if !caught && !$VIMNOERRTHROW
+ Xpath 8192 " X: 0
+ endif
+ if !MSG('E584', ":elseif after :else")
+ Xpath 16384 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ elseif 1 ||| 2
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 65536 " X: 65536
+ if !caught && !$VIMNOERRTHROW
+ Xpath 131072 " X: 0
+ endif
+ if !MSG('E582', ":elseif without :if")
+ Xpath 262144 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let v:errmsg = ""
+ let caught = 0
+ while 1
+ elseif 1 ||| 2
+ endwhile
+ catch /^Vim\((\a\+)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
+ finally
+ Xpath 1048576 " X: 1048576
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2097152 " X: 0
+ endif
+ if !MSG('E582', ":elseif without :if")
+ Xpath 4194304 " X: 0
+ endif
+ endtry
+ catch /.*/
+ Xpath 8388608 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+Xpath 16777216 " X: 16777216
+
+unlet! caught
+delfunction MSG
+
+Xcheck 17895765
+
+
+"-------------------------------------------------------------------------------
+" Test 81: Discarding exceptions after an error or interrupt {{{1
+"
+" When an exception is thrown from inside a :try conditional without
+" :catch and :finally clauses and an error or interrupt occurs before
+" the :endtry is reached, the exception is discarded.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ throw "arrgh"
+ Xpath 4 " X: 0
+" if 1
+ Xpath 8 " X: 0
+ " error after :throw: missing :endif
+ endtry
+ Xpath 16 " X: 0
+ catch /arrgh/
+ Xpath 32 " X: 0
+ endtry
+ Xpath 64 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 128 " X: 128
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ Xpath 512 " X: 0
+ endtry " INTERRUPT
+ Xpath 1024 " X: 0
+ catch /arrgh/
+ Xpath 2048 " X: 0
+ endtry
+ Xpath 4096 " X: 0
+endif
+
+Xcheck 387
+
+
+"-------------------------------------------------------------------------------
+" Test 82: Ignoring :catch clauses after an error or interrupt {{{1
+"
+" When an exception is thrown and an error or interrupt occurs before
+" the matching :catch clause is reached, the exception is discarded
+" and the :catch clause is ignored (also for the error or interrupt
+" exception being thrown then).
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ try
+ Xpath 1 " X: 1
+ throw "arrgh"
+ Xpath 2 " X: 0
+" if 1
+ Xpath 4 " X: 0
+ " error after :throw: missing :endif
+ catch /.*/
+ Xpath 8 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 32 " X: 0
+ catch /arrgh/
+ Xpath 64 " X: 0
+ endtry
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim()
+ function! E()
+ try
+ try
+ Xpath 256 " X: 256
+ throw "arrgh"
+ Xpath 512 " X: 0
+" if 1
+ Xpath 1024 " X: 0
+ " error after :throw: missing :endif
+ catch /.*/
+ Xpath 2048 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 4096 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 8192 " X: 0
+ catch /arrgh/
+ Xpath 16384 " X: 0
+ endtry
+ endfunction
+
+ call E()
+ Xpath 32768 " X: 0
+endif
+
+if ExtraVim()
+ try
+ try
+ Xpath 65536 " X: 65536
+ throw "arrgh"
+ Xpath 131072 " X: 0
+ catch /.*/ "INTERRUPT
+ Xpath 262144 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 524288 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 1048576 " X: 0
+ catch /arrgh/
+ Xpath 2097152 " X: 0
+ endtry
+ Xpath 4194304 " X: 0
+endif
+
+if ExtraVim()
+ function I()
+ try
+ try
+ Xpath 8388608 " X: 8388608
+ throw "arrgh"
+ Xpath 16777216 " X: 0
+ catch /.*/ "INTERRUPT
+ Xpath 33554432 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ catch /.*/
+ Xpath 67108864 " X: 0
+ Xout v:exception "in" ExtraVimThrowpoint()
+ endtry
+ Xpath 134217728 " X: 0
+ catch /arrgh/
+ Xpath 268435456 " X: 0
+ endtry
+ endfunction
+
+ call I()
+ Xpath 536870912 " X: 0
+endif
+
+Xcheck 8454401
+
+
+"-------------------------------------------------------------------------------
+" Test 83: Executing :finally clauses after an error or interrupt {{{1
+"
+" When an exception is thrown and an error or interrupt occurs before
+" the :finally of the innermost :try is reached, the exception is
+" discarded and the :finally clause is executed.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+ try
+ Xpath 1 " X: 1
+ try
+ Xpath 2 " X: 2
+ throw "arrgh"
+ Xpath 4 " X: 0
+" if 1
+ Xpath 8 " X: 0
+ " error after :throw: missing :endif
+ finally
+ Xpath 16 " X: 16
+ endtry
+ Xpath 32 " X: 0
+ catch /arrgh/
+ Xpath 64 " X: 0
+ endtry
+ Xpath 128 " X: 0
+endif
+
+if ExtraVim()
+ try
+ Xpath 256 " X: 256
+ try
+ Xpath 512 " X: 512
+ throw "arrgh"
+ Xpath 1024 " X: 0
+ finally "INTERRUPT
+ Xpath 2048 " X: 2048
+ endtry
+ Xpath 4096 " X: 0
+ catch /arrgh/
+ Xpath 8192 " X: 0
+ endtry
+ Xpath 16384 " X: 0
+endif
+
+Xcheck 2835
+
+
+"-------------------------------------------------------------------------------
+" Test 84: Exceptions in autocommand sequences. {{{1
+"
+" When an exception occurs in a sequence of autocommands for
+" a specific event, the rest of the sequence is not executed. The
+" command that triggered the autocommand execution aborts, and the
+" exception is propagated to the caller.
+"
+" For the FuncUndefined event under a function call expression or
+" :call command, the function is not exexecuted, even when it has
+" been defined by the autocommands before the exception occurred.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! INT()
+ "INTERRUPT
+ let dummy = 0
+ endfunction
+
+ aug TMP
+ autocmd!
+
+ autocmd User x1 Xpath 1 " X: 1
+ autocmd User x1 throw "x1"
+ autocmd User x1 Xpath 2 " X: 0
+
+ autocmd User x2 Xpath 4 " X: 4
+ autocmd User x2 asdf
+ autocmd User x2 Xpath 8 " X: 0
+
+ autocmd User x3 Xpath 16 " X: 16
+ autocmd User x3 call INT()
+ autocmd User x3 Xpath 32 " X: 0
+
+ autocmd FuncUndefined U1 function! U1()
+ autocmd FuncUndefined U1 Xpath 64 " X: 0
+ autocmd FuncUndefined U1 endfunction
+ autocmd FuncUndefined U1 Xpath 128 " X: 128
+ autocmd FuncUndefined U1 throw "U1"
+ autocmd FuncUndefined U1 Xpath 256 " X: 0
+
+ autocmd FuncUndefined U2 function! U2()
+ autocmd FuncUndefined U2 Xpath 512 " X: 0
+ autocmd FuncUndefined U2 endfunction
+ autocmd FuncUndefined U2 Xpath 1024 " X: 1024
+ autocmd FuncUndefined U2 ASDF
+ autocmd FuncUndefined U2 Xpath 2048 " X: 0
+
+ autocmd FuncUndefined U3 function! U3()
+ autocmd FuncUndefined U3 Xpath 4096 " X: 0
+ autocmd FuncUndefined U3 endfunction
+ autocmd FuncUndefined U3 Xpath 8192 " X: 8192
+ autocmd FuncUndefined U3 call INT()
+ autocmd FuncUndefined U3 Xpath 16384 " X: 0
+ aug END
+
+ try
+ try
+ Xpath 32768 " X: 32768
+ doautocmd User x1
+ catch /x1/
+ Xpath 65536 " X: 65536
+ endtry
+
+ while 1
+ try
+ Xpath 131072 " X: 131072
+ let caught = 0
+ doautocmd User x2
+ catch /asdf/
+ let caught = 1
+ finally
+ Xpath 262144 " X: 262144
+ if !caught && !$VIMNOERRTHROW
+ Xpath 524288 " X: 0
+ " Propagate uncaught error exception,
+ else
+ " ... but break loop for caught error exception,
+ " or discard error and break loop if $VIMNOERRTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ while 1
+ try
+ Xpath 1048576 " X: 1048576
+ let caught = 0
+ doautocmd User x3
+ catch /Vim:Interrupt/
+ let caught = 1
+ finally
+ Xpath 2097152 " X: 2097152
+ if !caught && !$VIMNOINTTHROW
+ Xpath 4194304 " X: 0
+ " Propagate uncaught interrupt exception,
+ else
+ " ... but break loop for caught interrupt exception,
+ " or discard interrupt and break loop if $VIMNOINTTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ if exists("*U1") | delfunction U1 | endif
+ if exists("*U2") | delfunction U2 | endif
+ if exists("*U3") | delfunction U3 | endif
+
+ try
+ Xpath 8388608 " X: 8388608
+ call U1()
+ catch /U1/
+ Xpath 16777216 " X: 16777216
+ endtry
+
+ while 1
+ try
+ Xpath 33554432 " X: 33554432
+ let caught = 0
+ call U2()
+ catch /ASDF/
+ let caught = 1
+ finally
+ Xpath 67108864 " X: 67108864
+ if !caught && !$VIMNOERRTHROW
+ Xpath 134217728 " X: 0
+ " Propagate uncaught error exception,
+ else
+ " ... but break loop for caught error exception,
+ " or discard error and break loop if $VIMNOERRTHROW
+ break
+ endif
+ endtry
+ endwhile
+
+ while 1
+ try
+ Xpath 268435456 " X: 268435456
+ let caught = 0
+ call U3()
+ catch /Vim:Interrupt/
+ let caught = 1
+ finally
+ Xpath 536870912 " X: 536870912
+ if !caught && !$VIMNOINTTHROW
+ Xpath 1073741824 " X: 0
+ " Propagate uncaught interrupt exception,
+ else
+ " ... but break loop for caught interrupt exception,
+ " or discard interrupt and break loop if $VIMNOINTTHROW
+ break
+ endif
+ endtry
+ endwhile
+ catch /.*/
+ " The Xpath command does not accept 2^31 (negative); display explicitly:
+ exec "!echo 2147483648 >>" . g:ExtraVimResult
+ Xout "Caught" v:exception "in" v:throwpoint
+ endtry
+
+ unlet caught
+ delfunction INT
+ delfunction U1
+ delfunction U2
+ delfunction U3
+ au! TMP
+ aug! TMP
+endif
+
+Xcheck 934782101
+
+
+"-------------------------------------------------------------------------------
+" Test 85: Error exceptions in autocommands for I/O command events {{{1
+"
+" When an I/O command is inside :try/:endtry, autocommands to be
+" executed after it should be skipped on an error (exception) in the
+" command itself or in autocommands to be executed before the command.
+" In the latter case, the I/O command should not be executed either.
+" Example 1: BufWritePre, :write, BufWritePost
+" Example 2: FileReadPre, :read, FileReadPost.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+function! MSG(enr, emsg)
+ let english = v:lang == "C" || v:lang =~ '^[Ee]n'
+ if a:enr == ""
+ Xout "TODO: Add message number for:" a:emsg
+ let v:errmsg = ":" . v:errmsg
+ endif
+ let match = 1
+ if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
+ let match = 0
+ if v:errmsg == ""
+ Xout "Message missing."
+ else
+ let v:errmsg = escape(v:errmsg, '"')
+ Xout "Unexpected message:" v:errmsg
+ endif
+ endif
+ return match
+endfunction
+
+" Remove the autocommands for the events specified as arguments in all used
+" autogroups.
+function! Delete_autocommands(...)
+ let augfile = tempname()
+ while 1
+ try
+ exec "redir >" . augfile
+ aug
+ redir END
+ exec "edit" augfile
+ g/^$/d
+ norm G$
+ let wrap = "w"
+ while search('\%( \|^\)\@<=.\{-}\%( \)\@=', wrap) > 0
+ let wrap = "W"
+ exec "norm y/ \n"
+ let argno = 1
+ while argno <= a:0
+ exec "au!" escape(@", " ") a:{argno}
+ let argno = argno + 1
+ endwhile
+ endwhile
+ catch /.*/
+ finally
+ bwipeout!
+ call delete(augfile)
+ break " discard errors for $VIMNOERRTHROW
+ endtry
+ endwhile
+endfunction
+
+call Delete_autocommands("BufWritePre", "BufWritePost")
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! BufWritePost * let post = 1
+ aug END
+ let caught = 0
+ write /n/o/n/e/x/i/s/t/e/n/t
+ catch /^Vim(write):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
+ finally
+ Xpath 1 " X: 1
+ if !caught && !$VIMNOERRTHROW
+ Xpath 2 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
+ \ '', "")
+ if !MSG('E212', "Can't open file for writing")
+ Xpath 4 " X: 0
+ endif
+ if post
+ Xpath 8 " X: 0
+ Xout "BufWritePost commands executed after write error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 16 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! BufWritePre * asdf
+ au! BufWritePost * let post = 1
+ aug END
+ let tmpfile = tempname()
+ let caught = 0
+ exec "write" tmpfile
+ catch /^Vim\((write)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
+ finally
+ Xpath 32 " X: 32
+ if !caught && !$VIMNOERRTHROW
+ Xpath 64 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
+ if !MSG('E492', "Not an editor command")
+ Xpath 128 " X: 0
+ endif
+ if filereadable(tmpfile)
+ Xpath 256 " X: 0
+ Xout ":write command not suppressed after BufWritePre error"
+ endif
+ if post
+ Xpath 512 " X: 0
+ Xout "BufWritePost commands executed after BufWritePre error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 1024 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+call delete(tmpfile)
+
+call Delete_autocommands("BufWritePre", "BufWritePost",
+ \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
+
+while 1
+ try
+ try
+ let post = 0
+ aug TMP
+ au! FileReadPost * let post = 1
+ aug END
+ let caught = 0
+ read /n/o/n/e/x/i/s/t/e/n/t
+ catch /^Vim(read):/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
+ finally
+ Xpath 2048 " X: 2048
+ if !caught && !$VIMNOERRTHROW
+ Xpath 4096 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
+ \ '', "")
+ if !MSG('E484', "Can't open file")
+ Xpath 8192 " X: 0
+ endif
+ if post
+ Xpath 16384 " X: 0
+ Xout "FileReadPost commands executed after write error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ catch /.*/
+ Xpath 32768 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+while 1
+ try
+ let infile = tempname()
+ let tmpfile = tempname()
+ exec "!echo XYZ >" . infile
+ exec "edit" tmpfile
+ try
+ Xpath 65536 " X: 65536
+ try
+ let post = 0
+ aug TMP
+ au! FileReadPre * asdf
+ au! FileReadPost * let post = 1
+ aug END
+ let caught = 0
+ exec "0read" infile
+ catch /^Vim\((read)\)\=:/
+ let caught = 1
+ let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
+ \ "")
+ finally
+ Xpath 131072 " X: 131072
+ if !caught && !$VIMNOERRTHROW
+ Xpath 262144 " X: 0
+ endif
+ let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
+ if !MSG('E492', "Not an editor command")
+ Xpath 524288 " X: 0
+ endif
+ if getline("1") == "XYZ"
+ Xpath 1048576 " X: 0
+ Xout ":read command not suppressed after FileReadPre error"
+ endif
+ if post
+ Xpath 2097152 " X: 0
+ Xout "FileReadPost commands executed after " .
+ \ "FileReadPre error"
+ endif
+ au! TMP
+ aug! TMP
+ endtry
+ finally
+ bwipeout!
+ endtry
+ catch /.*/
+ Xpath 4194304 " X: 0
+ Xout v:exception "in" v:throwpoint
+ finally
+ break " discard error for $VIMNOERRTHROW
+ endtry
+endwhile
+
+call delete(infile)
+call delete(tmpfile)
+unlet! caught post infile tmpfile
+delfunction MSG
+delfunction Delete_autocommands
+
+Xcheck 198689
+
+
+"-------------------------------------------------------------------------------
+" Test 86: $VIMNOERRTHROW and $VIMNOINTTHROW support {{{1
+"
+" It is possible to configure Vim for throwing exceptions on error
+" or interrupt, controlled by variables $VIMNOERRTHROW and
+" $VIMNOINTTHROW. This is just for increasing the number of tests.
+" All tests here should run for all four combinations of setting
+" these variables to 0 or 1. The variables are intended for the
+" development phase only. In the final release, Vim should be
+" configured to always use error and interrupt exceptions.
+"
+" The test result is "OK",
+"
+" - if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
+" configured and exceptions are thrown on error and on
+" interrupt.
+"
+" - if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
+" configured and works as intended.
+"
+" What actually happens, is shown in the test output.
+"
+" Otherwise, the test result is "FAIL", and the test output describes
+" the problem.
+"
+" IMPORTANT: This must be the last test because it sets $VIMNOERRTHROW and
+" $VIMNOINTTHROW.
+"-------------------------------------------------------------------------------
+
+XpathINIT
+
+if ExtraVim()
+
+ function! ThrowOnError()
+ XloopNEXT
+ let caught = 0
+ try
+ Xloop 1 " X: 1 + 8 + 64
+ asdf
+ catch /.*/
+ let caught = 1 " error exception caught
+ finally
+ Xloop 2 " X: 2 + 16 + 128
+ return caught " discard aborting error
+ endtry
+ Xloop 4 " X: 0
+ endfunction
+
+ let quits_skipped = 0
+
+ function! ThrowOnInterrupt()
+ XloopNEXT
+ let caught = 0
+ try
+ Xloop 1 " X: (1 + 8 + 64) * 512
+ "INTERRUPT3
+ let dummy = 0
+ let g:quits_skipped = g:quits_skipped + 1
+ catch /.*/
+ let caught = 1 " interrupt exception caught
+ finally
+ Xloop 2 " X: (2 + 16 + 128) * 512
+ return caught " discard interrupt
+ endtry
+ Xloop 4 " X: 0
+ endfunction
+
+ function! CheckThrow(Type)
+ execute 'return ThrowOn' . a:Type . '()'
+ endfunction
+
+ function! CheckConfiguration(type) " type is "error" or "interrupt"
+
+ let type = a:type
+ let Type = substitute(type, '.*', '\u&', "")
+ let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
+
+ if type == "error"
+ XloopINIT! 1 8
+ elseif type == "interrupt"
+ XloopINIT! 512 8
+ endif
+
+ exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
+ exec 'let suppressed_for_tests = ' . VAR . ' != 0'
+ let used_in_tests = CheckThrow(Type)
+
+ exec 'let ' . VAR . ' = 0'
+ let request_works = CheckThrow(Type)
+
+ exec 'let ' . VAR . ' = 1'
+ let suppress_works = !CheckThrow(Type)
+
+ if type == "error"
+ XloopINIT! 262144 8
+ elseif type == "interrupt"
+ XloopINIT! 2097152 8
+
+ if g:quits_skipped != 0
+ Xloop 1 " X: 0*2097152
+ Xout "Test environment error. Interrupt breakpoints skipped: "
+ \ . g:quits_skipped . ".\n"
+ \ . "Cannot check whether interrupt exceptions are thrown."
+ return
+ endif
+ endif
+
+ let failure =
+ \ !suppressed_for_tests && !used_in_tests
+ \ || !request_works
+
+ let contradiction =
+ \ used_in_tests
+ \ ? suppressed_for_tests && !request_works
+ \ : !suppressed_for_tests
+
+ if failure
+ " Failure in configuration.
+ Xloop 2 " X: 0 * 2* (262144 + 2097152)
+ elseif contradiction
+ " Failure in test logic. Should not happen.
+ Xloop 4 " X: 0 * 4 * (262144 + 2097152)
+ endif
+
+ let var_control_configured =
+ \ request_works != used_in_tests
+ \ || suppress_works == used_in_tests
+
+ let var_control_not_configured =
+ \ requested_for_tests || suppressed_for_tests
+ \ ? request_works && !suppress_works
+ \ : request_works == used_in_tests
+ \ && suppress_works != used_in_tests
+
+ let with = used_in_tests ? "with" : "without"
+
+ let set = suppressed_for_tests ? "non-zero" :
+ \ requested_for_tests ? "0" : "unset"
+
+ let although = contradiction && !var_control_not_configured
+ \ ? ",\nalthough "
+ \ : ".\n"
+
+ let output = "All tests were run " . with . " throwing exceptions on "
+ \ . type . although
+
+ if !var_control_not_configured
+ let output = output . VAR . " was " . set . "."
+
+ if !request_works && !requested_for_tests
+ let output = output .
+ \ "\n" . Type . " exceptions are not thrown when " . VAR .
+ \ " is\nset to 0."
+ endif
+
+ if !suppress_works && (!used_in_tests ||
+ \ !request_works &&
+ \ !requested_for_tests && !suppressed_for_tests)
+ let output = output .
+ \ "\n" . Type . " exceptions are thrown when " . VAR .
+ \ " is set to 1."
+ endif
+
+ if !failure && var_control_configured
+ let output = output .
+ \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
+ \ . "=" . used_in_tests . "."
+ \ . "\nThis is for testing in the development phase only."
+ \ . " Remove the \n"
+ \ . VAR . " control in the final release."
+ endif
+ else
+ let output = output .
+ \ "The " . VAR . " control is not configured."
+ endif
+
+ Xout output
+ endfunction
+
+ call CheckConfiguration("error")
+ Xpath 16777216 " X: 16777216
+ call CheckConfiguration("interrupt")
+ Xpath 33554432 " X: 33554432
+endif
+
+Xcheck 50443995
+
+" IMPORTANT: No test should be added after this test because it changes
+" $VIMNOERRTHROW and $VIMNOINTTHROW.
+
+
+"-------------------------------------------------------------------------------
+" Modelines {{{1
+" vim: ts=8 sw=4 tw=80 fdm=marker
+" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
+"-------------------------------------------------------------------------------
diff --git a/src/testdir/test5.in b/src/testdir/test5.in
new file mode 100644
index 000000000..e19e20d59
--- /dev/null
+++ b/src/testdir/test5.in
@@ -0,0 +1,29 @@
+Test for autocommand that deletes the current buffer on BufLeave event.
+Also test deleting the last buffer, should give a new, empty buffer.
+
+STARTTEST
+:so small.vim
+:au BufLeave Xxx bwipe
+/start of
+:.,/end of/w! Xxx " write test file Xxx
+:sp Xxx " split to Xxx
+:bwipe " delete buffer Xxx, now we're back here
+G?this is a
+othis is some more text
+: " Append some text to this file
+:?start?,$w! test.out " Write current file contents
+:bwipe test.out " delete alternate buffer
+:au bufleave test5.in bwipe
+:bwipe! " delete current buffer, get an empty one
+ithis is another test line:w >>test.out
+: " append an extra line to the output file
+:qa!
+ENDTEST
+
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test5.ok b/src/testdir/test5.ok
new file mode 100644
index 000000000..674306079
--- /dev/null
+++ b/src/testdir/test5.ok
@@ -0,0 +1,9 @@
+start of test file Xxx
+vim: set noai :
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+this is some more text
+end of test file Xxx
+this is another test line
diff --git a/src/testdir/test50.in b/src/testdir/test50.in
new file mode 100644
index 000000000..d78ac8e8f
--- /dev/null
+++ b/src/testdir/test50.in
@@ -0,0 +1,85 @@
+Test for shortpathname ':8' extension.
+Only for use on Win32 systems!
+
+STARTTEST
+:so small.vim
+:fun! TestIt(file, bits, expected)
+ let res=fnamemodify(a:file,a:bits)
+ if a:expected == ''
+ echo "'".a:file."'->(".a:bits.")->'".res."'"
+ else
+ if substitute(res,'/','\\', 'g') != substitute( a:expected, '/','\\', 'g')
+ echo "FAILED: '".a:file."'->(".a:bits.")->'".res."'"
+ echo "Expected: '".a:expected."'"
+ else
+ echo "OK"
+ endif
+ endif
+endfun
+:fun! MakeDir( dirname )
+ "exe '!mkdir '.substitute(a:dirname,'/','\\','g')
+ call system('mkdir '.substitute(a:dirname,'/','\\','g'))
+endfun
+:fun! RMDir( dirname)
+ "exe '!rmdir '.substitute(a:dirname,'/','\\','g')
+ call system('rmdir '.substitute(a:dirname,'/','\\','g'))
+endfun
+:fun! MakeFile( filename)
+ "exe '!copy nul '.substitute(a:filename,'/','\\','g')
+ call system('copy nul '.substitute(a:filename,'/','\\','g'))
+endfun
+:fun! TestColonEight()
+ redir! >test.out
+ " This could change for CygWin to //cygdrive/c
+ let dir1='c:/x.x.y'
+ if filereadable(dir1) || isdirectory(dir1)
+ call confirm( "'".dir1."' exists, cannot run test" )
+ return
+ endif
+ let file1=dir1.'/zz.y.txt'
+ let nofile1=dir1.'/z.y.txt'
+ let dir2=dir1.'/VimIsTheGreatestSinceSlicedBread'
+ let file2=dir2.'/z.txt'
+ let nofile2=dir2.'/zz.txt'
+ let resdir1='c:/XX2235~1.Y'
+ let resfile1=resdir1.'/ZZY~1.TXT'
+ let resnofile1=resdir1.'/z.y.txt'
+ let resdir2=resdir1.'/VIMIST~1'
+ let resfile2=resdir2.'/z.txt'
+ let resnofile2=resdir2.'/zz.txt'
+ call MakeDir( dir1 )
+ call MakeDir( dir2 )
+ call MakeFile( file1 )
+ call MakeFile( file2 )
+ call TestIt(file1, ':p:8', resfile1)
+ call TestIt(nofile1, ':p:8', resnofile1)
+ call TestIt(file2, ':p:8', resfile2)
+ call TestIt(nofile2, ':p:8', resnofile2)
+ call TestIt(nofile2, ':p:8:h', fnamemodify(resnofile2,':h'))
+ exe 'cd '.dir1
+ call TestIt(file1, ':.:8', strpart(resfile1,strlen(resdir1)+1))
+ call TestIt(nofile1, ':.:8', strpart(resnofile1,strlen(resdir1)+1))
+ call TestIt(file2, ':.:8', strpart(resfile2,strlen(resdir1)+1))
+ call TestIt(nofile2, ':.:8', strpart(resnofile2,strlen(resdir1)+1))
+ let $HOME=dir1
+ call TestIt(file1, ':~:8', '~'.strpart(resfile1,strlen(resdir1)))
+ call TestIt(nofile1, ':~:8', '~'.strpart(resnofile1,strlen(resdir1)))
+ call TestIt(file2, ':~:8', '~'.strpart(resfile2,strlen(resdir1)))
+ call TestIt(nofile2, ':~:8', '~'.strpart(resnofile2,strlen(resdir1)))
+ cd c:/
+ call delete( file2 )
+ call delete( file1 )
+ call RMDir( dir2 )
+ call RMDir( dir1 )
+ echo
+ redir END
+endfun
+:let dir = getcwd()
+:call TestColonEight()
+:exe "cd " . dir
+:edit! test.out
+:set ff=dos
+:w
+:qa!
+ENDTEST
+
diff --git a/src/testdir/test50.ok b/src/testdir/test50.ok
new file mode 100644
index 000000000..91ef1d660
--- /dev/null
+++ b/src/testdir/test50.ok
@@ -0,0 +1,14 @@
+
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
+OK
diff --git a/src/testdir/test51.in b/src/testdir/test51.in
new file mode 100644
index 000000000..a158c8691
--- /dev/null
+++ b/src/testdir/test51.in
@@ -0,0 +1,34 @@
+Tests for ":highlight". vim: set ft=vim :
+
+STARTTEST
+:so small.vim
+:" basic test if ":highlight" doesn't crash
+:highlight
+:hi Search
+:" test setting colors.
+:" test clearing one color and all doesn't generate error or warning
+:hi NewGroup term=bold cterm=italic ctermfg=DarkBlue ctermbg=Grey gui= guifg=#00ff00 guibg=Cyan
+:hi Group2 term= cterm=
+:hi Group3 term=underline cterm=bold
+:redir >test.out
+:hi NewGroup
+:hi Group2
+:hi Group3
+:hi clear NewGroup
+:hi NewGroup
+:hi Group2
+:hi Group2 NONE
+:hi Group2
+:hi clear
+:hi Group3
+:hi Crash term='asdf
+:redir END
+:" filter ctermfg and ctermbg, the numbers depend on the terminal
+:e test.out
+:%s/ctermfg=\d*/ctermfg=2/
+:%s/ctermbg=\d*/ctermbg=3/
+:" filter out possibly translated error message
+:%s/E475: [^:]*:/E475:/
+:wq!
+ENDTEST
+
diff --git a/src/testdir/test51.ok b/src/testdir/test51.ok
new file mode 100644
index 000000000..fae83936c
--- /dev/null
+++ b/src/testdir/test51.ok
@@ -0,0 +1,15 @@
+
+
+NewGroup xxx term=bold cterm=italic ctermfg=2 ctermbg=3
+
+
+Group3 xxx term=underline cterm=bold
+
+
+
+
+
+
+
+
+E475: term='asdf
diff --git a/src/testdir/test52.in b/src/testdir/test52.in
new file mode 100644
index 000000000..206b65a1f
--- /dev/null
+++ b/src/testdir/test52.in
@@ -0,0 +1,65 @@
+Tests for reading and writing files with conversion for Win32.
+
+STARTTEST
+:so mbyte.vim
+:" make this a dummy test for non-Win32 systems
+:if !has("win32") | e! test.ok | wq! test.out | endif
+:"
+:" write tests:
+:" combine three values for 'encoding' with three values for 'fileencoding'
+:" also write files for read tests
+/^1
+:set encoding=utf-8
+:.w! ++enc=utf-8 test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=utf-8 Xutf8
+/^2
+:set encoding=cp1251
+:.w ++enc=utf-8 >>test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=cp1251 Xcp1251
+/^3
+:set encoding=cp866
+:.w ++enc=utf-8 >>test.out
+:.w ++enc=cp1251 >>test.out
+:.w ++enc=cp866 >>test.out
+:.w! ++enc=cp866 Xcp866
+:"
+:" read three 'fileencoding's with utf-8 'encoding'
+:set encoding=utf-8 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=utf-8 >>test.out
+:e Xcp1251
+:.w ++enc=utf-8 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=utf-8 >>test.out
+:"
+:" read three 'fileencoding's with cp1251 'encoding'
+:set encoding=utf-8 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=cp1251 >>test.out
+:e Xcp1251
+:.w ++enc=cp1251 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=cp1251 >>test.out
+:"
+:" read three 'fileencoding's with cp866 'encoding'
+:set encoding=cp866 fencs=utf-8,cp1251
+:e Xutf8
+:.w ++enc=cp866 >>test.out
+:e Xcp1251
+:.w ++enc=cp866 >>test.out
+:set fencs=utf-8,cp866
+:e Xcp866
+:.w ++enc=cp866 >>test.out
+:"
+:qa!
+ENDTEST
+
+1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+2 cp1251 text: Vim version 6.2. : 1970 Jan 01
+3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01
diff --git a/src/testdir/test52.ok b/src/testdir/test52.ok
new file mode 100644
index 000000000..90b516508
--- /dev/null
+++ b/src/testdir/test52.ok
@@ -0,0 +1,18 @@
+1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+1 utf-8 text: Vim version 6.2. : 1970 Jan 01
+1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01
+2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+2 cp1251 text: Vim version 6.2. : 1970 Jan 01
+2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01
+3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+3 cp866 text: Vim version 6.2. : 1970 Jan 01
+3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01
+1 utf-8 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+2 cp1251 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+3 cp866 text: Для Vim version 6.2. Последнее изменение: 1970 Jan 01
+1 utf-8 text: Vim version 6.2. : 1970 Jan 01
+2 cp1251 text: Vim version 6.2. : 1970 Jan 01
+3 cp866 text: Vim version 6.2. : 1970 Jan 01
+1 utf-8 text: Vim version 6.2. ᫥ : 1970 Jan 01
+2 cp1251 text: Vim version 6.2. ᫥ : 1970 Jan 01
+3 cp866 text: Vim version 6.2. ᫥ : 1970 Jan 01
diff --git a/src/testdir/test6.in b/src/testdir/test6.in
new file mode 100644
index 000000000..1ebbe2fa5
--- /dev/null
+++ b/src/testdir/test6.in
@@ -0,0 +1,24 @@
+Test for autocommand that redefines the argument list, when doing ":all".
+
+STARTTEST
+:so small.vim
+:au BufReadPost Xxx2 next Xxx2 Xxx1
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+$r3:.,/end of/w! Xxx3 " write test file Xxx3
+:next! Xxx1 Xxx2 Xxx3 " redefine arglist; go to Xxx1
+:all " open window for all args
+:w! test.out " Write contents of Xxx1
+:w >>test.out " Append contents of last window (Xxx1)
+:rew " should now be in Xxx2
+:w >>test.out " Append contents of Xxx2
+:qa!
+ENDTEST
+
+start of test file Xxx
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test6.ok b/src/testdir/test6.ok
new file mode 100644
index 000000000..b6b0c93e4
--- /dev/null
+++ b/src/testdir/test6.ok
@@ -0,0 +1,18 @@
+start of test file Xxx1
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx1
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx2
+ this is a test
+ this is a test
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test7.in b/src/testdir/test7.in
new file mode 100644
index 000000000..b9cc0585f
--- /dev/null
+++ b/src/testdir/test7.in
@@ -0,0 +1,26 @@
+Test for autocommand that changes the buffer list, when doing ":ball".
+
+STARTTEST
+:so small.vim
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+:sp Xxx1
+:close
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+:sp Xxx2
+:close
+$r3:.,/end of/w! Xxx3 " write test file Xxx3
+:sp Xxx3
+:close
+:au BufReadPost Xxx2 bwipe
+$r4:ball " open window for all args, close Xxx2
+:.,$w! test.out " Write contents of this file
+:w >>test.out " Append contents of second window (Xxx1)
+:/^start of/,$w >>test.out " Append contents of last window (this file)
+:qa!
+ENDTEST
+
+start of test file Xxx
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test7.ok b/src/testdir/test7.ok
new file mode 100644
index 000000000..a0d1ff94a
--- /dev/null
+++ b/src/testdir/test7.ok
@@ -0,0 +1,12 @@
+start of test file Xxx4
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx1
+ this is a test
+ this is a test
+end of test file Xxx
+start of test file Xxx4
+ this is a test
+ this is a test
+end of test file Xxx
diff --git a/src/testdir/test8.in b/src/testdir/test8.in
new file mode 100644
index 000000000..6fe171546
--- /dev/null
+++ b/src/testdir/test8.in
@@ -0,0 +1,24 @@
+Test for BufWritePre autocommand that deletes or unloads the buffer.
+
+STARTTEST
+:so small.vim
+:au BufWritePre Xxx1 bunload
+:au BufWritePre Xxx2 bwipe
+/^start of
+A1:.,/end of/w! Xxx1 " write test file Xxx1
+$r2:.,/end of/w! Xxx2 " write test file Xxx2
+:e! Xxx2 " edit Xxx2
+:bdel test8.in " delete this file from the buffer list
+:e Xxx1 " edit Xxx1
+:w " write it, will unload it and give an error msg
+:w! test.out " Write contents of this file
+:e! Xxx2 " start editing Xxx2
+:bwipe test.out " remove test.out from the buffer list
+:w " write it, will delete the buffer and give an error msg
+:w >>test.out " Append contents of this file
+:qa!
+ENDTEST
+
+start of Xxx
+ test
+end of Xxx
diff --git a/src/testdir/test8.ok b/src/testdir/test8.ok
new file mode 100644
index 000000000..29b066a13
--- /dev/null
+++ b/src/testdir/test8.ok
@@ -0,0 +1,6 @@
+start of Xxx2
+ test
+end of Xxx
+start of Xxx1
+ test
+end of Xxx
diff --git a/src/testdir/test9.in b/src/testdir/test9.in
new file mode 100644
index 000000000..84e17943c
--- /dev/null
+++ b/src/testdir/test9.in
@@ -0,0 +1,12 @@
+Test for Bufleave autocommand that deletes the buffer we are about to edit.
+
+STARTTEST
+:so small.vim
+:au BufLeave test9.in bwipe yy
+:e yy
+:/^start of/,$w! test.out " Write contents of this file
+:qa!
+ENDTEST
+
+start of test file xx
+end of test file xx
diff --git a/src/testdir/test9.ok b/src/testdir/test9.ok
new file mode 100644
index 000000000..cccb5f3ef
--- /dev/null
+++ b/src/testdir/test9.ok
@@ -0,0 +1,2 @@
+start of test file xx
+end of test file xx
diff --git a/src/testdir/todos.vim b/src/testdir/todos.vim
new file mode 100644
index 000000000..0256a51c8
--- /dev/null
+++ b/src/testdir/todos.vim
@@ -0,0 +1,3 @@
+:" Script to make sure a file is in "dos" file format.
+:set ff=dos
+:wq
diff --git a/src/testdir/unix.vim b/src/testdir/unix.vim
new file mode 100644
index 000000000..f766e74c3
--- /dev/null
+++ b/src/testdir/unix.vim
@@ -0,0 +1,3 @@
+" Settings for test script execution
+" Always use "sh", don't use the value of "$SHELL".
+set shell=sh
diff --git a/src/testdir/vms.vim b/src/testdir/vms.vim
new file mode 100644
index 000000000..3305a77c2
--- /dev/null
+++ b/src/testdir/vms.vim
@@ -0,0 +1,4 @@
+" Settings for test script execution under OpenVMS
+
+" Do not make any swap files
+set noswapfile