1" Vim script language tests
2" Author:	Servatius Brandt <Servatius.Brandt@fujitsu-siemens.com>
3" Last Change:	2006 Apr 28
4
5"-------------------------------------------------------------------------------
6" Test environment							    {{{1
7"-------------------------------------------------------------------------------
8
9
10" Adding new tests easily.						    {{{2
11"
12" Writing new tests is eased considerably with the following functions and
13" abbreviations (see "Commands for recording the execution path", "Automatic
14" argument generation").
15"
16" To get the abbreviations, execute the command
17"
18"    :let test49_set_env = 1 | source test49.vim
19"
20" To get them always (from src/testdir), put a line
21"
22"    au! BufRead test49.vim let test49_set_env = 1 | source test49.vim
23"
24" into the local .vimrc file in the src/testdir directory.
25"
26if exists("test49_set_env") && test49_set_env
27
28    " Automatic argument generation for the test environment commands.
29
30    function! Xsum()
31	let addend = substitute(getline("."), '^.*"\s*X:\s*\|^.*', '', "")
32	" Evaluate arithmetic expression.
33	if addend != ""
34	    exec "let g:Xsum = g:Xsum + " . addend
35	endif
36    endfunction
37
38    function! Xcheck()
39	let g:Xsum=0
40	?XpathINIT?,.call Xsum()
41	exec "norm A "
42	return g:Xsum
43    endfunction
44
45    iab Xcheck Xcheck<Space><C-R>=Xcheck()<CR><C-O>x
46
47    function! Xcomment(num)
48	let str = ""
49	let tabwidth = &sts ? &sts : &ts
50	let tabs = (48+tabwidth - a:num - virtcol(".")) / tabwidth
51	while tabs > 0
52	    let str = str . "\t"
53	    let tabs = tabs - 1
54	endwhile
55	let str = str . '" X:'
56	return str
57    endfunction
58
59    function! Xloop()
60	let back = line(".") . "|norm" . virtcol(".") . "|"
61	norm 0
62	let last = search('X\(loop\|path\)INIT\|Xloop\>', "bW")
63	exec back
64	let theline = getline(last)
65	if theline =~ 'X\(loop\|path\)INIT'
66	    let num = 1
67	else
68	    let num = 2 * substitute(theline, '.*Xloop\s*\(\d\+\).*', '\1', "")
69	endif
70	?X\(loop\|path\)INIT?
71	    \s/\(XloopINIT!\=\s*\d\+\s\+\)\@<=\(\d\+\)/\=2*submatch(2)/
72	exec back
73	exec "norm a "
74	return num . Xcomment(strlen(num))
75    endfunction
76
77    iab Xloop Xloop<Space><C-R>=Xloop()<CR><C-O>x
78
79    function! Xpath(loopinit)
80	let back = line(".") . "|norm" . virtcol(".") . "|"
81	norm 0
82	let last = search('XpathINIT\|Xpath\>\|XloopINIT', "bW")
83	exec back
84	let theline = getline(last)
85	if theline =~ 'XpathINIT'
86	    let num = 1
87	elseif theline =~ 'Xpath\>'
88	    let num = 2 * substitute(theline, '.*Xpath\s*\(\d\+\).*', '\1', "")
89	else
90	    let pattern = '.*XloopINIT!\=\s*\(\d\+\)\s*\(\d\+\).*'
91	    let num = substitute(theline, pattern, '\1', "")
92	    let factor = substitute(theline, pattern, '\2', "")
93	    " The "<C-O>x" from the "Xpath" iab and the character triggering its
94	    " expansion are in the input buffer.  Save and clear typeahead so
95	    " that it is not read away by the call to "input()" below.  Restore
96	    " afterwards.
97	    call inputsave()
98	    let loops = input("Number of iterations in previous loop? ")
99	    call inputrestore()
100	    while (loops > 0)
101		let num = num * factor
102		let loops = loops - 1
103	    endwhile
104	endif
105	exec "norm a "
106	if a:loopinit
107	    return num . " 1"
108	endif
109	return num . Xcomment(strlen(num))
110    endfunction
111
112    iab Xpath Xpath<Space><C-R>=Xpath(0)<CR><C-O>x
113    iab XloopINIT XloopINIT<Space><C-R>=Xpath(1)<CR><C-O>x
114
115    " Also useful (see ExtraVim below):
116    aug ExtraVim
117	au!
118	au  BufEnter <sfile> syn region ExtraVim
119		    \ start=+^if\s\+ExtraVim(.*)+ end=+^endif+
120		    \ transparent keepend
121	au  BufEnter <sfile> syn match ExtraComment /^"/
122		    \ contained containedin=ExtraVim
123	au  BufEnter <sfile> hi link ExtraComment vimComment
124    aug END
125
126    aug Xpath
127	au  BufEnter <sfile> syn keyword Xpath
128		    \ XpathINIT Xpath XloopINIT Xloop XloopNEXT Xcheck Xout
129	au  BufEnter <sfile> hi link Xpath Special
130    aug END
131
132    do BufEnter <sfile>
133
134    " Do not execute the tests when sourcing this file for getting the functions
135    " and abbreviations above, which are intended for easily adding new test
136    " cases; they are not needed for test execution.  Unlet the variable
137    " controlling this so that an explicit ":source" command for this file will
138    " execute the tests.
139    unlet test49_set_env
140    finish
141
142endif
143
144
145" Commands for recording the execution path.				    {{{2
146"
147" The Xpath/Xloop commands can be used for computing the eXecution path by
148" adding (different) powers of 2 from those script lines, for which the
149" execution should be checked.  Xloop provides different addends for each
150" execution of a loop.  Permitted values are 2^0 to 2^30, so that 31 execution
151" points (multiply counted inside loops) can be tested.
152"
153" Note that the arguments of the following commands can be generated
154" automatically, see below.
155"
156" Usage:								    {{{3
157"
158"   - Use XpathINIT at the beginning of the test.
159"
160"   - Use Xpath to check if a line is executed.
161"     Argument: power of 2 (decimal).
162"
163"   - To check multiple execution of loops use Xloop for automatically
164"     computing Xpath values:
165"
166"	- Use XloopINIT before the loop.
167"	  Two arguments:
168"		- the first Xpath value (power of 2) to be used (Xnext),
169"		- factor for computing a new Xnext value when reexecuting a loop
170"		  (by a ":continue" or ":endwhile"); this should be 2^n where
171"		  n is the number of Xloop commands inside the loop.
172"	  If XloopINIT! is used, the first execution of XloopNEXT is
173"	  a no-operation.
174"
175"       - Use Xloop inside the loop:
176"	  One argument:
177"		The argument and the Xnext value are multiplied to build the
178"		next Xpath value.  No new Xnext value is prepared.  The argument
179"		should be 2^(n-1) for the nth Xloop command inside the loop.
180"		If the loop has only one Xloop command, the argument can be
181"		ommitted (default: 1).
182"
183"	- Use XloopNEXT before ":continue" and ":endwhile".  This computes a new
184"	  Xnext value for the next execution of the loop by multiplying the old
185"	  one with the factor specified in the XloopINIT command.  No Argument.
186"	  Alternatively, when XloopINIT! is used, a single XloopNEXT at the
187"	  beginning of the loop can be used.
188"
189"     Nested loops are not supported.
190"
191"   - Use Xcheck at end of each test.  It prints the test number, the expected
192"     execution path value, the test result ("OK" or "FAIL"), and, if the tests
193"     fails, the actual execution path.
194"     One argument:
195"	    Expected Xpath/Xloop sum for the correct execution path.
196"	    In order that this value can be computed automatically, do the
197"	    following: For each line in the test with an Xpath and Xloop
198"	    command, add a comment starting with "X:" and specifying an
199"	    expression that evaluates to the value contributed by this line to
200"	    the correct execution path.  (For copying an Xpath argument of at
201"	    least two digits into the comment, press <C-P>.)  At the end of the
202"	    test, just type "Xcheck" and press <Esc>.
203"
204"   - In order to add additional information to the test output file, use the
205"     Xout command.  Argument(s) like ":echo".
206"
207" Automatic argument generation:					    {{{3
208"
209"   The arguments of the Xpath, XloopINIT, Xloop, and Xcheck commands can be
210"   generated automatically, so that new tests can easily be written without
211"   mental arithmetic.  The Xcheck argument is computed from the "X:" comments
212"   of the preceding Xpath and Xloop commands.  See the commands and
213"   abbreviations at the beginning of this file.
214"
215" Implementation:							    {{{3
216"     XpathINIT, Xpath, XloopINIT, Xloop, XloopNEXT, Xcheck, Xout.
217"
218" The variants for existing g:ExtraVimResult are needed when executing a script
219" in an extra Vim process, see ExtraVim below.
220
221" EXTRA_VIM_START - do not change or remove this line.
222
223com!		    XpathINIT	let g:Xpath = 0
224
225if exists("g:ExtraVimResult")
226    com! -count -bar    Xpath	exec "!echo <count> >>" . g:ExtraVimResult
227else
228    com! -count -bar    Xpath	let g:Xpath = g:Xpath + <count>
229endif
230
231com! -count -nargs=1 -bang
232		  \ XloopINIT	let g:Xnext = <count> |
233				    \ let g:Xfactor = <args> |
234				    \ let g:Xskip = strlen("<bang>")
235
236if exists("g:ExtraVimResult")
237    com! -count=1 -bar  Xloop	exec "!echo " . (g:Xnext * <count>) . " >>" .
238				    \ g:ExtraVimResult
239else
240    com! -count=1 -bar  Xloop	let g:Xpath = g:Xpath + g:Xnext * <count>
241endif
242
243com!		    XloopNEXT	let g:Xnext = g:Xnext *
244				    \ (g:Xskip ? 1 : g:Xfactor) |
245				    \ let g:Xskip = 0
246
247let @r = ""
248let Xtest = 1
249com! -count	    Xcheck	let Xresult = "*** Test " .
250				    \ (Xtest<10?"  ":Xtest<100?" ":"") .
251				    \ Xtest . ": " . (
252				    \ (Xpath==<count>) ? "OK (".Xpath.")" :
253					\ "FAIL (".Xpath." instead of <count>)"
254				    \ ) |
255				    \ let @R = Xresult . "\n" |
256				    \ echo Xresult |
257				    \ let Xtest = Xtest + 1
258
259if exists("g:ExtraVimResult")
260    com! -nargs=+    Xoutq	exec "!echo @R:'" .
261				    \ substitute(substitute(<q-args>,
262				    \ "'", '&\\&&', "g"), "\n", "@NL@", "g")
263				    \ . "' >>" . g:ExtraVimResult
264else
265    com! -nargs=+    Xoutq	let @R = "--- Test " .
266				    \ (g:Xtest<10?"  ":g:Xtest<100?" ":"") .
267				    \ g:Xtest . ": " . substitute(<q-args>,
268				    \ "\n", "&\t      ", "g") . "\n"
269endif
270com! -nargs=+	    Xout	exec 'Xoutq' <args>
271
272" Switch off storing of lines for undoing changes.  Speeds things up a little.
273set undolevels=-1
274
275" EXTRA_VIM_STOP - do not change or remove this line.
276
277
278" ExtraVim() - Run a script file in an extra Vim process.		    {{{2
279"
280" This is useful for testing immediate abortion of the script processing due to
281" an error in a command dynamically enclosed by a :try/:tryend region or when an
282" exception is thrown but not caught or when an interrupt occurs.  It can also
283" be used for testing :finish.
284"
285" An interrupt location can be specified by an "INTERRUPT" comment.  A number
286" telling how often this location is reached (in a loop or in several function
287" calls) should be specified as argument.  When missing, once per script
288" invocation or function call is assumed.  INTERRUPT locations are tested by
289" setting a breakpoint in that line and using the ">quit" debug command when
290" the breakpoint is reached.  A function for which an INTERRUPT location is
291" specified must be defined before calling it (or executing it as a script by
292" using ExecAsScript below).
293"
294" This function is only called in normal modus ("g:ExtraVimResult" undefined).
295"
296" Tests to be executed as an extra script should be written as follows:
297"
298"	column 1			column 1
299"	|				|
300"	v				v
301"
302"	XpathINIT			XpathINIT
303"	if ExtraVim()			if ExtraVim()
304"	    ...				"   ...
305"	    ...				"   ...
306"	endif				endif
307"	Xcheck <number>			Xcheck <number>
308"
309" Double quotes in column 1 are removed before the script is executed.
310" They should be used if the test has unbalanced conditionals (:if/:endif,
311" :while:/endwhile, :try/:endtry) or for a line with a syntax error.  The
312" extra script may use Xpath, XloopINIT, Xloop, XloopNEXT, and Xout as usual.
313"
314" A file name may be specified as argument.  All messages of the extra Vim
315" process are then redirected to the file.  An existing file is overwritten.
316"
317let ExtraVimCount = 0
318let ExtraVimBase = expand("<sfile>")
319let ExtraVimTestEnv = ""
320"
321function! ExtraVim(...)
322    " Count how often this function is called.
323    let g:ExtraVimCount = g:ExtraVimCount + 1
324
325    " Disable folds to prevent that the ranges in the ":write" commands below
326    " are extended up to the end of a closed fold.  This also speeds things up
327    " considerably.
328    set nofoldenable
329
330    " Open a buffer for this test script and copy the test environment to
331    " a temporary file.  Take account of parts relevant for the extra script
332    " execution only.
333    let current_buffnr = bufnr("%")
334    execute "view +1" g:ExtraVimBase
335    if g:ExtraVimCount == 1
336	let g:ExtraVimTestEnv = tempname()
337	execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w"
338		    \ g:ExtraVimTestEnv "|']+"
339	execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
340		    \ g:ExtraVimTestEnv "|']+"
341	execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
342		    \ g:ExtraVimTestEnv "|']+"
343	execute "/E" . "XTRA_VIM_START/+,/E" . "XTRA_VIM_STOP/-w >>"
344		    \ g:ExtraVimTestEnv "|']+"
345    endif
346
347    " Start the extra Vim script with a ":source" command for the test
348    " environment.  The source line number where the extra script will be
349    " appended, needs to be passed as variable "ExtraVimBegin" to the script.
350    let extra_script = tempname()
351    exec "!echo 'source " . g:ExtraVimTestEnv . "' >" . extra_script
352    let extra_begin = 1
353
354    " Starting behind the test environment, skip over the first g:ExtraVimCount
355    " occurrences of "if ExtraVim()" and copy the following lines up to the
356    " matching "endif" to the extra Vim script.
357    execute "/E" . "ND_OF_TEST_ENVIRONMENT/"
358    exec 'norm ' . g:ExtraVimCount . '/^\s*if\s\+ExtraVim(.*)/+' . "\n"
359    execute ".,/^endif/-write >>" . extra_script
360
361    " Open a buffer for the extra Vim script, delete all ^", and write the
362    " script if was actually modified.
363    execute "edit +" . (extra_begin + 1) extra_script
364    ,$s/^"//e
365    update
366
367    " Count the INTERRUPTs and build the breakpoint and quit commands.
368    let breakpoints = ""
369    let debug_quits = ""
370    let in_func = 0
371    exec extra_begin
372    while search(
373	    \ '"\s*INTERRUPT\h\@!\|^\s*fu\%[nction]\>!\=\s*\%(\u\|s:\)\w*\s*(\|'
374	    \ . '^\s*\\\|^\s*endf\%[unction]\>\|'
375	    \ . '\%(^\s*fu\%[nction]!\=\s*\)\@<!\%(\u\|s:\)\w*\s*(\|'
376	    \ . 'ExecAsScript\s\+\%(\u\|s:\)\w*',
377	    \ "W") > 0
378	let theline = getline(".")
379	if theline =~ '^\s*fu'
380	    " Function definition.
381	    let in_func = 1
382	    let func_start = line(".")
383	    let func_name = substitute(theline,
384		\ '^\s*fu\%[nction]!\=\s*\(\%(\u\|s:\)\w*\).*', '\1', "")
385	elseif theline =~ '^\s*endf'
386	    " End of function definition.
387	    let in_func = 0
388	else
389	    let finding = substitute(theline, '.*\(\%' . col(".") . 'c.*\)',
390		\ '\1', "")
391	    if finding =~ '^"\s*INTERRUPT\h\@!'
392		" Interrupt comment.  Compose as many quit commands as
393		" specified.
394		let cnt = substitute(finding,
395		    \ '^"\s*INTERRUPT\s*\(\d*\).*$', '\1', "")
396		let quits = ""
397		while cnt > 0
398		    " Use "\r" rather than "\n" to separate the quit commands.
399		    " "\r" is not interpreted as command separator by the ":!"
400		    " command below but works to separate commands in the
401		    " external vim.
402		    let quits = quits . "q\r"
403		    let cnt = cnt - 1
404		endwhile
405		if in_func
406		    " Add the function breakpoint and note the number of quits
407		    " to be used, if specified, or one for every call else.
408		    let breakpoints = breakpoints . " -c 'breakadd func " .
409			\ (line(".") - func_start) . " " .
410			\ func_name . "'"
411		    if quits != ""
412			let debug_quits = debug_quits . quits
413		    elseif !exists("quits{func_name}")
414			let quits{func_name} = "q\r"
415		    else
416			let quits{func_name} = quits{func_name} . "q\r"
417		    endif
418		else
419		    " Add the file breakpoint and the quits to be used for it.
420		    let breakpoints = breakpoints . " -c 'breakadd file " .
421			\ line(".") . " " . extra_script . "'"
422		    if quits == ""
423			let quits = "q\r"
424		    endif
425		    let debug_quits = debug_quits . quits
426		endif
427	    else
428		" Add the quits to be used for calling the function or executing
429		" it as script file.
430		if finding =~ '^ExecAsScript'
431		    " Sourcing function as script.
432		    let finding = substitute(finding,
433			\ '^ExecAsScript\s\+\(\%(\u\|s:\)\w*\).*', '\1', "")
434		else
435		    " Function call.
436		    let finding = substitute(finding,
437			\ '^\(\%(\u\|s:\)\w*\).*', '\1', "")
438		endif
439		if exists("quits{finding}")
440		    let debug_quits = debug_quits . quits{finding}
441		endif
442	    endif
443	endif
444    endwhile
445
446    " Close the buffer for the script and create an (empty) resultfile.
447    bwipeout
448    let resultfile = tempname()
449    exec "!>" . resultfile
450
451    " Run the script in an extra vim.  Switch to extra modus by passing the
452    " resultfile in ExtraVimResult.  Redirect messages to the file specified as
453    " argument if any.  Use ":debuggreedy" so that the commands provided on the
454    " pipe are consumed at the debug prompt.  Use "-N" to enable command-line
455    " continuation ("C" in 'cpo').  Add "nviminfo" to 'viminfo' to avoid
456    " messing up the user's viminfo file.
457    let redirect = a:0 ?
458	\ " -c 'au VimLeave * redir END' -c 'redir\\! >" . a:1 . "'" : ""
459    exec "!echo '" . debug_quits . "q' | ../vim -u NONE -N -Xes" . redirect .
460	\ " -c 'debuggreedy|set viminfo+=nviminfo'" .
461	\ " -c 'let ExtraVimBegin = " . extra_begin . "'" .
462	\ " -c 'let ExtraVimResult = \"" . resultfile . "\"'" . breakpoints .
463	\ " -S " . extra_script
464
465    " Build the resulting sum for resultfile and add it to g:Xpath.  Add Xout
466    " information provided by the extra Vim process to the test output.
467    let sum = 0
468    exec "edit" resultfile
469    let line = 1
470    while line <= line("$")
471	let theline = getline(line)
472	if theline =~ '^@R:'
473	    exec 'Xout "' . substitute(substitute(
474		\ escape(escape(theline, '"'), '\"'),
475		\ '^@R:', '', ""), '@NL@', "\n", "g") . '"'
476	else
477	    let sum = sum + getline(line)
478	endif
479	let line = line + 1
480    endwhile
481    bwipeout
482    let g:Xpath = g:Xpath + sum
483
484    " Delete the extra script and the resultfile.
485    call delete(extra_script)
486    call delete(resultfile)
487
488    " Switch back to the buffer that was active when this function was entered.
489    exec "buffer" current_buffnr
490
491    " Return 0.  This protects extra scripts from being run in the main Vim
492    " process.
493    return 0
494endfunction
495
496
497" ExtraVimThrowpoint() - Relative throwpoint in ExtraVim script		    {{{2
498"
499" Evaluates v:throwpoint and returns the throwpoint relative to the beginning of
500" an ExtraVim script as passed by ExtraVim() in ExtraVimBegin.
501"
502" EXTRA_VIM_START - do not change or remove this line.
503function! ExtraVimThrowpoint()
504    if !exists("g:ExtraVimBegin")
505	Xout "ExtraVimThrowpoint() used outside ExtraVim() script."
506	return v:throwpoint
507    endif
508
509    if v:throwpoint =~ '^function\>'
510	return v:throwpoint
511    endif
512
513    return "line " .
514	\ (substitute(v:throwpoint, '.*, line ', '', "") - g:ExtraVimBegin) .
515	\ " of ExtraVim() script"
516endfunction
517" EXTRA_VIM_STOP - do not change or remove this line.
518
519
520" MakeScript() - Make a script file from a function.			    {{{2
521"
522" Create a script that consists of the body of the function a:funcname.
523" Replace any ":return" by a ":finish", any argument variable by a global
524" variable, and and every ":call" by a ":source" for the next following argument
525" in the variable argument list.  This function is useful if similar tests are
526" to be made for a ":return" from a function call or a ":finish" in a script
527" file.
528"
529" In order to execute a function specifying an INTERRUPT location (see ExtraVim)
530" as a script file, use ExecAsScript below.
531"
532" EXTRA_VIM_START - do not change or remove this line.
533function! MakeScript(funcname, ...)
534    let script = tempname()
535    execute "redir! >" . script
536    execute "function" a:funcname
537    redir END
538    execute "edit" script
539    " Delete the "function" and the "endfunction" lines.  Do not include the
540    " word "function" in the pattern since it might be translated if LANG is
541    " set.  When MakeScript() is being debugged, this deletes also the debugging
542    " output of its line 3 and 4.
543    exec '1,/.*' . a:funcname . '(.*)/d'
544    /^\d*\s*endfunction\>/,$d
545    %s/^\d*//e
546    %s/return/finish/e
547    %s/\<a:\(\h\w*\)/g:\1/ge
548    normal gg0
549    let cnt = 0
550    while search('\<call\s*\%(\u\|s:\)\w*\s*(.*)', 'W') > 0
551	let cnt = cnt + 1
552	s/\<call\s*\%(\u\|s:\)\w*\s*(.*)/\='source ' . a:{cnt}/
553    endwhile
554    g/^\s*$/d
555    write
556    bwipeout
557    return script
558endfunction
559" EXTRA_VIM_STOP - do not change or remove this line.
560
561
562" ExecAsScript - Source a temporary script made from a function.	    {{{2
563"
564" Make a temporary script file from the function a:funcname, ":source" it, and
565" delete it afterwards.
566"
567" When inside ":if ExtraVim()", add a file breakpoint for each INTERRUPT
568" location specified in the function.
569"
570" EXTRA_VIM_START - do not change or remove this line.
571function! ExecAsScript(funcname)
572    " Make a script from the function passed as argument.
573    let script = MakeScript(a:funcname)
574
575    " When running in an extra Vim process, add a file breakpoint for each
576    " function breakpoint set when the extra Vim process was invoked by
577    " ExtraVim().
578    if exists("g:ExtraVimResult")
579	let bplist = tempname()
580	execute "redir! >" . bplist
581	breaklist
582	redir END
583	execute "edit" bplist
584	" Get the line number from the function breakpoint.  Works also when
585	" LANG is set.
586	execute 'v/^\s*\d\+\s\+func\s\+' . a:funcname . '\s.*/d'
587	%s/^\s*\d\+\s\+func\s\+\%(\u\|s:\)\w*\s\D*\(\d*\).*/\1/e
588	let cnt = 0
589	while cnt < line("$")
590	    let cnt = cnt + 1
591	    if getline(cnt) != ""
592		execute "breakadd file" getline(cnt) script
593	    endif
594	endwhile
595	bwipeout!
596	call delete(bplist)
597    endif
598
599    " Source and delete the script.
600    exec "source" script
601    call delete(script)
602endfunction
603
604com! -nargs=1 -bar ExecAsScript call ExecAsScript(<f-args>)
605" EXTRA_VIM_STOP - do not change or remove this line.
606
607
608" END_OF_TEST_ENVIRONMENT - do not change or remove this line.
609
610
611"-------------------------------------------------------------------------------
612" Test 1:   :endwhile in function					    {{{1
613"
614"	    Detect if a broken loop is (incorrectly) reactivated by the
615"	    :endwhile.  Use a :return to prevent an endless loop, and make
616"	    this test first to get a meaningful result on an error before other
617"	    tests will hang.
618"-------------------------------------------------------------------------------
619
620XpathINIT
621
622function! F()
623    Xpath 1					" X: 1
624    let first = 1
625    XloopINIT 2 8
626    while 1
627	Xloop 1					" X: 2	    + 0 * 16
628	if first
629	    Xloop 2				" X: 4	    + 0 * 32
630	    let first = 0
631	    XloopNEXT
632	    break
633	else
634	    Xloop 4				" X: 0	    + 0 * 64
635	    return
636	endif
637    endwhile
638endfunction
639
640call F()
641Xpath 128					" X: 128
642
643function! G()
644    Xpath 256					" X: 256    + 0 * 2048
645    let first = 1
646    XloopINIT 512 8
647    while 1
648	Xloop 1					" X: 512    + 0 * 4096
649	if first
650	    Xloop 2				" X: 1024   + 0 * 8192
651	    let first = 0
652	    XloopNEXT
653	    break
654	else
655	    Xloop 4				" X: 0	    + 0 * 16384
656	    return
657	endif
658	if 1	" unmatched :if
659    endwhile
660endfunction
661
662call G()
663Xpath 32768					" X: 32768
664
665Xcheck 34695
666
667" Leave F and G for execution as scripts in the next test.
668
669
670"-------------------------------------------------------------------------------
671" Test 2:   :endwhile in script						    {{{1
672"
673"	    Detect if a broken loop is (incorrectly) reactivated by the
674"	    :endwhile.  Use a :finish to prevent an endless loop, and place
675"	    this test before others that might hang to get a meaningful result
676"	    on an error.
677"
678"	    This test executes the bodies of the functions F and G from the
679"	    previous test as script files (:return replaced by :finish).
680"-------------------------------------------------------------------------------
681
682XpathINIT
683
684ExecAsScript F					" X: 1 + 2 + 4
685Xpath 128					" X: 128
686
687ExecAsScript G					" X: 256 + 512 + 1024
688Xpath 32768					" X: 32768
689
690unlet first
691delfunction F
692delfunction G
693
694Xcheck 34695
695
696
697"-------------------------------------------------------------------------------
698" Test 3:   :if, :elseif, :while, :continue, :break			    {{{1
699"-------------------------------------------------------------------------------
700
701XpathINIT
702if 1
703    Xpath 1					" X: 1
704    let loops = 3
705    XloopINIT 2 512
706    while loops > -1	    " main loop: loops == 3, 2, 1 (which breaks)
707	if loops <= 0
708	    let break_err = 1
709	    let loops = -1
710	else					"    3:  2:      1:
711	    Xloop 1				" X: 2 + 2*512 + 2*512*512
712	endif
713	if (loops == 2)
714	    while loops == 2 " dummy loop
715		Xloop 2				" X:     4*512
716		let loops = loops - 1
717		continue    " stop dummy loop
718		Xloop 4				" X:     0
719	    endwhile
720	    XloopNEXT
721	    continue	    " continue main loop
722	    Xloop 8				" X:     0
723	elseif (loops == 1)
724	    let p = 1
725	    while p	    " dummy loop
726		Xloop 16			" X:		 32*512*512
727		let p = 0
728		break	    " break dummy loop
729		Xloop 32			" X:		 0
730	    endwhile
731	    Xloop 64				" X:		 128*512*512
732	    unlet p
733	    break	    " break main loop
734	    Xloop 128				" X:		 0
735	endif
736	if (loops > 0)
737	    Xloop 256				" X: 512
738	endif
739	while loops == 3    " dummy loop
740	    let loops = loops - 1
741	endwhile	    " end dummy loop
742	XloopNEXT
743    endwhile		    " end main loop
744    Xpath 268435456				" X: 1024*512*512
745else
746    Xpath 536870912				" X: 0
747endif
748Xpath 1073741824				" X: 4096*512*512
749if exists("break_err")
750    " The Xpath command does not accept 2^31 (negative); add explicitly:
751    let Xpath = Xpath + 2147483648		" X: 0
752    unlet break_err
753endif
754
755unlet loops
756
757Xcheck 1384648195
758
759
760"-------------------------------------------------------------------------------
761" Test 4:   :return							    {{{1
762"-------------------------------------------------------------------------------
763
764XpathINIT
765
766function! F()
767    if 1
768	Xpath 1					" X: 1
769	let loops = 3
770	XloopINIT 2 16
771	while loops > 0				"    3:  2:     1:
772	    Xloop 1				" X: 2 + 2*16 + 0*16*16
773	    if (loops == 2)
774		Xloop 2				" X:     4*16
775		return
776		Xloop 4				" X:     0
777	    endif
778	    Xloop 8				" X: 16
779	    let loops = loops - 1
780	    XloopNEXT
781	endwhile
782	Xpath 8192				" X: 0
783    else
784	Xpath 16384				" X: 0
785    endif
786endfunction
787
788call F()
789Xpath 32768					" X: 8*16*16*16
790
791Xcheck 32883
792
793" Leave F for execution as a script in the next test.
794
795
796"-------------------------------------------------------------------------------
797" Test 5:   :finish							    {{{1
798"
799"	    This test executes the body of the function F from the previous test
800"	    as a script file (:return replaced by :finish).
801"-------------------------------------------------------------------------------
802
803XpathINIT
804
805ExecAsScript F					" X: 1 + 2 + 2*16 + 4*16 + 16
806Xpath 32768					" X: 32768
807
808unlet loops
809delfunction F
810
811Xcheck 32883
812
813
814"-------------------------------------------------------------------------------
815" Test 6:   Defining functions in :while loops				    {{{1
816"
817"	     Functions can be defined inside other functions.  An inner function
818"	     gets defined when the outer function is executed.  Functions may
819"	     also be defined inside while loops.  Expressions in braces for
820"	     defining the function name are allowed.
821"-------------------------------------------------------------------------------
822
823XpathINIT
824
825if ExtraVim()
826
827    " The command CALL collects the argument of all its invocations in "calls"
828    " when used from a function (that is, when the global variable "calls" needs
829    " the "g:" prefix).  This is to check that the function code is skipped when
830    " the function is defined.  For inner functions, do so only if the outer
831    " function is not being executed.
832    "
833    let calls = ""
834    com! -nargs=1 CALL
835		\ if !exists("calls") && !exists("outer") |
836		\ let g:calls = g:calls . <args> |
837		\ endif
838
839
840    XloopINIT! 1 16
841
842    let i = 0
843    while i < 3
844
845	XloopNEXT
846	let i = i + 1
847
848	if i == 1
849	    Xloop 1				" X: 1
850	    function! F1(arg)
851		CALL a:arg
852		let outer = 1
853
854		XloopINIT! 4096 4
855		let j = 0
856		while j < 1
857		    XloopNEXT
858		    Xloop 1			" X: 4096
859		    let j = j + 1
860		    function! G1(arg)
861			CALL a:arg
862		    endfunction
863		    Xloop 2			" X: 8192
864		endwhile
865	    endfunction
866	    Xloop 2				" X: 2
867
868	    continue
869	endif
870
871	Xloop 4					" X: 4 * (16 + 256)
872	function! F{i}(i, arg)
873	    CALL a:arg
874	    let outer = 1
875
876	    XloopINIT! 16384 4
877	    if a:i == 3
878		XloopNEXT
879		XloopNEXT
880		XloopNEXT
881	    endif
882	    let k = 0
883	    while k < 3
884		XloopNEXT
885		Xloop 1				" X: 16384*(1+4+16+64+256+1024)
886		let k = k + 1
887		function! G{a:i}{k}(arg)
888		    CALL a:arg
889		endfunction
890		Xloop 2				" X: 32768*(1+4+16+64+256+1024)
891	    endwhile
892	endfunction
893	Xloop 8					" X: 8 * (16 + 256)
894
895    endwhile
896
897    if exists("*G1")
898	Xpath 67108864				" X: 0
899    endif
900    if exists("*F1")
901	call F1("F1")
902	if exists("*G1")
903	    call G1("G1")
904	endif
905    endif
906
907    if exists("G21") || exists("G21") || exists("G21")
908	Xpath 134217728				" X: 0
909    endif
910    if exists("*F2")
911	call F2(2, "F2")
912	if exists("*G21")
913	    call G21("G21")
914	endif
915	if exists("*G22")
916	    call G22("G22")
917	endif
918	if exists("*G23")
919	    call G23("G23")
920	endif
921    endif
922
923    if exists("G31") || exists("G31") || exists("G31")
924	Xpath 268435456				" X: 0
925    endif
926    if exists("*F3")
927	call F3(3, "F3")
928	if exists("*G31")
929	    call G31("G31")
930	endif
931	if exists("*G32")
932	    call G32("G32")
933	endif
934	if exists("*G33")
935	    call G33("G33")
936	endif
937    endif
938
939    Xpath 536870912				" X: 536870912
940
941    if calls != "F1G1F2G21G22G23F3G31G32G33"
942	Xpath 1073741824			" X: 0
943	Xout "calls is" calls
944    endif
945
946    delfunction F1
947    delfunction G1
948    delfunction F2
949    delfunction G21
950    delfunction G22
951    delfunction G23
952    delfunction G31
953    delfunction G32
954    delfunction G33
955
956endif
957
958Xcheck 603978947
959
960
961"-------------------------------------------------------------------------------
962" Test 7:   Continuing on errors outside functions			    {{{1
963"
964"	    On an error outside a function, the script processing continues
965"	    at the line following the outermost :endif or :endwhile.  When not
966"	    inside an :if or :while, the script processing continues at the next
967"	    line.
968"-------------------------------------------------------------------------------
969
970XpathINIT
971
972if 1
973    Xpath 1					" X: 1
974    while 1
975	Xpath 2					" X: 2
976	asdf
977	Xpath 4					" X: 0
978	break
979    endwhile | Xpath 8				" X: 0
980    Xpath 16					" X: 0
981endif | Xpath 32				" X: 0
982Xpath 64					" X: 64
983
984while 1
985    Xpath 128					" X: 128
986    if 1
987	Xpath 256				" X: 256
988	asdf
989	Xpath 512				" X: 0
990    endif | Xpath 1024				" X: 0
991    Xpath 2048					" X: 0
992    break
993endwhile | Xpath 4096				" X: 0
994Xpath 8192					" X: 8192
995
996asdf
997Xpath 16384					" X: 16384
998
999asdf | Xpath 32768				" X: 0
1000Xpath 65536					" X: 65536
1001
1002Xcheck 90563
1003
1004
1005"-------------------------------------------------------------------------------
1006" Test 8:   Aborting and continuing on errors inside functions		    {{{1
1007"
1008"	    On an error inside a function without the "abort" attribute, the
1009"	    script processing continues at the next line (unless the error was
1010"	    in a :return command).  On an error inside a function with the
1011"	    "abort" attribute, the function is aborted and the script processing
1012"	    continues after the function call; the value -1 is returned then.
1013"-------------------------------------------------------------------------------
1014
1015XpathINIT
1016
1017function! F()
1018    if 1
1019	Xpath 1					" X: 1
1020	while 1
1021	    Xpath 2				" X: 2
1022	    asdf
1023	    Xpath 4				" X: 4
1024	    asdf | Xpath 8			" X: 0
1025	    Xpath 16				" X: 16
1026	    break
1027	endwhile
1028	Xpath 32				" X: 32
1029    endif | Xpath 64				" X: 64
1030    Xpath 128					" X: 128
1031
1032    while 1
1033	Xpath 256				" X: 256
1034	if 1
1035	    Xpath 512				" X: 512
1036	    asdf
1037	    Xpath 1024				" X: 1024
1038	    asdf | Xpath 2048			" X: 0
1039	    Xpath 4096				" X: 4096
1040	endif
1041	Xpath 8192				" X: 8192
1042	break
1043    endwhile | Xpath 16384			" X: 16384
1044    Xpath 32768					" X: 32768
1045
1046    return novar		" returns (default return value 0)
1047    Xpath 65536					" X: 0
1048    return 1			" not reached
1049endfunction
1050
1051function! G() abort
1052    if 1
1053	Xpath 131072				" X: 131072
1054	while 1
1055	    Xpath 262144			" X: 262144
1056	    asdf		" returns -1
1057	    Xpath 524288			" X: 0
1058	    break
1059	endwhile
1060	Xpath 1048576				" X: 0
1061    endif | Xpath 2097152			" X: 0
1062    Xpath Xpath 4194304				" X: 0
1063
1064    return -4			" not reached
1065endfunction
1066
1067function! H() abort
1068    while 1
1069	Xpath 8388608				" X: 8388608
1070	if 1
1071	    Xpath 16777216			" X: 16777216
1072	    asdf		" returns -1
1073	    Xpath 33554432			" X: 0
1074	endif
1075	Xpath 67108864				" X: 0
1076	break
1077    endwhile | Xpath 134217728			" X: 0
1078    Xpath 268435456				" X: 0
1079
1080    return -4			" not reached
1081endfunction
1082
1083" Aborted functions (G and H) return -1.
1084let sum = (F() + 1) - 4*G() - 8*H()
1085Xpath 536870912					" X: 536870912
1086if sum != 13
1087    Xpath 1073741824				" X: 0
1088    Xout "sum is" sum
1089endif
1090
1091unlet sum
1092delfunction F
1093delfunction G
1094delfunction H
1095
1096Xcheck 562493431
1097
1098
1099"-------------------------------------------------------------------------------
1100" Test 9:   Continuing after aborted functions				    {{{1
1101"
1102"	    When a function with the "abort" attribute is aborted due to an
1103"	    error, the next function back in the call hierarchy without an
1104"	    "abort" attribute continues; the value -1 is returned then.
1105"-------------------------------------------------------------------------------
1106
1107XpathINIT
1108
1109function! F() abort
1110    Xpath 1					" X: 1
1111    let result = G()	" not aborted
1112    Xpath 2					" X: 2
1113    if result != 2
1114	Xpath 4					" X: 0
1115    endif
1116    return 1
1117endfunction
1118
1119function! G()		" no abort attribute
1120    Xpath 8					" X: 8
1121    if H() != -1	" aborted
1122	Xpath 16				" X: 0
1123    endif
1124    Xpath 32					" X: 32
1125    return 2
1126endfunction
1127
1128function! H() abort
1129    Xpath 64					" X: 64
1130    call I()		" aborted
1131    Xpath 128					" X: 0
1132    return 4
1133endfunction
1134
1135function! I() abort
1136    Xpath 256					" X: 256
1137    asdf		" error
1138    Xpath 512					" X: 0
1139    return 8
1140endfunction
1141
1142if F() != 1
1143    Xpath 1024					" X: 0
1144endif
1145
1146delfunction F
1147delfunction G
1148delfunction H
1149delfunction I
1150
1151Xcheck 363
1152
1153
1154"-------------------------------------------------------------------------------
1155" Test 10:  :if, :elseif, :while argument parsing			    {{{1
1156"
1157"	    A '"' or '|' in an argument expression must not be mixed up with
1158"	    a comment or a next command after a bar.  Parsing errors should
1159"	    be recognized.
1160"-------------------------------------------------------------------------------
1161
1162XpathINIT
1163
1164function! MSG(enr, emsg)
1165    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1166    if a:enr == ""
1167	Xout "TODO: Add message number for:" a:emsg
1168	let v:errmsg = ":" . v:errmsg
1169    endif
1170    let match = 1
1171    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1172	let match = 0
1173	if v:errmsg == ""
1174	    Xout "Message missing."
1175	else
1176	    let v:errmsg = escape(v:errmsg, '"')
1177	    Xout "Unexpected message:" v:errmsg
1178	endif
1179    endif
1180    return match
1181endfunction
1182
1183if 1 || strlen("\"") | Xpath 1			" X: 1
1184    Xpath 2					" X: 2
1185endif
1186Xpath 4						" X: 4
1187
1188if 0
1189elseif 1 || strlen("\"") | Xpath 8		" X: 8
1190    Xpath 16					" X: 16
1191endif
1192Xpath 32					" X: 32
1193
1194while 1 || strlen("\"") | Xpath 64		" X: 64
1195    Xpath 128					" X: 128
1196    break
1197endwhile
1198Xpath 256					" X: 256
1199
1200let v:errmsg = ""
1201if 1 ||| strlen("\"") | Xpath 512		" X: 0
1202    Xpath 1024					" X: 0
1203endif
1204Xpath 2048					" X: 2048
1205if !MSG('E15', "Invalid expression")
1206    Xpath 4096					" X: 0
1207endif
1208
1209let v:errmsg = ""
1210if 0
1211elseif 1 ||| strlen("\"") | Xpath 8192		" X: 0
1212    Xpath 16384					" X: 0
1213endif
1214Xpath 32768					" X: 32768
1215if !MSG('E15', "Invalid expression")
1216    Xpath 65536					" X: 0
1217endif
1218
1219let v:errmsg = ""
1220while 1 ||| strlen("\"") | Xpath 131072		" X: 0
1221    Xpath 262144				" X: 0
1222    break
1223endwhile
1224Xpath 524288					" X: 524288
1225if !MSG('E15', "Invalid expression")
1226    Xpath 1048576				" X: 0
1227endif
1228
1229delfunction MSG
1230
1231Xcheck 559615
1232
1233
1234"-------------------------------------------------------------------------------
1235" Test 11:  :if, :elseif, :while argument evaluation after abort	    {{{1
1236"
1237"	    When code is skipped over due to an error, the boolean argument to
1238"	    an :if, :elseif, or :while must not be evaluated.
1239"-------------------------------------------------------------------------------
1240
1241XpathINIT
1242
1243let calls = 0
1244
1245function! P(num)
1246    let g:calls = g:calls + a:num   " side effect on call
1247    return 0
1248endfunction
1249
1250if 1
1251    Xpath 1					" X: 1
1252    asdf		" error
1253    Xpath 2					" X: 0
1254    if P(1)		" should not be called
1255	Xpath 4					" X: 0
1256    elseif !P(2)	" should not be called
1257	Xpath 8					" X: 0
1258    else
1259	Xpath 16				" X: 0
1260    endif
1261    Xpath 32					" X: 0
1262    while P(4)		" should not be called
1263	Xpath 64				" X: 0
1264    endwhile
1265    Xpath 128					" X: 0
1266endif
1267
1268if calls % 2
1269    Xpath 256					" X: 0
1270endif
1271if (calls/2) % 2
1272    Xpath 512					" X: 0
1273endif
1274if (calls/4) % 2
1275    Xpath 1024					" X: 0
1276endif
1277Xpath 2048					" X: 2048
1278
1279unlet calls
1280delfunction P
1281
1282Xcheck 2049
1283
1284
1285"-------------------------------------------------------------------------------
1286" Test 12:  Expressions in braces in skipped code			    {{{1
1287"
1288"	    In code skipped over due to an error or inactive conditional,
1289"	    an expression in braces as part of a variable or function name
1290"	    should not be evaluated.
1291"-------------------------------------------------------------------------------
1292
1293XpathINIT
1294
1295XloopINIT 1 8
1296
1297function! NULL()
1298    Xloop 1					" X: 0
1299    return 0
1300endfunction
1301
1302function! ZERO()
1303    Xloop 2					" X: 0
1304    return 0
1305endfunction
1306
1307function! F0()
1308    Xloop 4					" X: 0
1309endfunction
1310
1311function! F1(arg)
1312    Xpath 4096					" X: 0
1313endfunction
1314
1315let V0 = 1
1316
1317Xpath 8192					" X: 8192
1318echo 0 ? F{NULL() + V{ZERO()}}() : 1
1319XloopNEXT
1320
1321Xpath 16384					" X: 16384
1322if 0
1323    Xpath 32768					" X: 0
1324    call F{NULL() + V{ZERO()}}()
1325endif
1326XloopNEXT
1327
1328Xpath 65536					" X: 65536
1329if 1
1330    asdf		" error
1331    Xpath 131072				" X: 0
1332    call F1(F{NULL() + V{ZERO()}}())
1333endif
1334XloopNEXT
1335
1336Xpath 262144					" X: 262144
1337if 1
1338    asdf		" error
1339    Xpath 524288				" X: 0
1340    call F{NULL() + V{ZERO()}}()
1341endif
1342
1343Xcheck 352256
1344
1345
1346"-------------------------------------------------------------------------------
1347" Test 13:  Failure in argument evaluation for :while			    {{{1
1348"
1349"	    A failure in the expression evaluation for the condition of a :while
1350"	    causes the whole :while loop until the matching :endwhile being
1351"	    ignored.  Continuation is at the next following line.
1352"-------------------------------------------------------------------------------
1353
1354XpathINIT
1355
1356Xpath 1						" X: 1
1357while asdf
1358    Xpath 2					" X: 0
1359    while 1
1360	Xpath 4					" X: 0
1361	break
1362    endwhile
1363    Xpath 8					" X: 0
1364    break
1365endwhile
1366Xpath 16					" X: 16
1367
1368while asdf | Xpath 32 | endwhile | Xpath 64	" X: 0
1369Xpath 128					" X: 128
1370
1371Xcheck 145
1372
1373
1374"-------------------------------------------------------------------------------
1375" Test 14:  Failure in argument evaluation for :if			    {{{1
1376"
1377"	    A failure in the expression evaluation for the condition of an :if
1378"	    does not cause the corresponding :else or :endif being matched to
1379"	    a previous :if/:elseif.  Neither of both branches of the failed :if
1380"	    are executed.
1381"-------------------------------------------------------------------------------
1382
1383XpathINIT
1384XloopINIT 1 256
1385
1386function! F()
1387    Xloop 1					" X: 1	    + 256 * 1
1388    let x = 0
1389    if x		" false
1390	Xloop 2					" X: 0	    + 256 * 0
1391    elseif !x		" always true
1392	Xloop 4					" X: 4	    + 256 * 4
1393	let x = 1
1394	if g:boolvar	" possibly undefined
1395	    Xloop 8				" X: 8	    + 256 * 0
1396	else
1397	    Xloop 16				" X: 0	    + 256 * 0
1398	endif
1399	Xloop 32				" X: 32	    + 256 * 32
1400    elseif x		" never executed
1401	Xloop 64				" X: 0	    + 256 * 0
1402    endif
1403    Xloop 128					" X: 128    + 256 * 128
1404endfunction
1405
1406let boolvar = 1
1407call F()
1408
1409XloopNEXT
1410unlet boolvar
1411call F()
1412
1413delfunction F
1414
1415Xcheck 42413
1416
1417
1418"-------------------------------------------------------------------------------
1419" Test 15:  Failure in argument evaluation for :if (bar)		    {{{1
1420"
1421"	    Like previous test, except that the failing :if ... | ... | :endif
1422"	    is in a single line.
1423"-------------------------------------------------------------------------------
1424
1425XpathINIT
1426XloopINIT 1 256
1427
1428function! F()
1429    Xloop 1					" X: 1	    + 256 * 1
1430    let x = 0
1431    if x		" false
1432	Xloop 2					" X: 0	    + 256 * 0
1433    elseif !x		" always true
1434	Xloop 4					" X: 4	    + 256 * 4
1435	let x = 1
1436	if g:boolvar | Xloop 8 | else | Xloop 16 | endif    " X: 8
1437	Xloop 32				" X: 32	    + 256 * 32
1438    elseif x		" never executed
1439	Xloop 64				" X: 0	    + 256 * 0
1440    endif
1441    Xloop 128					" X: 128    + 256 * 128
1442endfunction
1443
1444let boolvar = 1
1445call F()
1446
1447XloopNEXT
1448unlet boolvar
1449call F()
1450
1451delfunction F
1452
1453Xcheck 42413
1454
1455
1456"-------------------------------------------------------------------------------
1457" Test 16:  Double :else or :elseif after :else				    {{{1
1458"
1459"	    Multiple :elses or an :elseif after an :else are forbidden.
1460"-------------------------------------------------------------------------------
1461
1462XpathINIT
1463
1464function! F() abort
1465    if 0
1466	Xpath 1					" X: 0
1467    else
1468	Xpath 2					" X: 2
1469    else		" aborts function
1470	Xpath 4					" X: 0
1471    endif
1472endfunction
1473
1474function! G() abort
1475    if 0
1476	Xpath 8					" X: 0
1477    else
1478	Xpath 16				" X: 16
1479    elseif 1		" aborts function
1480	Xpath 32				" X: 0
1481    else
1482	Xpath 64				" X: 0
1483    endif
1484endfunction
1485
1486function! H() abort
1487    if 0
1488	Xpath 128				" X: 0
1489    elseif 0
1490	Xpath 256				" X: 0
1491    else
1492	Xpath 512				" X: 512
1493    else		" aborts function
1494	Xpath 1024				" X: 0
1495    endif
1496endfunction
1497
1498function! I() abort
1499    if 0
1500	Xpath 2048				" X: 0
1501    elseif 0
1502	Xpath 4096				" X: 0
1503    else
1504	Xpath 8192				" X: 8192
1505    elseif 1		" aborts function
1506	Xpath 16384				" X: 0
1507    else
1508	Xpath 32768				" X: 0
1509    endif
1510endfunction
1511
1512call F()
1513call G()
1514call H()
1515call I()
1516
1517delfunction F
1518delfunction G
1519delfunction H
1520delfunction I
1521
1522Xcheck 8722
1523
1524
1525"-------------------------------------------------------------------------------
1526" Test 17:  Nesting of unmatched :if or :endif inside a :while		    {{{1
1527"
1528"	    The :while/:endwhile takes precedence in nesting over an unclosed
1529"	    :if or an unopened :endif.
1530"-------------------------------------------------------------------------------
1531
1532XpathINIT
1533
1534function! MSG(enr, emsg)
1535    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
1536    if a:enr == ""
1537	Xout "TODO: Add message number for:" a:emsg
1538	let v:errmsg = ":" . v:errmsg
1539    endif
1540    let match = 1
1541    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
1542	let match = 0
1543	if v:errmsg == ""
1544	    Xout "Message missing."
1545	else
1546	    let v:errmsg = escape(v:errmsg, '"')
1547	    Xout "Unexpected message:" v:errmsg
1548	endif
1549    endif
1550    return match
1551endfunction
1552
1553let messages = ""
1554
1555" While loops inside a function are continued on error.
1556function! F()
1557    let v:errmsg = ""
1558    XloopINIT 1 16
1559    let loops = 3
1560    while loops > 0
1561	let loops = loops - 1			"    2:  1:     0:
1562	Xloop 1					" X: 1 + 1*16 + 1*16*16
1563	if (loops == 1)
1564	    Xloop 2				" X:     2*16
1565	    XloopNEXT
1566	    continue
1567	elseif (loops == 0)
1568	    Xloop 4				" X:		4*16*16
1569	    break
1570	elseif 1
1571	    Xloop 8				" X: 8
1572	    XloopNEXT
1573	" endif missing!
1574    endwhile	" :endwhile after :if 1
1575    Xpath 4096					" X: 16*16*16
1576    if MSG('E171', "Missing :endif")
1577	let g:messages = g:messages . "A"
1578    endif
1579
1580    let v:errmsg = ""
1581    XloopINIT! 8192 4
1582    let loops = 2
1583    while loops > 0				"    2:     1:
1584	XloopNEXT
1585	let loops = loops - 1
1586	Xloop 1					" X: 8192 + 8192*4
1587	if 0
1588	    Xloop 2				" X: 0
1589	" endif missing
1590    endwhile	" :endwhile after :if 0
1591    Xpath 131072				" X: 8192*4*4
1592    if MSG('E171', "Missing :endif")
1593	let g:messages = g:messages . "B"
1594    endif
1595
1596    let v:errmsg = ""
1597    XloopINIT 262144 4
1598    let loops = 2
1599    while loops > 0				"    2:     1:
1600	let loops = loops - 1
1601	Xloop 1					" X: 262144 + 262144 * 4
1602	" if missing!
1603	endif	" :endif without :if in while
1604	Xloop 2					" X: 524288 + 524288 * 4
1605	XloopNEXT
1606    endwhile
1607    Xpath 4194304				" X: 262144*4*4
1608    if MSG('E580', ":endif without :if")
1609	let g:messages = g:messages . "C"
1610    endif
1611endfunction
1612
1613call F()
1614
1615" Error continuation outside a function is at the outermost :endwhile or :endif.
1616let v:errmsg = ""
1617XloopINIT! 8388608 4
1618let loops = 2
1619while loops > 0					"    2:		1:
1620    XloopNEXT
1621    let loops = loops - 1
1622    Xloop 1					" X: 8388608 + 0 * 4
1623    if 0
1624	Xloop 2					" X: 0
1625    " endif missing! Following :endwhile fails.
1626endwhile | Xpath 134217728			" X: 0
1627Xpath 268435456					" X: 2*8388608*4*4
1628if MSG('E171', "Missing :endif")
1629    let messages = g:messages . "D"
1630endif
1631
1632if messages != "ABCD"
1633    Xpath 536870912				" X: 0
1634    Xout "messages is" messages "instead of ABCD"
1635endif
1636
1637unlet loops messages
1638delfunction F
1639delfunction MSG
1640
1641Xcheck 285127993
1642
1643
1644"-------------------------------------------------------------------------------
1645" Test 18:  Interrupt (Ctrl-C pressed)					    {{{1
1646"
1647"	    On an interrupt, the script processing is terminated immediately.
1648"-------------------------------------------------------------------------------
1649
1650XpathINIT
1651
1652if ExtraVim()
1653    if 1
1654	Xpath 1					" X: 1
1655	while 1
1656	    Xpath 2				" X: 2
1657	    if 1
1658		Xpath 4				" X: 4
1659		"INTERRUPT
1660		Xpath 8				" X: 0
1661		break
1662		finish
1663	    endif | Xpath 16			" X: 0
1664	    Xpath 32				" X: 0
1665	endwhile | Xpath 64			" X: 0
1666	Xpath 128				" X: 0
1667    endif | Xpath 256				" X: 0
1668    Xpath 512					" X: 0
1669endif
1670
1671if ExtraVim()
1672    try
1673	Xpath 1024				" X: 1024
1674	"INTERRUPT
1675	Xpath 2048				" X: 0
1676    endtry | Xpath 4096				" X: 0
1677    Xpath 8192					" X: 0
1678endif
1679
1680if ExtraVim()
1681    function! F()
1682	if 1
1683	    Xpath 16384				" X: 16384
1684	    while 1
1685		Xpath 32768			" X: 32768
1686		if 1
1687		    Xpath 65536			" X: 65536
1688		    "INTERRUPT
1689		    Xpath 131072		" X: 0
1690		    break
1691		    return
1692		endif | Xpath 262144		" X: 0
1693		Xpath Xpath 524288		" X: 0
1694	    endwhile | Xpath 1048576		" X: 0
1695	    Xpath Xpath 2097152			" X: 0
1696	endif | Xpath Xpath 4194304		" X: 0
1697	Xpath Xpath 8388608			" X: 0
1698    endfunction
1699
1700    call F() | Xpath 16777216			" X: 0
1701    Xpath 33554432				" X: 0
1702endif
1703
1704if ExtraVim()
1705    function! G()
1706	try
1707	    Xpath 67108864			" X: 67108864
1708	    "INTERRUPT
1709	    Xpath 134217728			" X: 0
1710	endtry | Xpath 268435456		" X: 0
1711	Xpath 536870912				" X: 0
1712    endfunction
1713
1714    call G() | Xpath 1073741824			" X: 0
1715    " The Xpath command does not accept 2^31 (negative); display explicitly:
1716    exec "!echo 2147483648 >>" . g:ExtraVimResult
1717						" X: 0
1718endif
1719
1720Xcheck 67224583
1721
1722
1723"-------------------------------------------------------------------------------
1724" Test 19:  Aborting on errors inside :try/:endtry			    {{{1
1725"
1726"	    An error in a command dynamically enclosed in a :try/:endtry region
1727"	    aborts script processing immediately.  It does not matter whether
1728"	    the failing command is outside or inside a function and whether a
1729"	    function has an "abort" attribute.
1730"-------------------------------------------------------------------------------
1731
1732XpathINIT
1733
1734if ExtraVim()
1735    function! F() abort
1736	Xpath 1					" X: 1
1737	asdf
1738	Xpath 2					" X: 0
1739    endfunction
1740
1741    try
1742	Xpath 4					" X: 4
1743	call F()
1744	Xpath 8					" X: 0
1745    endtry | Xpath 16				" X: 0
1746    Xpath 32					" X: 0
1747endif
1748
1749if ExtraVim()
1750    function! G()
1751	Xpath 64				" X: 64
1752	asdf
1753	Xpath 128				" X: 0
1754    endfunction
1755
1756    try
1757	Xpath 256				" X: 256
1758	call G()
1759	Xpath 512				" X: 0
1760    endtry | Xpath 1024				" X: 0
1761    Xpath 2048					" X: 0
1762endif
1763
1764if ExtraVim()
1765    try
1766	Xpath 4096				" X: 4096
1767	asdf
1768	Xpath 8192				" X: 0
1769    endtry | Xpath 16384			" X: 0
1770    Xpath 32768					" X: 0
1771endif
1772
1773if ExtraVim()
1774    if 1
1775	try
1776	    Xpath 65536				" X: 65536
1777	    asdf
1778	    Xpath 131072			" X: 0
1779	endtry | Xpath 262144			" X: 0
1780    endif | Xpath 524288			" X: 0
1781    Xpath 1048576				" X: 0
1782endif
1783
1784if ExtraVim()
1785    let p = 1
1786    while p
1787	let p = 0
1788	try
1789	    Xpath 2097152			" X: 2097152
1790	    asdf
1791	    Xpath 4194304			" X: 0
1792	endtry | Xpath 8388608			" X: 0
1793    endwhile | Xpath 16777216			" X: 0
1794    Xpath 33554432				" X: 0
1795endif
1796
1797if ExtraVim()
1798    let p = 1
1799    while p
1800	let p = 0
1801"	try
1802	    Xpath 67108864			" X: 67108864
1803    endwhile | Xpath 134217728			" X: 0
1804    Xpath 268435456				" X: 0
1805endif
1806
1807Xcheck 69275973
1808"-------------------------------------------------------------------------------
1809" Test 20:  Aborting on errors after :try/:endtry			    {{{1
1810"
1811"	    When an error occurs after the last active :try/:endtry region has
1812"	    been left, termination behavior is as if no :try/:endtry has been
1813"	    seen.
1814"-------------------------------------------------------------------------------
1815
1816XpathINIT
1817
1818if ExtraVim()
1819    let p = 1
1820    while p
1821	let p = 0
1822	try
1823	    Xpath 1				" X: 1
1824	endtry
1825	asdf
1826    endwhile | Xpath 2				" X: 0
1827    Xpath 4					" X: 4
1828endif
1829
1830if ExtraVim()
1831    while 1
1832	try
1833	    Xpath 8				" X: 8
1834	    break
1835	    Xpath 16				" X: 0
1836	endtry
1837    endwhile
1838    Xpath 32					" X: 32
1839    asdf
1840    Xpath 64					" X: 64
1841endif
1842
1843if ExtraVim()
1844    while 1
1845	try
1846	    Xpath 128				" X: 128
1847	    break
1848	    Xpath 256				" X: 0
1849	finally
1850	    Xpath 512				" X: 512
1851	endtry
1852    endwhile
1853    Xpath 1024					" X: 1024
1854    asdf
1855    Xpath 2048					" X: 2048
1856endif
1857
1858if ExtraVim()
1859    while 1
1860	try
1861	    Xpath 4096				" X: 4096
1862	finally
1863	    Xpath 8192				" X: 8192
1864	    break
1865	    Xpath 16384				" X: 0
1866	endtry
1867    endwhile
1868    Xpath 32768					" X: 32768
1869    asdf
1870    Xpath 65536					" X: 65536
1871endif
1872
1873if ExtraVim()
1874    let p = 1
1875    while p
1876	let p = 0
1877	try
1878	    Xpath 131072			" X: 131072
1879	    continue
1880	    Xpath 262144			" X: 0
1881	endtry
1882    endwhile
1883    Xpath 524288				" X: 524288
1884    asdf
1885    Xpath 1048576				" X: 1048576
1886endif
1887
1888if ExtraVim()
1889    let p = 1
1890    while p
1891	let p = 0
1892	try
1893	    Xpath 2097152			" X: 2097152
1894	    continue
1895	    Xpath 4194304			" X: 0
1896	finally
1897	    Xpath 8388608			" X: 8388608
1898	endtry
1899    endwhile
1900    Xpath 16777216				" X: 16777216
1901    asdf
1902    Xpath 33554432				" X: 33554432
1903endif
1904
1905if ExtraVim()
1906    let p = 1
1907    while p
1908	let p = 0
1909	try
1910	    Xpath 67108864			" X: 67108864
1911	finally
1912	    Xpath 134217728			" X: 134217728
1913	    continue
1914	    Xpath 268435456			" X: 0
1915	endtry
1916    endwhile
1917    Xpath 536870912				" X: 536870912
1918    asdf
1919    Xpath 1073741824				" X: 1073741824
1920endif
1921
1922Xcheck 1874575085
1923
1924
1925"-------------------------------------------------------------------------------
1926" Test 21:  :finally for :try after :continue/:break/:return/:finish	    {{{1
1927"
1928"	    If a :try conditional stays inactive due to a preceding :continue,
1929"	    :break, :return, or :finish, its :finally clause should not be
1930"	    executed.
1931"-------------------------------------------------------------------------------
1932
1933XpathINIT
1934
1935if ExtraVim()
1936    function F()
1937	let loops = 2
1938	XloopINIT! 1 256
1939	while loops > 0
1940	    XloopNEXT
1941	    let loops = loops - 1
1942	    try
1943		if loops == 1
1944		    Xloop 1			" X: 1
1945		    continue
1946		    Xloop 2			" X: 0
1947		elseif loops == 0
1948		    Xloop 4			" X: 4*256
1949		    break
1950		    Xloop 8			" X: 0
1951		endif
1952
1953		try		" inactive
1954		    Xloop 16			" X: 0
1955		finally
1956		    Xloop 32			" X: 0
1957		endtry
1958	    finally
1959		Xloop 64			" X: 64 + 64*256
1960	    endtry
1961	    Xloop 128				" X: 0
1962	endwhile
1963
1964	try
1965	    Xpath 65536				" X: 65536
1966	    return
1967	    Xpath 131072			" X: 0
1968	    try		    " inactive
1969		Xpath 262144			" X: 0
1970	    finally
1971		Xpath 524288			" X: 0
1972	    endtry
1973	finally
1974	    Xpath 1048576			" X: 1048576
1975	endtry
1976	Xpath 2097152				" X: 0
1977    endfunction
1978
1979    try
1980	Xpath 4194304				" X: 4194304
1981	call F()
1982	Xpath 8388608				" X: 8388608
1983	finish
1984	Xpath 16777216				" X: 0
1985	try		" inactive
1986	    Xpath 33554432			" X: 0
1987	finally
1988	    Xpath 67108864			" X: 0
1989	endtry
1990    finally
1991	Xpath 134217728				" X: 134217728
1992    endtry
1993    Xpath 268435456				" X: 0
1994endif
1995
1996Xcheck 147932225
1997
1998
1999"-------------------------------------------------------------------------------
2000" Test 22:  :finally for a :try after an error/interrupt/:throw		    {{{1
2001"
2002"	    If a :try conditional stays inactive due to a preceding error or
2003"	    interrupt or :throw, its :finally clause should not be executed.
2004"-------------------------------------------------------------------------------
2005
2006XpathINIT
2007
2008if ExtraVim()
2009    function! Error()
2010	try
2011	    asdf    " aborting error, triggering error exception
2012	endtry
2013    endfunction
2014
2015    Xpath 1					" X: 1
2016    call Error()
2017    Xpath 2					" X: 0
2018
2019    if 1	" not active due to error
2020	try	" not active since :if inactive
2021	    Xpath 4				" X: 0
2022	finally
2023	    Xpath 8				" X: 0
2024	endtry
2025    endif
2026
2027    try		" not active due to error
2028	Xpath 16				" X: 0
2029    finally
2030	Xpath 32				" X: 0
2031    endtry
2032endif
2033
2034if ExtraVim()
2035    function! Interrupt()
2036	try
2037	    "INTERRUPT	" triggering interrupt exception
2038	endtry
2039    endfunction
2040
2041    Xpath 64					" X: 64
2042    call Interrupt()
2043    Xpath 128					" X: 0
2044
2045    if 1	" not active due to interrupt
2046	try	" not active since :if inactive
2047	    Xpath 256				" X: 0
2048	finally
2049	    Xpath 512				" X: 0
2050	endtry
2051    endif
2052
2053    try		" not active due to interrupt
2054	Xpath 1024				" X: 0
2055    finally
2056	Xpath 2048				" X: 0
2057    endtry
2058endif
2059
2060if ExtraVim()
2061    function! Throw()
2062	throw "xyz"
2063    endfunction
2064
2065    Xpath 4096					" X: 4096
2066    call Throw()
2067    Xpath 8192					" X: 0
2068
2069    if 1	" not active due to :throw
2070	try	" not active since :if inactive
2071	    Xpath 16384				" X: 0
2072	finally
2073	    Xpath 32768				" X: 0
2074	endtry
2075    endif
2076
2077    try		" not active due to :throw
2078	Xpath 65536				" X: 0
2079    finally
2080	Xpath 131072				" X: 0
2081    endtry
2082endif
2083
2084Xcheck 4161
2085
2086
2087"-------------------------------------------------------------------------------
2088" Test 23:  :catch clauses for a :try after a :throw			    {{{1
2089"
2090"	    If a :try conditional stays inactive due to a preceding :throw,
2091"	    none of its :catch clauses should be executed.
2092"-------------------------------------------------------------------------------
2093
2094XpathINIT
2095
2096if ExtraVim()
2097    try
2098	Xpath 1					" X: 1
2099	throw "xyz"
2100	Xpath 2					" X: 0
2101
2102	if 1	" not active due to :throw
2103	    try	" not active since :if inactive
2104		Xpath 4				" X: 0
2105	    catch /xyz/
2106		Xpath 8				" X: 0
2107	    endtry
2108	endif
2109    catch /xyz/
2110	Xpath 16				" X: 16
2111    endtry
2112
2113    Xpath 32					" X: 32
2114    throw "abc"
2115    Xpath 64					" X: 0
2116
2117    try		" not active due to :throw
2118	Xpath 128				" X: 0
2119    catch /abc/
2120	Xpath 256				" X: 0
2121    endtry
2122endif
2123
2124Xcheck 49
2125
2126
2127"-------------------------------------------------------------------------------
2128" Test 24:  :endtry for a :try after a :throw				    {{{1
2129"
2130"	    If a :try conditional stays inactive due to a preceding :throw,
2131"	    its :endtry should not rethrow the exception to the next surrounding
2132"	    active :try conditional.
2133"-------------------------------------------------------------------------------
2134
2135XpathINIT
2136
2137if ExtraVim()
2138    try			" try 1
2139	try		" try 2
2140	    Xpath 1				" X: 1
2141	    throw "xyz"	" makes try 2 inactive
2142	    Xpath 2				" X: 0
2143
2144	    try		" try 3
2145		Xpath 4				" X: 0
2146	    endtry	" no rethrow to try 1
2147	catch /xyz/	" should catch although try 2 inactive
2148	    Xpath 8				" X: 8
2149	endtry
2150    catch /xyz/		" try 1 active, but exception already caught
2151	Xpath 16				" X: 0
2152    endtry
2153    Xpath 32					" X: 32
2154endif
2155
2156Xcheck 41
2157
2158
2159"-------------------------------------------------------------------------------
2160" Test 25:  Executing :finally clauses on normal control flow		    {{{1
2161"
2162"	    Control flow in a :try conditional should always fall through to its
2163"	    :finally clause.  A :finally clause of a :try conditional inside an
2164"	    inactive conditional should never be executed.
2165"-------------------------------------------------------------------------------
2166
2167XpathINIT
2168
2169function! F()
2170    let loops = 3
2171    XloopINIT 1 256
2172    while loops > 0				"     3:   2:       1:
2173	Xloop 1					" X:  1 +  1*256 + 1*256*256
2174	if loops >= 2
2175	    try
2176		Xloop 2				" X:  2 +  2*256
2177		if loops == 2
2178		    try
2179			Xloop 4			" X:       4*256
2180		    finally
2181			Xloop 8			" X:       8*256
2182		    endtry
2183		endif
2184	    finally
2185		Xloop 16			" X: 16 + 16*256
2186		if loops == 2
2187		    try
2188			Xloop 32		" X:      32*256
2189		    finally
2190			Xloop 64		" X:      64*256
2191		    endtry
2192		endif
2193	    endtry
2194	endif
2195	Xloop 128				" X: 128 + 128*256 + 128*256*256
2196	let loops = loops - 1
2197	XloopNEXT
2198    endwhile
2199    Xpath 16777216				" X: 16777216
2200endfunction
2201
2202if 1
2203    try
2204	Xpath 33554432				" X: 33554432
2205	call F()
2206	Xpath 67108864				" X: 67108864
2207    finally
2208	Xpath 134217728				" X: 134217728
2209    endtry
2210else
2211    try
2212	Xpath 268435456				" X: 0
2213    finally
2214	Xpath 536870912				" X: 0
2215    endtry
2216endif
2217
2218delfunction F
2219
2220Xcheck 260177811
2221
2222
2223"-------------------------------------------------------------------------------
2224" Test 26:  Executing :finally clauses after :continue or :break	    {{{1
2225"
2226"	    For a :continue or :break dynamically enclosed in a :try/:endtry
2227"	    region inside the next surrounding :while/:endwhile, if the
2228"	    :continue/:break is before the :finally, the :finally clause is
2229"	    executed first.  If the :continue/:break is after the :finally, the
2230"	    :finally clause is broken (like an :if/:endif region).
2231"-------------------------------------------------------------------------------
2232
2233XpathINIT
2234
2235try
2236    let loops = 3
2237    XloopINIT! 1 32
2238    while loops > 0
2239	XloopNEXT
2240	try
2241	    try
2242		if loops == 2			"    3:   2:     1:
2243		    Xloop 1			" X:      1*32
2244		    let loops = loops - 1
2245		    continue
2246		elseif loops == 1
2247		    Xloop 2			" X:		 2*32*32
2248		    break
2249		    finish
2250		endif
2251		Xloop 4				" X: 4
2252	    endtry
2253	finally
2254	    Xloop 8				" X: 8  + 8*32 + 8*32*32
2255	endtry
2256	Xloop 16				" X: 16
2257	let loops = loops - 1
2258    endwhile
2259    Xpath 32768					" X: 32768
2260finally
2261    Xpath 65536					" X: 65536
2262    let loops = 3
2263    XloopINIT 131072 16
2264    while loops > 0
2265	try
2266	finally
2267	    try
2268		if loops == 2
2269		    Xloop 1			" X: 131072*16
2270		    let loops = loops - 1
2271		    XloopNEXT
2272		    continue
2273		elseif loops == 1
2274		    Xloop 2			" X: 131072*2*16*16
2275		    break
2276		    finish
2277		endif
2278	    endtry
2279	    Xloop 4				" X: 131072*4
2280	endtry
2281	Xloop 8					" X: 131072*8
2282	let loops = loops - 1
2283	XloopNEXT
2284    endwhile
2285    Xpath 536870912				" X: 536870912
2286endtry
2287Xpath 1073741824				" X: 1073741824
2288
2289unlet loops
2290
2291Xcheck 1681500476
2292
2293
2294"-------------------------------------------------------------------------------
2295" Test 27:  Executing :finally clauses after :return			    {{{1
2296"
2297"	    For a :return command dynamically enclosed in a :try/:endtry region,
2298"	    :finally clauses are executed and the called function is ended.
2299"-------------------------------------------------------------------------------
2300
2301XpathINIT
2302
2303function! F()
2304    try
2305	Xpath 1					" X: 1
2306	try
2307	    Xpath 2				" X: 2
2308	    return
2309	    Xpath 4				" X: 0
2310	finally
2311	    Xpath 8				" X: 8
2312	endtry
2313	Xpath 16				" X: 0
2314    finally
2315	Xpath 32				" X: 32
2316    endtry
2317    Xpath 64					" X: 0
2318endfunction
2319
2320function! G()
2321    try
2322	Xpath 128				" X: 128
2323	return
2324	Xpath 256				" X: 0
2325    finally
2326	Xpath 512				" X: 512
2327	call F()
2328	Xpath 1024				" X: 1024
2329    endtry
2330    Xpath 2048					" X: 0
2331endfunction
2332
2333function! H()
2334    try
2335	Xpath 4096				" X: 4096
2336	call G()
2337	Xpath 8192				" X: 8192
2338    finally
2339	Xpath 16384				" X: 16384
2340	return
2341	Xpath 32768				" X: 0
2342    endtry
2343    Xpath 65536					" X: 0
2344endfunction
2345
2346try
2347    Xpath 131072				" X: 131072
2348    call H()
2349    Xpath 262144				" X: 262144
2350finally
2351    Xpath 524288				" X: 524288
2352endtry
2353Xpath 1048576					" X: 1048576
2354
2355Xcheck 1996459
2356
2357" Leave F, G, and H for execution as scripts in the next test.
2358
2359
2360"-------------------------------------------------------------------------------
2361" Test 28:  Executing :finally clauses after :finish			    {{{1
2362"
2363"	    For a :finish command dynamically enclosed in a :try/:endtry region,
2364"	    :finally clauses are executed and the sourced file is finished.
2365"
2366"	    This test executes the bodies of the functions F, G, and H from the
2367"	    previous test as script files (:return replaced by :finish).
2368"-------------------------------------------------------------------------------
2369
2370XpathINIT
2371
2372let scriptF = MakeScript("F")			" X: 1 + 2 + 8 + 32
2373let scriptG = MakeScript("G", scriptF)		" X: 128 + 512 + 1024
2374let scriptH = MakeScript("H", scriptG)		" X: 4096 + 8192 + 16384
2375
2376try
2377    Xpath 131072				" X: 131072
2378    exec "source" scriptH
2379    Xpath 262144				" X: 262144
2380finally
2381    Xpath 524288				" X: 524288
2382endtry
2383Xpath 1048576					" X: 1048576
2384
2385call delete(scriptF)
2386call delete(scriptG)
2387call delete(scriptH)
2388unlet scriptF scriptG scriptH
2389delfunction F
2390delfunction G
2391delfunction H
2392
2393Xcheck 1996459
2394
2395
2396"-------------------------------------------------------------------------------
2397" Test 29:  Executing :finally clauses on errors			    {{{1
2398"
2399"	    After an error in a command dynamically enclosed in a :try/:endtry
2400"	    region, :finally clauses are executed and the script processing is
2401"	    terminated.
2402"-------------------------------------------------------------------------------
2403
2404XpathINIT
2405
2406if ExtraVim()
2407    function! F()
2408	while 1
2409	    try
2410		Xpath 1				" X: 1
2411		while 1
2412		    try
2413			Xpath 2			" X: 2
2414			asdf	    " error
2415			Xpath 4			" X: 0
2416		    finally
2417			Xpath 8			" X: 8
2418		    endtry | Xpath 16		" X: 0
2419		    Xpath 32			" X: 0
2420		    break
2421		endwhile
2422		Xpath 64			" X: 0
2423	    finally
2424		Xpath 128			" X: 128
2425	    endtry | Xpath 256			" X: 0
2426	    Xpath 512				" X: 0
2427	    break
2428	endwhile
2429	Xpath 1024				" X: 0
2430    endfunction
2431
2432    while 1
2433	try
2434	    Xpath 2048				" X: 2048
2435	    while 1
2436		call F()
2437		Xpath 4096			" X: 0
2438		break
2439	    endwhile  | Xpath 8192		" X: 0
2440	    Xpath 16384				" X: 0
2441	finally
2442	    Xpath 32768				" X: 32768
2443	endtry | Xpath 65536			" X: 0
2444    endwhile | Xpath 131072			" X: 0
2445    Xpath 262144				" X: 0
2446endif
2447
2448if ExtraVim()
2449    function! G() abort
2450	if 1
2451	    try
2452		Xpath 524288			" X: 524288
2453		asdf	    " error
2454		Xpath 1048576			" X: 0
2455	    finally
2456		Xpath 2097152			" X: 2097152
2457	    endtry | Xpath 4194304		" X: 0
2458	endif | Xpath 8388608			" X: 0
2459	Xpath 16777216				" X: 0
2460    endfunction
2461
2462    if 1
2463	try
2464	    Xpath 33554432			" X: 33554432
2465	    call G()
2466	    Xpath 67108864			" X: 0
2467	finally
2468	    Xpath 134217728			" X: 134217728
2469	endtry | Xpath 268435456		" X: 0
2470    endif | Xpath 536870912			" X: 0
2471    Xpath 1073741824				" X: 0
2472endif
2473
2474Xcheck 170428555
2475
2476
2477"-------------------------------------------------------------------------------
2478" Test 30:  Executing :finally clauses on interrupt			    {{{1
2479"
2480"	    After an interrupt in a command dynamically enclosed in
2481"	    a :try/:endtry region, :finally clauses are executed and the
2482"	    script processing is terminated.
2483"-------------------------------------------------------------------------------
2484
2485XpathINIT
2486
2487if ExtraVim()
2488    XloopINIT 1 16
2489
2490    function! F()
2491	try
2492	    Xloop 1				" X: 1 + 1*16
2493	    "INTERRUPT
2494	    Xloop 2				" X: 0
2495	finally
2496	    Xloop 4				" X: 4 + 4*16
2497	endtry
2498	Xloop 8					" X: 0
2499    endfunction
2500
2501    try
2502	Xpath 256				" X: 256
2503	try
2504	    Xpath 512				" X: 512
2505	    "INTERRUPT
2506	    Xpath 1024				" X: 0
2507	finally
2508	    Xpath 2048				" X: 2048
2509	    try
2510		Xpath 4096			" X: 4096
2511		try
2512		    Xpath 8192			" X: 8192
2513		finally
2514		    Xpath 16384			" X: 16384
2515		    try
2516			Xpath 32768		" X: 32768
2517			"INTERRUPT
2518			Xpath 65536		" X: 0
2519		    endtry
2520		    Xpath 131072		" X: 0
2521		endtry
2522		Xpath 262144			" X: 0
2523	    endtry
2524	    Xpath 524288			" X: 0
2525	endtry
2526	Xpath 1048576				" X: 0
2527    finally
2528	Xpath 2097152				" X: 2097152
2529	try
2530	    Xpath 4194304			" X: 4194304
2531	    call F()
2532	    Xpath 8388608			" X: 0
2533	finally
2534	    Xpath 16777216			" X: 16777216
2535	    try
2536		Xpath 33554432			" X: 33554432
2537		XloopNEXT
2538		ExecAsScript F
2539		Xpath 67108864			" X: 0
2540	    finally
2541		Xpath 134217728			" X: 134217728
2542	    endtry
2543	    Xpath 268435456			" X: 0
2544	endtry
2545	Xpath 536870912				" X: 0
2546    endtry
2547    Xpath 1073741824				" X: 0
2548endif
2549
2550Xcheck 190905173
2551
2552
2553"-------------------------------------------------------------------------------
2554" Test 31:  Executing :finally clauses after :throw			    {{{1
2555"
2556"	    After a :throw dynamically enclosed in a :try/:endtry region,
2557"	    :finally clauses are executed and the script processing is
2558"	    terminated.
2559"-------------------------------------------------------------------------------
2560
2561XpathINIT
2562
2563if ExtraVim()
2564    XloopINIT 1 16
2565
2566    function! F()
2567	try
2568	    Xloop 1				" X: 1 + 1*16
2569	    throw "exception"
2570	    Xloop 2				" X: 0
2571	finally
2572	    Xloop 4				" X: 4 + 4*16
2573	endtry
2574	Xloop 8					" X: 0
2575    endfunction
2576
2577    try
2578	Xpath 256				" X: 256
2579	try
2580	    Xpath 512				" X: 512
2581	    throw "exception"
2582	    Xpath 1024				" X: 0
2583	finally
2584	    Xpath 2048				" X: 2048
2585	    try
2586		Xpath 4096			" X: 4096
2587		try
2588		    Xpath 8192			" X: 8192
2589		finally
2590		    Xpath 16384			" X: 16384
2591		    try
2592			Xpath 32768		" X: 32768
2593			throw "exception"
2594			Xpath 65536		" X: 0
2595		    endtry
2596		    Xpath 131072		" X: 0
2597		endtry
2598		Xpath 262144			" X: 0
2599	    endtry
2600	    Xpath 524288			" X: 0
2601	endtry
2602	Xpath 1048576				" X: 0
2603    finally
2604	Xpath 2097152				" X: 2097152
2605	try
2606	    Xpath 4194304			" X: 4194304
2607	    call F()
2608	    Xpath 8388608			" X: 0
2609	finally
2610	    Xpath 16777216			" X: 16777216
2611	    try
2612		Xpath 33554432			" X: 33554432
2613		XloopNEXT
2614		ExecAsScript F
2615		Xpath 67108864			" X: 0
2616	    finally
2617		Xpath 134217728			" X: 134217728
2618	    endtry
2619	    Xpath 268435456			" X: 0
2620	endtry
2621	Xpath 536870912				" X: 0
2622    endtry
2623    Xpath 1073741824				" X: 0
2624endif
2625
2626Xcheck 190905173
2627
2628
2629"-------------------------------------------------------------------------------
2630" Test 32:  Remembering the :return value on :finally			    {{{1
2631"
2632"	    If a :finally clause is executed due to a :return specifying
2633"	    a value, this is the value visible to the caller if not overwritten
2634"	    by a new :return in the :finally clause.  A :return without a value
2635"	    in the :finally clause overwrites with value 0.
2636"-------------------------------------------------------------------------------
2637
2638XpathINIT
2639
2640function! F()
2641    try
2642	Xpath 1					" X: 1
2643	try
2644	    Xpath 2				" X: 2
2645	    return "ABCD"
2646	    Xpath 4				" X: 0
2647	finally
2648	    Xpath 8				" X: 8
2649	endtry
2650	Xpath 16				" X: 0
2651    finally
2652	Xpath 32				" X: 32
2653    endtry
2654    Xpath 64					" X: 0
2655endfunction
2656
2657function! G()
2658    try
2659	Xpath 128				" X: 128
2660	return 8
2661	Xpath 256				" X: 0
2662    finally
2663	Xpath 512				" X: 512
2664	return 16 + strlen(F())
2665	Xpath 1024				" X: 0
2666    endtry
2667    Xpath 2048					" X: 0
2668endfunction
2669
2670function! H()
2671    try
2672	Xpath 4096				" X: 4096
2673	return 32
2674	Xpath 8192				" X: 0
2675    finally
2676	Xpath 16384				" X: 16384
2677	return
2678	Xpath 32768				" X: 0
2679    endtry
2680    Xpath 65536					" X: 0
2681endfunction
2682
2683function! I()
2684    try
2685	Xpath 131072				" X: 131072
2686    finally
2687	Xpath 262144				" X: 262144
2688	return G() + H() + 64
2689	Xpath 524288				" X: 0
2690    endtry
2691    Xpath 1048576				" X: 0
2692endfunction
2693
2694let retcode = I()
2695Xpath 2097152					" X: 2097152
2696
2697if retcode < 0
2698    Xpath 4194304				" X: 0
2699endif
2700if retcode % 4
2701    Xpath 8388608				" X: 0
2702endif
2703if (retcode/4) % 2
2704    Xpath 16777216				" X: 16777216
2705endif
2706if (retcode/8) % 2
2707    Xpath 33554432				" X: 0
2708endif
2709if (retcode/16) % 2
2710    Xpath 67108864				" X: 67108864
2711endif
2712if (retcode/32) % 2
2713    Xpath 134217728				" X: 0
2714endif
2715if (retcode/64) % 2
2716    Xpath 268435456				" X: 268435456
2717endif
2718if retcode/128
2719    Xpath 536870912				" X: 0
2720endif
2721
2722unlet retcode
2723delfunction F
2724delfunction G
2725delfunction H
2726delfunction I
2727
2728Xcheck 354833067
2729
2730
2731"-------------------------------------------------------------------------------
2732" Test 33:  :return under :execute or user command and :finally		    {{{1
2733"
2734"	    A :return command may be executed under an ":execute" or from
2735"	    a user command.  Executing of :finally clauses and passing through
2736"	    the return code works also then.
2737"-------------------------------------------------------------------------------
2738XpathINIT
2739
2740command! -nargs=? RETURN
2741    \ try | return <args> | finally | return <args> * 2 | endtry
2742
2743function! F()
2744    try
2745	RETURN 8
2746	Xpath 1					" X: 0
2747    finally
2748	Xpath 2					" X: 2
2749    endtry
2750    Xpath 4					" X: 0
2751endfunction
2752
2753function! G()
2754    try
2755	RETURN 32
2756	Xpath 8					" X: 0
2757    finally
2758	Xpath 16				" X: 16
2759	RETURN 128
2760	Xpath 32				" X: 0
2761    endtry
2762    Xpath 64					" X: 0
2763endfunction
2764
2765function! H()
2766    try
2767	execute "try | return 512 | finally | return 1024 | endtry"
2768	Xpath 128				" X: 0
2769    finally
2770	Xpath 256				" X: 256
2771    endtry
2772    Xpath 512					" X: 0
2773endfunction
2774
2775function! I()
2776    try
2777	execute "try | return 2048 | finally | return 4096 | endtry"
2778	Xpath 1024				" X: 0
2779    finally
2780	Xpath 2048				" X: 2048
2781	execute "try | return 8192 | finally | return 16384 | endtry"
2782	Xpath 4096				" X: 0
2783    endtry
2784    Xpath 8192					" X: 0
2785endfunction
2786
2787function! J()
2788    try
2789	RETURN 32768
2790	Xpath 16384				" X: 0
2791    finally
2792	Xpath 32768				" X: 32768
2793	return
2794	Xpath 65536				" X: 0
2795    endtry
2796    Xpath 131072				" X: 0
2797endfunction
2798
2799function! K()
2800    try
2801	execute "try | return 131072 | finally | return 262144 | endtry"
2802	Xpath 262144				" X: 0
2803    finally
2804	Xpath 524288				" X: 524288
2805	execute "try | return 524288 | finally | return | endtry"
2806	Xpath 1048576				" X: 0
2807    endtry
2808    Xpath 2097152				" X: 0
2809endfunction
2810
2811function! L()
2812    try
2813	return
2814	Xpath 4194304				" X: 0
2815    finally
2816	Xpath 8388608				" X: 8388608
2817	RETURN 1048576
2818	Xpath 16777216				" X: 0
2819    endtry
2820    Xpath 33554432				" X: 0
2821endfunction
2822
2823function! M()
2824    try
2825	return
2826	Xpath 67108864				" X: 0
2827    finally
2828	Xpath 134217728				" X: 134217728
2829	execute "try | return 4194304 | finally | return 8388608 | endtry"
2830	Xpath 268435456				" X: 0
2831    endtry
2832    Xpath 536870912				" X: 0
2833endfunction
2834
2835function! N()
2836    RETURN 16777216
2837endfunction
2838
2839function! O()
2840    execute "try | return 67108864 | finally | return 134217728 | endtry"
2841endfunction
2842
2843let sum	     = F() + G() + H()  + I()   + J() + K() + L()     + M()
2844let expected = 16  + 256 + 1024 + 16384 + 0   + 0   + 2097152 + 8388608
2845let sum	     = sum      + N()      + O()
2846let expected = expected + 33554432 + 134217728
2847
2848if sum == expected
2849    Xout "sum = " . sum . " (ok)"
2850else
2851    Xout "sum = " . sum . ", expected: " . expected
2852endif
2853
2854Xpath 1073741824				" X: 1073741824
2855
2856if sum != expected
2857    " The Xpath command does not accept 2^31 (negative); add explicitly:
2858    let Xpath = Xpath + 2147483648		" X: 0
2859endif
2860
2861unlet sum expected
2862delfunction F
2863delfunction G
2864delfunction H
2865delfunction I
2866delfunction J
2867delfunction K
2868delfunction L
2869delfunction M
2870delfunction N
2871delfunction O
2872
2873Xcheck 1216907538
2874
2875
2876"-------------------------------------------------------------------------------
2877" Test 34:  :finally reason discarded by :continue			    {{{1
2878"
2879"	    When a :finally clause is executed due to a :continue, :break,
2880"	    :return, :finish, error, interrupt or :throw, the jump reason is
2881"	    discarded by a :continue in the finally clause.
2882"-------------------------------------------------------------------------------
2883
2884XpathINIT
2885
2886if ExtraVim()
2887
2888    XloopINIT! 1 8
2889
2890    function! C(jump)
2891	XloopNEXT
2892	let loop = 0
2893	while loop < 2
2894	    let loop = loop + 1
2895	    if loop == 1
2896		try
2897		    if a:jump == "continue"
2898			continue
2899		    elseif a:jump == "break"
2900			break
2901		    elseif a:jump == "return" || a:jump == "finish"
2902			return
2903		    elseif a:jump == "error"
2904			asdf
2905		    elseif a:jump == "interrupt"
2906			"INTERRUPT
2907			let dummy = 0
2908		    elseif a:jump == "throw"
2909			throw "abc"
2910		    endif
2911		finally
2912		    continue	" discards jump that caused the :finally
2913		    Xloop 1		" X: 0
2914		endtry
2915		Xloop 2			" X: 0
2916	    elseif loop == 2
2917		Xloop 4			" X: 4*(1+8+64+512+4096+32768+262144)
2918	    endif
2919	endwhile
2920    endfunction
2921
2922    call C("continue")
2923    Xpath 2097152				" X: 2097152
2924    call C("break")
2925    Xpath 4194304				" X: 4194304
2926    call C("return")
2927    Xpath 8388608				" X: 8388608
2928    let g:jump = "finish"
2929    ExecAsScript C
2930    unlet g:jump
2931    Xpath 16777216				" X: 16777216
2932    try
2933	call C("error")
2934	Xpath 33554432				" X: 33554432
2935    finally
2936	Xpath 67108864				" X: 67108864
2937	try
2938	    call C("interrupt")
2939	    Xpath 134217728			" X: 134217728
2940	finally
2941	    Xpath 268435456			" X: 268435456
2942	    call C("throw")
2943	    Xpath 536870912			" X: 536870912
2944	endtry
2945    endtry
2946    Xpath 1073741824				" X: 1073741824
2947
2948    delfunction C
2949
2950endif
2951
2952Xcheck 2146584868
2953
2954
2955"-------------------------------------------------------------------------------
2956" Test 35:  :finally reason discarded by :break				    {{{1
2957"
2958"	    When a :finally clause is executed due to a :continue, :break,
2959"	    :return, :finish, error, interrupt or :throw, the jump reason is
2960"	    discarded by a :break in the finally clause.
2961"-------------------------------------------------------------------------------
2962
2963XpathINIT
2964
2965if ExtraVim()
2966
2967    XloopINIT! 1 8
2968
2969    function! B(jump)
2970	XloopNEXT
2971	let loop = 0
2972	while loop < 2
2973	    let loop = loop + 1
2974	    if loop == 1
2975		try
2976		    if a:jump == "continue"
2977			continue
2978		    elseif a:jump == "break"
2979			break
2980		    elseif a:jump == "return" || a:jump == "finish"
2981			return
2982		    elseif a:jump == "error"
2983			asdf
2984		    elseif a:jump == "interrupt"
2985			"INTERRUPT
2986			let dummy = 0
2987		    elseif a:jump == "throw"
2988			throw "abc"
2989		    endif
2990		finally
2991		    break	" discards jump that caused the :finally
2992		    Xloop 1		" X: 0
2993		endtry
2994	    elseif loop == 2
2995		Xloop 2			" X: 0
2996	    endif
2997	endwhile
2998	Xloop 4				" X: 4*(1+8+64+512+4096+32768+262144)
2999    endfunction
3000
3001    call B("continue")
3002    Xpath 2097152				" X: 2097152
3003    call B("break")
3004    Xpath 4194304				" X: 4194304
3005    call B("return")
3006    Xpath 8388608				" X: 8388608
3007    let g:jump = "finish"
3008    ExecAsScript B
3009    unlet g:jump
3010    Xpath 16777216				" X: 16777216
3011    try
3012	call B("error")
3013	Xpath 33554432				" X: 33554432
3014    finally
3015	Xpath 67108864				" X: 67108864
3016	try
3017	    call B("interrupt")
3018	    Xpath 134217728			" X: 134217728
3019	finally
3020	    Xpath 268435456			" X: 268435456
3021	    call B("throw")
3022	    Xpath 536870912			" X: 536870912
3023	endtry
3024    endtry
3025    Xpath 1073741824				" X: 1073741824
3026
3027    delfunction B
3028
3029endif
3030
3031Xcheck 2146584868
3032
3033
3034"-------------------------------------------------------------------------------
3035" Test 36:  :finally reason discarded by :return			    {{{1
3036"
3037"	    When a :finally clause is executed due to a :continue, :break,
3038"	    :return, :finish, error, interrupt or :throw, the jump reason is
3039"	    discarded by a :return in the finally clause.
3040"-------------------------------------------------------------------------------
3041
3042XpathINIT
3043
3044if ExtraVim()
3045
3046    XloopINIT! 1 8
3047
3048    function! R(jump, retval) abort
3049	XloopNEXT
3050	let loop = 0
3051	while loop < 2
3052	    let loop = loop + 1
3053	    if loop == 1
3054		try
3055		    if a:jump == "continue"
3056			continue
3057		    elseif a:jump == "break"
3058			break
3059		    elseif a:jump == "return"
3060			return
3061		    elseif a:jump == "error"
3062			asdf
3063		    elseif a:jump == "interrupt"
3064			"INTERRUPT
3065			let dummy = 0
3066		    elseif a:jump == "throw"
3067			throw "abc"
3068		    endif
3069		finally
3070		    return a:retval	" discards jump that caused the :finally
3071		    Xloop 1			" X: 0
3072		endtry
3073	    elseif loop == 2
3074		Xloop 2				" X: 0
3075	    endif
3076	endwhile
3077	Xloop 4					" X: 0
3078    endfunction
3079
3080    let sum =  -R("continue", -8)
3081    Xpath 2097152				" X: 2097152
3082    let sum = sum - R("break", -16)
3083    Xpath 4194304				" X: 4194304
3084    let sum = sum - R("return", -32)
3085    Xpath 8388608				" X: 8388608
3086    try
3087	let sum = sum - R("error", -64)
3088	Xpath 16777216				" X: 16777216
3089    finally
3090	Xpath 33554432				" X: 33554432
3091	try
3092	    let sum = sum - R("interrupt", -128)
3093	    Xpath 67108864			" X: 67108864
3094	finally
3095	    Xpath 134217728			" X: 134217728
3096	    let sum = sum - R("throw", -256)
3097	    Xpath 268435456			" X: 268435456
3098	endtry
3099    endtry
3100    Xpath 536870912				" X: 536870912
3101
3102    let expected = 8 + 16 + 32 + 64 + 128 + 256
3103    if sum != expected
3104	Xpath 1073741824			" X: 0
3105	Xout "sum =" . sum . ", expected: " . expected
3106    endif
3107
3108    unlet sum expected
3109    delfunction R
3110
3111endif
3112
3113Xcheck 1071644672
3114
3115
3116"-------------------------------------------------------------------------------
3117" Test 37:  :finally reason discarded by :finish			    {{{1
3118"
3119"	    When a :finally clause is executed due to a :continue, :break,
3120"	    :return, :finish, error, interrupt or :throw, the jump reason is
3121"	    discarded by a :finish in the finally clause.
3122"-------------------------------------------------------------------------------
3123
3124XpathINIT
3125
3126if ExtraVim()
3127
3128    XloopINIT! 1 8
3129
3130    function! F(jump)	" not executed as function, transformed to a script
3131	XloopNEXT
3132	let loop = 0
3133	while loop < 2
3134	    let loop = loop + 1
3135	    if loop == 1
3136		try
3137		    if a:jump == "continue"
3138			continue
3139		    elseif a:jump == "break"
3140			break
3141		    elseif a:jump == "finish"
3142			finish
3143		    elseif a:jump == "error"
3144			asdf
3145		    elseif a:jump == "interrupt"
3146			"INTERRUPT
3147			let dummy = 0
3148		    elseif a:jump == "throw"
3149			throw "abc"
3150		    endif
3151		finally
3152		    finish	" discards jump that caused the :finally
3153		    Xloop 1			" X: 0
3154		endtry
3155	    elseif loop == 2
3156		Xloop 2				" X: 0
3157	    endif
3158	endwhile
3159	Xloop 4					" X: 0
3160    endfunction
3161
3162    let scriptF = MakeScript("F")
3163    delfunction F
3164
3165    let g:jump = "continue"
3166    exec "source" scriptF
3167    Xpath 2097152				" X: 2097152
3168    let g:jump = "break"
3169    exec "source" scriptF
3170    Xpath 4194304				" X: 4194304
3171    let g:jump = "finish"
3172    exec "source" scriptF
3173    Xpath 8388608				" X: 8388608
3174    try
3175	let g:jump = "error"
3176	exec "source" scriptF
3177	Xpath 16777216				" X: 16777216
3178    finally
3179	Xpath 33554432				" X: 33554432
3180	try
3181	    let g:jump = "interrupt"
3182	    exec "source" scriptF
3183	    Xpath 67108864			" X: 67108864
3184	finally
3185	    Xpath 134217728			" X: 134217728
3186	    try
3187		let g:jump = "throw"
3188		exec "source" scriptF
3189		Xpath 268435456			" X: 268435456
3190	    finally
3191		Xpath 536870912			" X: 536870912
3192	    endtry
3193	endtry
3194    endtry
3195    unlet g:jump
3196
3197    call delete(scriptF)
3198    unlet scriptF
3199
3200endif
3201
3202Xcheck 1071644672
3203
3204
3205"-------------------------------------------------------------------------------
3206" Test 38:  :finally reason discarded by an error			    {{{1
3207"
3208"	    When a :finally clause is executed due to a :continue, :break,
3209"	    :return, :finish, error, interrupt or :throw, the jump reason is
3210"	    discarded by an error in the finally clause.
3211"-------------------------------------------------------------------------------
3212
3213XpathINIT
3214
3215if ExtraVim()
3216
3217    XloopINIT! 1 4
3218
3219    function! E(jump)
3220	XloopNEXT
3221	let loop = 0
3222	while loop < 2
3223	    let loop = loop + 1
3224	    if loop == 1
3225		try
3226		    if a:jump == "continue"
3227			continue
3228		    elseif a:jump == "break"
3229			break
3230		    elseif a:jump == "return" || a:jump == "finish"
3231			return
3232		    elseif a:jump == "error"
3233			asdf
3234		    elseif a:jump == "interrupt"
3235			"INTERRUPT
3236			let dummy = 0
3237		    elseif a:jump == "throw"
3238			throw "abc"
3239		    endif
3240		finally
3241		    asdf	" error; discards jump that caused the :finally
3242		endtry
3243	    elseif loop == 2
3244		Xloop 1				" X: 0
3245	    endif
3246	endwhile
3247	Xloop 2					" X: 0
3248    endfunction
3249
3250    try
3251	Xpath 16384				" X: 16384
3252	call E("continue")
3253	Xpath 32768				" X: 0
3254    finally
3255	try
3256	    Xpath 65536				" X: 65536
3257	    call E("break")
3258	    Xpath 131072			" X: 0
3259	finally
3260	    try
3261		Xpath 262144			" X: 262144
3262		call E("return")
3263		Xpath 524288			" X: 0
3264	    finally
3265		try
3266		    Xpath 1048576		" X: 1048576
3267		    let g:jump = "finish"
3268		    ExecAsScript E
3269		    Xpath 2097152		" X: 0
3270		finally
3271		    unlet g:jump
3272		    try
3273			Xpath 4194304		" X: 4194304
3274			call E("error")
3275			Xpath 8388608		" X: 0
3276		    finally
3277			try
3278			    Xpath 16777216	" X: 16777216
3279			    call E("interrupt")
3280			    Xpath 33554432	" X: 0
3281			finally
3282			    try
3283				Xpath 67108864	" X: 67108864
3284				call E("throw")
3285				Xpath 134217728	" X: 0
3286			    finally
3287				Xpath 268435456	" X: 268435456
3288				delfunction E
3289			    endtry
3290			endtry
3291		    endtry
3292		endtry
3293	    endtry
3294	endtry
3295    endtry
3296    Xpath 536870912				" X: 0
3297
3298endif
3299
3300Xcheck 357908480
3301
3302
3303"-------------------------------------------------------------------------------
3304" Test 39:  :finally reason discarded by an interrupt			    {{{1
3305"
3306"	    When a :finally clause is executed due to a :continue, :break,
3307"	    :return, :finish, error, interrupt or :throw, the jump reason is
3308"	    discarded by an interrupt in the finally clause.
3309"-------------------------------------------------------------------------------
3310
3311XpathINIT
3312
3313if ExtraVim()
3314
3315    XloopINIT! 1 4
3316
3317    function! I(jump)
3318	XloopNEXT
3319	let loop = 0
3320	while loop < 2
3321	    let loop = loop + 1
3322	    if loop == 1
3323		try
3324		    if a:jump == "continue"
3325			continue
3326		    elseif a:jump == "break"
3327			break
3328		    elseif a:jump == "return" || a:jump == "finish"
3329			return
3330		    elseif a:jump == "error"
3331			asdf
3332		    elseif a:jump == "interrupt"
3333			"INTERRUPT
3334			let dummy = 0
3335		    elseif a:jump == "throw"
3336			throw "abc"
3337		    endif
3338		finally
3339		    "INTERRUPT - discards jump that caused the :finally
3340		    let dummy = 0
3341		endtry
3342	    elseif loop == 2
3343		Xloop 1				" X: 0
3344	    endif
3345	endwhile
3346	Xloop 2					" X: 0
3347    endfunction
3348
3349    try
3350	Xpath 16384				" X: 16384
3351	call I("continue")
3352	Xpath 32768				" X: 0
3353    finally
3354	try
3355	    Xpath 65536				" X: 65536
3356	    call I("break")
3357	    Xpath 131072			" X: 0
3358	finally
3359	    try
3360		Xpath 262144			" X: 262144
3361		call I("return")
3362		Xpath 524288			" X: 0
3363	    finally
3364		try
3365		    Xpath 1048576		" X: 1048576
3366		    let g:jump = "finish"
3367		    ExecAsScript I
3368		    Xpath 2097152		" X: 0
3369		finally
3370		    unlet g:jump
3371		    try
3372			Xpath 4194304		" X: 4194304
3373			call I("error")
3374			Xpath 8388608		" X: 0
3375		    finally
3376			try
3377			    Xpath 16777216	" X: 16777216
3378			    call I("interrupt")
3379			    Xpath 33554432	" X: 0
3380			finally
3381			    try
3382				Xpath 67108864	" X: 67108864
3383				call I("throw")
3384				Xpath 134217728	" X: 0
3385			    finally
3386				Xpath 268435456	" X: 268435456
3387				delfunction I
3388			    endtry
3389			endtry
3390		    endtry
3391		endtry
3392	    endtry
3393	endtry
3394    endtry
3395    Xpath 536870912				" X: 0
3396
3397endif
3398
3399Xcheck 357908480
3400
3401
3402"-------------------------------------------------------------------------------
3403" Test 40:  :finally reason discarded by :throw				    {{{1
3404"
3405"	    When a :finally clause is executed due to a :continue, :break,
3406"	    :return, :finish, error, interrupt or :throw, the jump reason is
3407"	    discarded by a :throw in the finally clause.
3408"-------------------------------------------------------------------------------
3409
3410XpathINIT
3411
3412if ExtraVim()
3413
3414    XloopINIT! 1 4
3415
3416    function! T(jump)
3417	XloopNEXT
3418	let loop = 0
3419	while loop < 2
3420	    let loop = loop + 1
3421	    if loop == 1
3422		try
3423		    if a:jump == "continue"
3424			continue
3425		    elseif a:jump == "break"
3426			break
3427		    elseif a:jump == "return" || a:jump == "finish"
3428			return
3429		    elseif a:jump == "error"
3430			asdf
3431		    elseif a:jump == "interrupt"
3432			"INTERRUPT
3433			let dummy = 0
3434		    elseif a:jump == "throw"
3435			throw "abc"
3436		    endif
3437		finally
3438		    throw "xyz"	" discards jump that caused the :finally
3439		endtry
3440	    elseif loop == 2
3441		Xloop 1				" X: 0
3442	    endif
3443	endwhile
3444	Xloop 2					" X: 0
3445    endfunction
3446
3447    try
3448	Xpath 16384				" X: 16384
3449	call T("continue")
3450	Xpath 32768				" X: 0
3451    finally
3452	try
3453	    Xpath 65536				" X: 65536
3454	    call T("break")
3455	    Xpath 131072			" X: 0
3456	finally
3457	    try
3458		Xpath 262144			" X: 262144
3459		call T("return")
3460		Xpath 524288			" X: 0
3461	    finally
3462		try
3463		    Xpath 1048576		" X: 1048576
3464		    let g:jump = "finish"
3465		    ExecAsScript T
3466		    Xpath 2097152		" X: 0
3467		finally
3468		    unlet g:jump
3469		    try
3470			Xpath 4194304		" X: 4194304
3471			call T("error")
3472			Xpath 8388608		" X: 0
3473		    finally
3474			try
3475			    Xpath 16777216	" X: 16777216
3476			    call T("interrupt")
3477			    Xpath 33554432	" X: 0
3478			finally
3479			    try
3480				Xpath 67108864	" X: 67108864
3481				call T("throw")
3482				Xpath 134217728	" X: 0
3483			    finally
3484				Xpath 268435456	" X: 268435456
3485				delfunction T
3486			    endtry
3487			endtry
3488		    endtry
3489		endtry
3490	    endtry
3491	endtry
3492    endtry
3493    Xpath 536870912				" X: 0
3494
3495endif
3496
3497Xcheck 357908480
3498
3499
3500"-------------------------------------------------------------------------------
3501" Test 41:  Skipped :throw finding next command				    {{{1
3502"
3503"	    A :throw in an inactive conditional must not hide a following
3504"	    command.
3505"-------------------------------------------------------------------------------
3506
3507XpathINIT
3508
3509function! F()
3510    Xpath 1					" X: 1
3511    if 0 | throw "never" | endif | Xpath 2	" X: 2
3512    Xpath 4					" X: 4
3513endfunction
3514
3515function! G()
3516    Xpath 8					    " X: 8
3517    while 0 | throw "never" | endwhile | Xpath 16   " X: 16
3518    Xpath 32					    " X: 32
3519endfunction
3520
3521function H()
3522    Xpath 64						    " X: 64
3523    if 0 | try | throw "never" | endtry | endif | Xpath 128 " X: 128
3524    Xpath 256						    " X: 256
3525endfunction
3526
3527Xpath 512					" X: 512
3528
3529try
3530    Xpath 1024					" X: 1024
3531    call F()
3532    Xpath 2048					" X: 2048
3533catch /.*/
3534    Xpath 4096					" X: 0
3535    Xout v:exception "in" v:throwpoint
3536endtry
3537
3538Xpath 8192					" X: 8192
3539
3540try
3541    Xpath 16384					" X: 16384
3542    call G()
3543    Xpath 32768					" X: 32768
3544catch /.*/
3545    Xpath 65536					" X: 0
3546    Xout v:exception "in" v:throwpoint
3547endtry
3548
3549Xpath 131072					" X: 131072
3550
3551try
3552    Xpath 262144				" X: 262144
3553    call H()
3554    Xpath 524288				" X: 524288
3555catch /.*/
3556    Xpath 1048576				" X: 0
3557    Xout v:exception "in" v:throwpoint
3558endtry
3559
3560Xpath 2097152					" X: 2097152
3561
3562delfunction F
3563delfunction G
3564delfunction H
3565
3566Xcheck 3076095
3567
3568
3569"-------------------------------------------------------------------------------
3570" Test 42:  Catching number and string exceptions			    {{{1
3571"
3572"	    When a number is thrown, it is converted to a string exception.
3573"	    Numbers and strings may be caught by specifying a regular exception
3574"	    as argument to the :catch command.
3575"-------------------------------------------------------------------------------
3576
3577XpathINIT
3578
3579try
3580
3581    try
3582	Xpath 1					" X: 1
3583	throw 4711
3584	Xpath 2					" X: 0
3585    catch /4711/
3586	Xpath 4					" X: 4
3587    endtry
3588
3589    try
3590	Xpath 8					" X: 8
3591	throw 4711
3592	Xpath 16				" X: 0
3593    catch /^4711$/
3594	Xpath 32				" X: 32
3595    endtry
3596
3597    try
3598	Xpath 64				" X: 64
3599	throw 4711
3600	Xpath 128				" X: 0
3601    catch /\d/
3602	Xpath 256				" X: 256
3603    endtry
3604
3605    try
3606	Xpath 512				" X: 512
3607	throw 4711
3608	Xpath 1024				" X: 0
3609    catch /^\d\+$/
3610	Xpath 2048				" X: 2048
3611    endtry
3612
3613    try
3614	Xpath 4096				" X: 4096
3615	throw "arrgh"
3616	Xpath 8192				" X: 0
3617    catch /arrgh/
3618	Xpath 16384				" X: 16384
3619    endtry
3620
3621    try
3622	Xpath 32768				" X: 32768
3623	throw "arrgh"
3624	Xpath 65536				" X: 0
3625    catch /^arrgh$/
3626	Xpath 131072				" X: 131072
3627    endtry
3628
3629    try
3630	Xpath 262144				" X: 262144
3631	throw "arrgh"
3632	Xpath 524288				" X: 0
3633    catch /\l/
3634	Xpath 1048576				" X: 1048576
3635    endtry
3636
3637    try
3638	Xpath 2097152				" X: 2097152
3639	throw "arrgh"
3640	Xpath 4194304				" X: 0
3641    catch /^\l\+$/
3642	Xpath 8388608				" X: 8388608
3643    endtry
3644
3645    try
3646	try
3647	    Xpath 16777216			" X: 16777216
3648	    throw "ARRGH"
3649	    Xpath 33554432			" X: 0
3650	catch /^arrgh$/
3651	    Xpath 67108864			" X: 0
3652	endtry
3653    catch /^\carrgh$/
3654	Xpath 134217728				" X: 134217728
3655    endtry
3656
3657    try
3658	Xpath 268435456				" X: 268435456
3659	throw ""
3660	Xpath 536870912				" X: 0
3661    catch /^$/
3662	Xpath 1073741824			" X: 1073741824
3663    endtry
3664
3665catch /.*/
3666    " The Xpath command does not accept 2^31 (negative); add explicitly:
3667    let Xpath = Xpath + 2147483648		" X: 0
3668    Xout v:exception "in" v:throwpoint
3669endtry
3670
3671Xcheck 1505155949
3672
3673
3674"-------------------------------------------------------------------------------
3675" Test 43:  Selecting the correct :catch clause				    {{{1
3676"
3677"	    When an exception is thrown and there are multiple :catch clauses,
3678"	    the first matching one is taken.
3679"-------------------------------------------------------------------------------
3680
3681XpathINIT
3682
3683XloopINIT 1 1024
3684let loops = 3
3685while loops > 0
3686    try
3687	if loops == 3
3688	    Xloop 1				" X: 1
3689	    throw "a"
3690	    Xloop 2				" X: 0
3691	elseif loops == 2
3692	    Xloop 4				" X: 4*1024
3693	    throw "ab"
3694	    Xloop 8				" X: 0
3695	elseif loops == 1
3696	    Xloop 16				" X: 16*1024*1024
3697	    throw "abc"
3698	    Xloop 32				" X: 0
3699	endif
3700    catch /abc/
3701	Xloop 64				" X: 64*1024*1024
3702    catch /ab/
3703	Xloop 128				" X: 128*1024
3704    catch /.*/
3705	Xloop 256				" X: 256
3706    catch /a/
3707	Xloop 512				" X: 0
3708    endtry
3709
3710    let loops = loops - 1
3711    XloopNEXT
3712endwhile
3713Xpath 1073741824				" X: 1073741824
3714
3715unlet loops
3716
3717Xcheck 1157763329
3718
3719
3720"-------------------------------------------------------------------------------
3721" Test 44:  Missing or empty :catch patterns				    {{{1
3722"
3723"	    A missing or empty :catch pattern means the same as /.*/, that is,
3724"	    catches everything.  To catch only empty exceptions, /^$/ must be
3725"	    used.  A :catch with missing, empty, or /.*/ argument also works
3726"	    when followed by another command separated by a bar on the same
3727"	    line.  :catch patterns cannot be specified between ||.  But other
3728"	    pattern separators can be used instead of //.
3729"-------------------------------------------------------------------------------
3730
3731XpathINIT
3732
3733try
3734    try
3735	Xpath 1					" X: 1
3736	throw ""
3737    catch /^$/
3738	Xpath 2					" X: 2
3739    endtry
3740
3741    try
3742	Xpath 4					" X: 4
3743	throw ""
3744    catch /.*/
3745	Xpath 8					" X: 8
3746    endtry
3747
3748    try
3749	Xpath 16				" X: 16
3750	throw ""
3751    catch //
3752	Xpath 32				" X: 32
3753    endtry
3754
3755    try
3756	Xpath 64				" X: 64
3757	throw ""
3758    catch
3759	Xpath 128				" X: 128
3760    endtry
3761
3762    try
3763	Xpath 256				" X: 256
3764	throw "oops"
3765    catch /^$/
3766	Xpath 512				" X: 0
3767    catch /.*/
3768	Xpath 1024				" X: 1024
3769    endtry
3770
3771    try
3772	Xpath 2048				" X: 2048
3773	throw "arrgh"
3774    catch /^$/
3775	Xpath 4096				" X: 0
3776    catch //
3777	Xpath 8192				" X: 8192
3778    endtry
3779
3780    try
3781	Xpath 16384				" X: 16384
3782	throw "brrr"
3783    catch /^$/
3784	Xpath 32768				" X: 0
3785    catch
3786	Xpath 65536				" X: 65536
3787    endtry
3788
3789    try | Xpath 131072 | throw "x" | catch /.*/ | Xpath 262144 | endtry
3790						" X: 131072 + 262144
3791
3792    try | Xpath 524288 | throw "y" | catch // | Xpath 1048576 | endtry
3793						" X: 524288 + 1048576
3794
3795    while 1
3796	try
3797	    let caught = 0
3798	    let v:errmsg = ""
3799	    " Extra try level:  if ":catch" without arguments below raises
3800	    " a syntax error because it misinterprets the "Xpath" as a pattern,
3801	    " let it be caught by the ":catch /.*/" below.
3802	    try
3803		try | Xpath 2097152 | throw "z" | catch | Xpath 4194304 | :
3804		endtry				" X: 2097152 + 4194304
3805	    endtry
3806	catch /.*/
3807	    let caught = 1
3808	    Xout v:exception "in" v:throwpoint
3809	finally
3810	    if $VIMNOERRTHROW && v:errmsg != ""
3811		Xout v:errmsg
3812	    endif
3813	    if caught || $VIMNOERRTHROW && v:errmsg != ""
3814		Xpath 8388608				" X: 0
3815	    endif
3816	    break		" discard error for $VIMNOERRTHROW
3817	endtry
3818    endwhile
3819
3820    let cologne = 4711
3821    try
3822	try
3823	    Xpath 16777216			" X: 16777216
3824	    throw "throw cologne"
3825	" Next lines catches all and throws 4711:
3826	catch |throw cologne|
3827	    Xpath 33554432			" X: 0
3828	endtry
3829    catch /4711/
3830	Xpath 67108864				" X: 67108864
3831    endtry
3832
3833    try
3834	Xpath 134217728				" X: 134217728
3835	throw "plus"
3836    catch +plus+
3837	Xpath 268435456				" X: 268435456
3838    endtry
3839
3840    Xpath 536870912				" X: 536870912
3841catch /.*/
3842    Xpath 1073741824				" X: 0
3843    Xout v:exception "in" v:throwpoint
3844endtry
3845
3846unlet! caught cologne
3847
3848Xcheck 1031761407
3849
3850
3851"-------------------------------------------------------------------------------
3852" Test 45:  Catching exceptions from nested :try blocks			    {{{1
3853"
3854"	    When :try blocks are nested, an exception is caught by the innermost
3855"	    try conditional that has a matching :catch clause.
3856"-------------------------------------------------------------------------------
3857
3858XpathINIT
3859
3860XloopINIT 1 1024
3861let loops = 3
3862while loops > 0
3863    try
3864	try
3865	    try
3866		try
3867		    if loops == 3
3868			Xloop 1			" X: 1
3869			throw "a"
3870			Xloop 2			" X: 0
3871		    elseif loops == 2
3872			Xloop 4			" X: 4*1024
3873			throw "ab"
3874			Xloop 8			" X: 0
3875		    elseif loops == 1
3876			Xloop 16		" X: 16*1024*1024
3877			throw "abc"
3878			Xloop 32		" X: 0
3879		    endif
3880		catch /abc/
3881		    Xloop 64			" X: 64*1024*1024
3882		endtry
3883	    catch /ab/
3884		Xloop 128			" X: 128*1024
3885	    endtry
3886	catch /.*/
3887	    Xloop 256				" X: 256
3888	endtry
3889    catch /a/
3890	Xloop 512				" X: 0
3891    endtry
3892
3893    let loops = loops - 1
3894    XloopNEXT
3895endwhile
3896Xpath 1073741824				" X: 1073741824
3897
3898unlet loops
3899
3900Xcheck 1157763329
3901
3902
3903"-------------------------------------------------------------------------------
3904" Test 46:  Executing :finally after a :throw in nested :try		    {{{1
3905"
3906"	    When an exception is thrown from within nested :try blocks, the
3907"	    :finally clauses of the non-catching try conditionals should be
3908"	    executed before the matching :catch of the next surrounding :try
3909"	    gets the control.  If this also has a :finally clause, it is
3910"	    executed afterwards.
3911"-------------------------------------------------------------------------------
3912
3913XpathINIT
3914
3915let sum = 0
3916
3917try
3918    Xpath 1					" X: 1
3919    try
3920	Xpath 2					" X: 2
3921	try
3922	    Xpath 4				" X: 4
3923	    try
3924		Xpath 8				" X: 8
3925		throw "ABC"
3926		Xpath 16			" X: 0
3927	    catch /xyz/
3928		Xpath 32			" X: 0
3929	    finally
3930		Xpath 64			" X: 64
3931		if sum != 0
3932		    Xpath 128			" X: 0
3933		endif
3934		let sum = sum + 1
3935	    endtry
3936	    Xpath 256				" X: 0
3937	catch /123/
3938	    Xpath 512				" X: 0
3939	catch /321/
3940	    Xpath 1024				" X: 0
3941	finally
3942	    Xpath 2048				" X: 2048
3943	    if sum != 1
3944		Xpath 4096			" X: 0
3945	    endif
3946	    let sum = sum + 2
3947	endtry
3948	Xpath 8192				" X: 0
3949    finally
3950	Xpath 16384				" X: 16384
3951	if sum != 3
3952	    Xpath 32768				" X: 0
3953	endif
3954	let sum = sum + 4
3955    endtry
3956    Xpath 65536					" X: 0
3957catch /ABC/
3958    Xpath 131072				" X: 131072
3959    if sum != 7
3960	Xpath 262144				" X: 0
3961    endif
3962    let sum = sum + 8
3963finally
3964    Xpath 524288				" X: 524288
3965    if sum != 15
3966	Xpath 1048576				" X: 0
3967    endif
3968    let sum = sum + 16
3969endtry
3970Xpath 65536					" X: 65536
3971if sum != 31
3972    Xpath 131072				" X: 0
3973endif
3974
3975unlet sum
3976
3977Xcheck 739407
3978
3979
3980"-------------------------------------------------------------------------------
3981" Test 47:  Throwing exceptions from a :catch clause			    {{{1
3982"
3983"	    When an exception is thrown from a :catch clause, it should not be
3984"	    caught by a :catch of the same :try conditional.  After executing
3985"	    the :finally clause (if present), surrounding try conditionals
3986"	    should be checked for a matching :catch.
3987"-------------------------------------------------------------------------------
3988
3989XpathINIT
3990
3991Xpath 1						" X: 1
3992try
3993    Xpath 2					" X: 2
3994    try
3995	Xpath 4					" X: 4
3996	try
3997	    Xpath 8				" X: 8
3998	    throw "x1"
3999	    Xpath 16				" X: 0
4000	catch /x1/
4001	    Xpath 32				" X: 32
4002	    try
4003		Xpath 64			" X: 64
4004		throw "x2"
4005		Xpath 128			" X: 0
4006	    catch /x1/
4007		Xpath 256			" X: 0
4008	    catch /x2/
4009		Xpath 512			" X: 512
4010		try
4011		    Xpath 1024			" X: 1024
4012		    throw "x3"
4013		    Xpath 2048			" X: 0
4014		catch /x1/
4015		    Xpath 4096			" X: 0
4016		catch /x2/
4017		    Xpath 8192			" X: 0
4018		finally
4019		    Xpath 16384			" X: 16384
4020		endtry
4021		Xpath 32768			" X: 0
4022	    catch /x3/
4023		Xpath 65536			" X: 0
4024	    endtry
4025	    Xpath 131072			" X: 0
4026	catch /x1/
4027	    Xpath 262144			" X: 0
4028	catch /x2/
4029	    Xpath 524288			" X: 0
4030	catch /x3/
4031	    Xpath 1048576			" X: 0
4032	finally
4033	    Xpath 2097152			" X: 2097152
4034	endtry
4035	Xpath 4194304				" X: 0
4036    catch /x1/
4037	Xpath 8388608				" X: 0
4038    catch /x2/
4039	Xpath 16777216				" X: 0
4040    catch /x3/
4041	Xpath 33554432				" X: 33554432
4042    endtry
4043    Xpath 67108864				" X: 67108864
4044catch /.*/
4045    Xpath 134217728				" X: 0
4046    Xout v:exception "in" v:throwpoint
4047endtry
4048Xpath 268435456					" X: 268435456
4049
4050Xcheck 371213935
4051
4052
4053"-------------------------------------------------------------------------------
4054" Test 48:  Throwing exceptions from a :finally clause			    {{{1
4055"
4056"	    When an exception is thrown from a :finally clause, it should not be
4057"	    caught by a :catch of the same :try conditional.  Surrounding try
4058"	    conditionals should be checked for a matching :catch.  A previously
4059"	    thrown exception is discarded.
4060"-------------------------------------------------------------------------------
4061
4062XpathINIT
4063
4064try
4065
4066    try
4067	try
4068	    Xpath 1				" X: 1
4069	catch /x1/
4070	    Xpath 2				" X: 0
4071	finally
4072	    Xpath 4				" X: 4
4073	    throw "x1"
4074	    Xpath 8				" X: 0
4075	endtry
4076	Xpath 16				" X: 0
4077    catch /x1/
4078	Xpath 32				" X: 32
4079    endtry
4080    Xpath 64					" X: 64
4081
4082    try
4083	try
4084	    Xpath 128				" X: 128
4085	    throw "x2"
4086	    Xpath 256				" X: 0
4087	catch /x2/
4088	    Xpath 512				" X: 512
4089	catch /x3/
4090	    Xpath 1024				" X: 0
4091	finally
4092	    Xpath 2048				" X: 2048
4093	    throw "x3"
4094	    Xpath 4096				" X: 0
4095	endtry
4096	Xpath 8192				" X: 0
4097    catch /x2/
4098	Xpath 16384				" X: 0
4099    catch /x3/
4100	Xpath 32768				" X: 32768
4101    endtry
4102    Xpath 65536					" X: 65536
4103
4104    try
4105	try
4106	    try
4107		Xpath 131072			" X: 131072
4108		throw "x4"
4109		Xpath 262144			" X: 0
4110	    catch /x5/
4111		Xpath 524288			" X: 0
4112	    finally
4113		Xpath 1048576			" X: 1048576
4114		throw "x5"	" discards "x4"
4115		Xpath 2097152			" X: 0
4116	    endtry
4117	    Xpath 4194304			" X: 0
4118	catch /x4/
4119	    Xpath 8388608			" X: 0
4120	finally
4121	    Xpath 16777216			" X: 16777216
4122	endtry
4123	Xpath 33554432				" X: 0
4124    catch /x5/
4125	Xpath 67108864				" X: 67108864
4126    endtry
4127    Xpath 134217728				" X: 134217728
4128
4129catch /.*/
4130    Xpath 268435456				" X: 0
4131    Xout v:exception "in" v:throwpoint
4132endtry
4133Xpath 536870912					" X: 536870912
4134
4135Xcheck 756255461
4136
4137
4138"-------------------------------------------------------------------------------
4139" Test 49:  Throwing exceptions across functions			    {{{1
4140"
4141"	    When an exception is thrown but not caught inside a function, the
4142"	    caller is checked for a matching :catch clause.
4143"-------------------------------------------------------------------------------
4144
4145XpathINIT
4146
4147function! C()
4148    try
4149	Xpath 1					" X: 1
4150	throw "arrgh"
4151	Xpath 2					" X: 0
4152    catch /arrgh/
4153	Xpath 4					" X: 4
4154    endtry
4155    Xpath 8					" X: 8
4156endfunction
4157
4158XloopINIT! 16 16
4159
4160function! T1()
4161    XloopNEXT
4162    try
4163	Xloop 1					" X: 16 + 16*16
4164	throw "arrgh"
4165	Xloop 2					" X: 0
4166    finally
4167	Xloop 4					" X: 64 + 64*16
4168    endtry
4169    Xloop 8					" X: 0
4170endfunction
4171
4172function! T2()
4173    try
4174	Xpath 4096				" X: 4096
4175	call T1()
4176	Xpath 8192				" X: 0
4177    finally
4178	Xpath 16384				" X: 16384
4179    endtry
4180    Xpath 32768					" X: 0
4181endfunction
4182
4183try
4184    Xpath 65536					" X: 65536
4185    call C()	" throw and catch
4186    Xpath 131072				" X: 131072
4187catch /.*/
4188    Xpath 262144				" X: 0
4189    Xout v:exception "in" v:throwpoint
4190endtry
4191
4192try
4193    Xpath 524288				" X: 524288
4194    call T1()  " throw, one level
4195    Xpath 1048576				" X: 0
4196catch /arrgh/
4197    Xpath 2097152				" X: 2097152
4198catch /.*/
4199    Xpath 4194304				" X: 0
4200    Xout v:exception "in" v:throwpoint
4201endtry
4202
4203try
4204    Xpath 8388608				" X: 8388608
4205    call T2()	" throw, two levels
4206    Xpath 16777216				" X: 0
4207catch /arrgh/
4208    Xpath 33554432				" X: 33554432
4209catch /.*/
4210    Xpath 67108864				" X: 0
4211    Xout v:exception "in" v:throwpoint
4212endtry
4213Xpath 134217728					" X: 134217728
4214
4215Xcheck 179000669
4216
4217" Leave C, T1, and T2 for execution as scripts in the next test.
4218
4219
4220"-------------------------------------------------------------------------------
4221" Test 50:  Throwing exceptions across script files			    {{{1
4222"
4223"	    When an exception is thrown but not caught inside a script file,
4224"	    the sourcing script or function is checked for a matching :catch
4225"	    clause.
4226"
4227"	    This test executes the bodies of the functions C, T1, and T2 from
4228"	    the previous test as script files (:return replaced by :finish).
4229"-------------------------------------------------------------------------------
4230
4231XpathINIT
4232
4233let scriptC = MakeScript("C")			" X: 1 + 4 + 8
4234delfunction C
4235
4236XloopINIT! 16 16
4237
4238let scriptT1 = MakeScript("T1")			" X: 16 + 64 + 16*16 + 64*16
4239delfunction T1
4240
4241let scriptT2 = MakeScript("T2", scriptT1)	" X: 4096 + 16384
4242delfunction T2
4243
4244function! F()
4245    try
4246	Xpath 65536				" X: 65536
4247	exec "source" g:scriptC
4248	Xpath 131072				" X: 131072
4249    catch /.*/
4250	Xpath 262144				" X: 0
4251	Xout v:exception "in" v:throwpoint
4252    endtry
4253
4254    try
4255	Xpath 524288				" X: 524288
4256	exec "source" g:scriptT1
4257	Xpath 1048576				" X: 0
4258    catch /arrgh/
4259	Xpath 2097152				" X: 2097152
4260    catch /.*/
4261	Xpath 4194304				" X: 0
4262	Xout v:exception "in" v:throwpoint
4263    endtry
4264endfunction
4265
4266try
4267    Xpath 8388608				" X: 8388608
4268    call F()
4269    Xpath 16777216				" X: 16777216
4270    exec "source" scriptT2
4271    Xpath 33554432				" X: 0
4272catch /arrgh/
4273    Xpath 67108864				" X: 67108864
4274catch /.*/
4275    Xpath 134217728				" X: 0
4276    Xout v:exception "in" v:throwpoint
4277endtry
4278Xpath 268435456					" X: 268435456
4279
4280call delete(scriptC)
4281call delete(scriptT1)
4282call delete(scriptT2)
4283unlet scriptC scriptT1 scriptT2
4284delfunction F
4285
4286Xcheck 363550045
4287
4288
4289"-------------------------------------------------------------------------------
4290" Test 51:  Throwing exceptions across :execute and user commands	    {{{1
4291"
4292"	    A :throw command may be executed under an ":execute" or from
4293"	    a user command.
4294"-------------------------------------------------------------------------------
4295
4296XpathINIT
4297
4298command! -nargs=? THROW1    throw <args> | throw 1
4299command! -nargs=? THROW2    try | throw <args> | endtry | throw 2
4300command! -nargs=? THROW3    try | throw 3 | catch /3/ | throw <args> | endtry
4301command! -nargs=? THROW4    try | throw 4 | finally   | throw <args> | endtry
4302
4303try
4304
4305    try
4306	try
4307	    Xpath 1				" X: 1
4308	    THROW1 "A"
4309	catch /A/
4310	    Xpath 2				" X: 2
4311	endtry
4312    catch /1/
4313	Xpath 4					" X: 0
4314    endtry
4315
4316    try
4317	try
4318	    Xpath 8				" X: 8
4319	    THROW2 "B"
4320	catch /B/
4321	    Xpath 16				" X: 16
4322	endtry
4323    catch /2/
4324	Xpath 32				" X: 0
4325    endtry
4326
4327    try
4328	try
4329	    Xpath 64				" X: 64
4330	    THROW3 "C"
4331	catch /C/
4332	    Xpath 128				" X: 128
4333	endtry
4334    catch /3/
4335	Xpath 256				" X: 0
4336    endtry
4337
4338    try
4339	try
4340	    Xpath 512				" X: 512
4341	    THROW4 "D"
4342	catch /D/
4343	    Xpath 1024				" X: 1024
4344	endtry
4345    catch /4/
4346	Xpath 2048				" X: 0
4347    endtry
4348
4349    try
4350	try
4351	    Xpath 4096				" X: 4096
4352	    execute 'throw "E" | throw 5'
4353	catch /E/
4354	    Xpath 8192				" X: 8192
4355	endtry
4356    catch /5/
4357	Xpath 16384				" X: 0
4358    endtry
4359
4360    try
4361	try
4362	    Xpath 32768				" X: 32768
4363	    execute 'try | throw "F" | endtry | throw 6'
4364	catch /F/
4365	    Xpath 65536				" X: 65536
4366	endtry
4367    catch /6/
4368	Xpath 131072				" X: 0
4369    endtry
4370
4371    try
4372	try
4373	    Xpath 262144			" X: 262144
4374	    execute'try | throw 7 | catch /7/ | throw "G" | endtry'
4375	catch /G/
4376	    Xpath 524288			" X: 524288
4377	endtry
4378    catch /7/
4379	Xpath 1048576				" X: 0
4380    endtry
4381
4382    try
4383	try
4384	    Xpath 2097152			" X: 2097152
4385	    execute 'try | throw 8 | finally   | throw "H" | endtry'
4386	catch /H/
4387	    Xpath 4194304			" X: 4194304
4388	endtry
4389    catch /8/
4390	Xpath 8388608				" X: 0
4391    endtry
4392
4393catch /.*/
4394    Xpath 16777216				" X: 0
4395    Xout v:exception "in" v:throwpoint
4396endtry
4397
4398Xpath 33554432					" X: 33554432
4399
4400delcommand THROW1
4401delcommand THROW2
4402delcommand THROW3
4403delcommand THROW4
4404
4405Xcheck 40744667
4406
4407
4408"-------------------------------------------------------------------------------
4409" Test 52:  Uncaught exceptions						    {{{1
4410"
4411"	    When an exception is thrown but not caught, an error message is
4412"	    displayed when the script is terminated.  In case of an interrupt
4413"	    or error exception, the normal interrupt or error message(s) are
4414"	    displayed.
4415"-------------------------------------------------------------------------------
4416
4417XpathINIT
4418
4419let msgfile = tempname()
4420
4421function! MESSAGES(...)
4422    try
4423	exec "edit" g:msgfile
4424    catch /^Vim(edit):/
4425	return 0
4426    endtry
4427
4428    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
4429    let match = 1
4430    norm gg
4431
4432    let num = a:0 / 2
4433    let cnt = 1
4434    while cnt <= num
4435	let enr = a:{2*cnt - 1}
4436	let emsg= a:{2*cnt}
4437	let cnt = cnt + 1
4438
4439	if enr == ""
4440	    Xout "TODO: Add message number for:" emsg
4441	elseif enr == "INT"
4442	    let enr = ""
4443	endif
4444	if enr == "" && !english
4445	    continue
4446	endif
4447	let pattern = (enr != "") ? enr . ':.*' : ''
4448	if english
4449	    let pattern = pattern . emsg
4450	endif
4451	if !search(pattern, "W")
4452	    let match = 0
4453	    Xout "No match for:" pattern
4454	endif
4455	norm $
4456    endwhile
4457
4458    bwipeout!
4459    return match
4460endfunction
4461
4462if ExtraVim(msgfile)
4463    Xpath 1					" X: 1
4464    throw "arrgh"
4465endif
4466
4467Xpath 2						" X: 2
4468if !MESSAGES('E605', "Exception not caught")
4469    Xpath 4					" X: 0
4470endif
4471
4472if ExtraVim(msgfile)
4473    try
4474	Xpath 8					" X: 8
4475	throw "oops"
4476    catch /arrgh/
4477	Xpath 16				" X: 0
4478    endtry
4479    Xpath 32					" X: 0
4480endif
4481
4482Xpath 64					" X: 64
4483if !MESSAGES('E605', "Exception not caught")
4484    Xpath 128					" X: 0
4485endif
4486
4487if ExtraVim(msgfile)
4488    function! T()
4489	throw "brrr"
4490    endfunction
4491
4492    try
4493	Xpath 256				" X: 256
4494	throw "arrgh"
4495    catch /.*/
4496	Xpath 512				" X: 512
4497	call T()
4498    endtry
4499    Xpath 1024					" X: 0
4500endif
4501
4502Xpath 2048					" X: 2048
4503if !MESSAGES('E605', "Exception not caught")
4504    Xpath 4096					" X: 0
4505endif
4506
4507if ExtraVim(msgfile)
4508    try
4509	Xpath 8192				" X: 8192
4510	throw "arrgh"
4511    finally
4512	Xpath 16384				" X: 16384
4513	throw "brrr"
4514    endtry
4515    Xpath 32768					" X: 0
4516endif
4517
4518Xpath 65536					" X: 65536
4519if !MESSAGES('E605', "Exception not caught")
4520    Xpath 131072				" X: 0
4521endif
4522
4523if ExtraVim(msgfile)
4524    try
4525	Xpath 262144				" X: 262144
4526	"INTERRUPT
4527    endtry
4528    Xpath 524288				" X: 0
4529endif
4530
4531Xpath 1048576					" X: 1048576
4532if !MESSAGES('INT', "Interrupted")
4533    Xpath 2097152				" X: 0
4534endif
4535
4536if ExtraVim(msgfile)
4537    try
4538	Xpath 4194304				" X: 4194304
4539	let x = novar	" error E121/E15; exception: E121
4540    catch /E15:/	" should not catch
4541	Xpath 8388608				" X: 0
4542    endtry
4543    Xpath 16777216				" X: 0
4544endif
4545
4546Xpath 33554432					" X: 33554432
4547if !MESSAGES('E121', "Undefined variable", 'E15', "Invalid expression")
4548    Xpath 67108864				" X: 0
4549endif
4550
4551if ExtraVim(msgfile)
4552    try
4553	Xpath 134217728				" X: 134217728
4554"	unlet novar #	" error E108/E488; exception: E488
4555    catch /E108:/	" should not catch
4556	Xpath 268435456				" X: 0
4557    endtry
4558    Xpath 536870912				" X: 0
4559endif
4560
4561Xpath 1073741824				" X: 1073741824
4562if !MESSAGES('E108', "No such variable", 'E488', "Trailing characters")
4563    " The Xpath command does not accept 2^31 (negative); add explicitly:
4564    let Xpath = Xpath + 2147483648		" X: 0
4565endif
4566
4567call delete(msgfile)
4568unlet msgfile
4569
4570Xcheck 1247112011
4571
4572" Leave MESSAGES() for the next tests.
4573
4574
4575"-------------------------------------------------------------------------------
4576" Test 53:  Nesting errors: :endif/:else/:elseif			    {{{1
4577"
4578"	    For nesting errors of :if conditionals the correct error messages
4579"	    should be given.
4580"
4581"	    This test reuses the function MESSAGES() from the previous test.
4582"	    This functions checks the messages in g:msgfile.
4583"-------------------------------------------------------------------------------
4584
4585XpathINIT
4586
4587let msgfile = tempname()
4588
4589if ExtraVim(msgfile)
4590"   endif
4591endif
4592if MESSAGES('E580', ":endif without :if")
4593    Xpath 1					" X: 1
4594endif
4595
4596if ExtraVim(msgfile)
4597"   while 1
4598"       endif
4599"   endwhile
4600endif
4601if MESSAGES('E580', ":endif without :if")
4602    Xpath 2					" X: 2
4603endif
4604
4605if ExtraVim(msgfile)
4606"   try
4607"   finally
4608"       endif
4609"   endtry
4610endif
4611if MESSAGES('E580', ":endif without :if")
4612    Xpath 4					" X: 4
4613endif
4614
4615if ExtraVim(msgfile)
4616"   try
4617"       endif
4618"   endtry
4619endif
4620if MESSAGES('E580', ":endif without :if")
4621    Xpath 8					" X: 8
4622endif
4623
4624if ExtraVim(msgfile)
4625"   try
4626"       throw "a"
4627"   catch /a/
4628"       endif
4629"   endtry
4630endif
4631if MESSAGES('E580', ":endif without :if")
4632    Xpath 16					" X: 16
4633endif
4634
4635if ExtraVim(msgfile)
4636"   else
4637endif
4638if MESSAGES('E581', ":else without :if")
4639    Xpath 32					" X: 32
4640endif
4641
4642if ExtraVim(msgfile)
4643"   while 1
4644"       else
4645"   endwhile
4646endif
4647if MESSAGES('E581', ":else without :if")
4648    Xpath 64					" X: 64
4649endif
4650
4651if ExtraVim(msgfile)
4652"   try
4653"   finally
4654"       else
4655"   endtry
4656endif
4657if MESSAGES('E581', ":else without :if")
4658    Xpath 128					" X: 128
4659endif
4660
4661if ExtraVim(msgfile)
4662"   try
4663"       else
4664"   endtry
4665endif
4666if MESSAGES('E581', ":else without :if")
4667    Xpath 256					" X: 256
4668endif
4669
4670if ExtraVim(msgfile)
4671"   try
4672"       throw "a"
4673"   catch /a/
4674"       else
4675"   endtry
4676endif
4677if MESSAGES('E581', ":else without :if")
4678    Xpath 512					" X: 512
4679endif
4680
4681if ExtraVim(msgfile)
4682"   elseif
4683endif
4684if MESSAGES('E582', ":elseif without :if")
4685    Xpath 1024					" X: 1024
4686endif
4687
4688if ExtraVim(msgfile)
4689"   while 1
4690"       elseif
4691"   endwhile
4692endif
4693if MESSAGES('E582', ":elseif without :if")
4694    Xpath 2048					" X: 2048
4695endif
4696
4697if ExtraVim(msgfile)
4698"   try
4699"   finally
4700"       elseif
4701"   endtry
4702endif
4703if MESSAGES('E582', ":elseif without :if")
4704    Xpath 4096					" X: 4096
4705endif
4706
4707if ExtraVim(msgfile)
4708"   try
4709"       elseif
4710"   endtry
4711endif
4712if MESSAGES('E582', ":elseif without :if")
4713    Xpath 8192					" X: 8192
4714endif
4715
4716if ExtraVim(msgfile)
4717"   try
4718"       throw "a"
4719"   catch /a/
4720"       elseif
4721"   endtry
4722endif
4723if MESSAGES('E582', ":elseif without :if")
4724    Xpath 16384					" X: 16384
4725endif
4726
4727if ExtraVim(msgfile)
4728"   if 1
4729"   else
4730"   else
4731"   endif
4732endif
4733if MESSAGES('E583', "multiple :else")
4734    Xpath 32768					" X: 32768
4735endif
4736
4737if ExtraVim(msgfile)
4738"   if 1
4739"   else
4740"   elseif 1
4741"   endif
4742endif
4743if MESSAGES('E584', ":elseif after :else")
4744    Xpath 65536					" X: 65536
4745endif
4746
4747call delete(msgfile)
4748unlet msgfile
4749
4750Xcheck 131071
4751
4752" Leave MESSAGES() for the next test.
4753
4754
4755"-------------------------------------------------------------------------------
4756" Test 54:  Nesting errors: :while/:endwhile				    {{{1
4757"
4758"	    For nesting errors of :while conditionals the correct error messages
4759"	    should be given.
4760"
4761"	    This test reuses the function MESSAGES() from the previous test.
4762"	    This functions checks the messages in g:msgfile.
4763"-------------------------------------------------------------------------------
4764
4765XpathINIT
4766
4767let msgfile = tempname()
4768
4769if ExtraVim(msgfile)
4770"   endwhile
4771endif
4772if MESSAGES('E588', ":endwhile without :while")
4773    Xpath 1					" X: 1
4774endif
4775
4776if ExtraVim(msgfile)
4777"   if 1
4778"       endwhile
4779"   endif
4780endif
4781if MESSAGES('E588', ":endwhile without :while")
4782    Xpath 2					" X: 2
4783endif
4784
4785if ExtraVim(msgfile)
4786"   while 1
4787"       if 1
4788"   endwhile
4789endif
4790if MESSAGES('E171', "Missing :endif")
4791    Xpath 4					" X: 4
4792endif
4793
4794if ExtraVim(msgfile)
4795"   try
4796"   finally
4797"       endwhile
4798"   endtry
4799endif
4800if MESSAGES('E588', ":endwhile without :while")
4801    Xpath 8					" X: 8
4802endif
4803
4804if ExtraVim(msgfile)
4805"   while 1
4806"       try
4807"       finally
4808"   endwhile
4809endif
4810if MESSAGES('E600', "Missing :endtry")
4811    Xpath 16					" X: 16
4812endif
4813
4814if ExtraVim(msgfile)
4815"   while 1
4816"       if 1
4817"	    try
4818"	    finally
4819"   endwhile
4820endif
4821if MESSAGES('E600', "Missing :endtry")
4822    Xpath 32					" X: 32
4823endif
4824
4825if ExtraVim(msgfile)
4826"   while 1
4827"       try
4828"       finally
4829"	    if 1
4830"   endwhile
4831endif
4832if MESSAGES('E171', "Missing :endif")
4833    Xpath 64					" X: 64
4834endif
4835
4836if ExtraVim(msgfile)
4837"   try
4838"       endwhile
4839"   endtry
4840endif
4841if MESSAGES('E588', ":endwhile without :while")
4842    Xpath 128					" X: 128
4843endif
4844
4845if ExtraVim(msgfile)
4846"   while 1
4847"       try
4848"	    endwhile
4849"       endtry
4850"   endwhile
4851endif
4852if MESSAGES('E588', ":endwhile without :while")
4853    Xpath 256					" X: 256
4854endif
4855
4856if ExtraVim(msgfile)
4857"   try
4858"       throw "a"
4859"   catch /a/
4860"       endwhile
4861"   endtry
4862endif
4863if MESSAGES('E588', ":endwhile without :while")
4864    Xpath 512					" X: 512
4865endif
4866
4867if ExtraVim(msgfile)
4868"   while 1
4869"       try
4870"	    throw "a"
4871"	catch /a/
4872"	    endwhile
4873"       endtry
4874"   endwhile
4875endif
4876if MESSAGES('E588', ":endwhile without :while")
4877    Xpath 1024					" X: 1024
4878endif
4879
4880
4881call delete(msgfile)
4882unlet msgfile
4883
4884Xcheck 2047
4885
4886" Leave MESSAGES() for the next test.
4887
4888
4889"-------------------------------------------------------------------------------
4890" Test 55:  Nesting errors: :continue/:break				    {{{1
4891"
4892"	    For nesting errors of :continue and :break commands the correct
4893"	    error messages should be given.
4894"
4895"	    This test reuses the function MESSAGES() from the previous test.
4896"	    This functions checks the messages in g:msgfile.
4897"-------------------------------------------------------------------------------
4898
4899XpathINIT
4900
4901let msgfile = tempname()
4902
4903if ExtraVim(msgfile)
4904"   continue
4905endif
4906if MESSAGES('E586', ":continue without :while")
4907    Xpath 1					" X: 1
4908endif
4909
4910if ExtraVim(msgfile)
4911"   if 1
4912"       continue
4913"   endif
4914endif
4915if MESSAGES('E586', ":continue without :while")
4916    Xpath 2					" X: 2
4917endif
4918
4919if ExtraVim(msgfile)
4920"   try
4921"   finally
4922"       continue
4923"   endtry
4924endif
4925if MESSAGES('E586', ":continue without :while")
4926    Xpath 4					" X: 4
4927endif
4928
4929if ExtraVim(msgfile)
4930"   try
4931"       continue
4932"   endtry
4933endif
4934if MESSAGES('E586', ":continue without :while")
4935    Xpath 8					" X: 8
4936endif
4937
4938if ExtraVim(msgfile)
4939"   try
4940"       throw "a"
4941"   catch /a/
4942"       continue
4943"   endtry
4944endif
4945if MESSAGES('E586', ":continue without :while")
4946    Xpath 16					" X: 16
4947endif
4948
4949if ExtraVim(msgfile)
4950"   break
4951endif
4952if MESSAGES('E587', ":break without :while")
4953    Xpath 32					" X: 32
4954endif
4955
4956if ExtraVim(msgfile)
4957"   if 1
4958"       break
4959"   endif
4960endif
4961if MESSAGES('E587', ":break without :while")
4962    Xpath 64					" X: 64
4963endif
4964
4965if ExtraVim(msgfile)
4966"   try
4967"   finally
4968"       break
4969"   endtry
4970endif
4971if MESSAGES('E587', ":break without :while")
4972    Xpath 128					" X: 128
4973endif
4974
4975if ExtraVim(msgfile)
4976"   try
4977"       break
4978"   endtry
4979endif
4980if MESSAGES('E587', ":break without :while")
4981    Xpath 256					" X: 256
4982endif
4983
4984if ExtraVim(msgfile)
4985"   try
4986"       throw "a"
4987"   catch /a/
4988"       break
4989"   endtry
4990endif
4991if MESSAGES('E587', ":break without :while")
4992    Xpath 512					" X: 512
4993endif
4994
4995call delete(msgfile)
4996unlet msgfile
4997
4998Xcheck 1023
4999
5000" Leave MESSAGES() for the next test.
5001
5002
5003"-------------------------------------------------------------------------------
5004" Test 56:  Nesting errors: :endtry					    {{{1
5005"
5006"	    For nesting errors of :try conditionals the correct error messages
5007"	    should be given.
5008"
5009"	    This test reuses the function MESSAGES() from the previous test.
5010"	    This functions checks the messages in g:msgfile.
5011"-------------------------------------------------------------------------------
5012
5013XpathINIT
5014
5015let msgfile = tempname()
5016
5017if ExtraVim(msgfile)
5018"   endtry
5019endif
5020if MESSAGES('E602', ":endtry without :try")
5021    Xpath 1					" X: 1
5022endif
5023
5024if ExtraVim(msgfile)
5025"   if 1
5026"       endtry
5027"   endif
5028endif
5029if MESSAGES('E602', ":endtry without :try")
5030    Xpath 2					" X: 2
5031endif
5032
5033if ExtraVim(msgfile)
5034"   while 1
5035"       endtry
5036"   endwhile
5037endif
5038if MESSAGES('E602', ":endtry without :try")
5039    Xpath 4					" X: 4
5040endif
5041
5042if ExtraVim(msgfile)
5043"   try
5044"       if 1
5045"   endtry
5046endif
5047if MESSAGES('E171', "Missing :endif")
5048    Xpath 8					" X: 8
5049endif
5050
5051if ExtraVim(msgfile)
5052"   try
5053"       while 1
5054"   endtry
5055endif
5056if MESSAGES('E170', "Missing :endwhile")
5057    Xpath 16					" X: 16
5058endif
5059
5060if ExtraVim(msgfile)
5061"   try
5062"   finally
5063"       if 1
5064"   endtry
5065endif
5066if MESSAGES('E171', "Missing :endif")
5067    Xpath 32					" X: 32
5068endif
5069
5070if ExtraVim(msgfile)
5071"   try
5072"   finally
5073"       while 1
5074"   endtry
5075endif
5076if MESSAGES('E170', "Missing :endwhile")
5077    Xpath 64					" X: 64
5078endif
5079
5080if ExtraVim(msgfile)
5081"   try
5082"       throw "a"
5083"   catch /a/
5084"       if 1
5085"   endtry
5086endif
5087if MESSAGES('E171', "Missing :endif")
5088    Xpath 128					" X: 128
5089endif
5090
5091if ExtraVim(msgfile)
5092"   try
5093"       throw "a"
5094"   catch /a/
5095"       while 1
5096"   endtry
5097endif
5098if MESSAGES('E170', "Missing :endwhile")
5099    Xpath 256					" X: 256
5100endif
5101
5102call delete(msgfile)
5103unlet msgfile
5104
5105delfunction MESSAGES
5106
5107Xcheck 511
5108
5109
5110"-------------------------------------------------------------------------------
5111" Test 57:  v:exception and v:throwpoint for user exceptions		    {{{1
5112"
5113"	    v:exception evaluates to the value of the exception that was caught
5114"	    most recently and is not finished.  (A caught exception is finished
5115"	    when the next ":catch", ":finally", or ":endtry" is reached.)
5116"	    v:throwpoint evaluates to the script/function name and line number
5117"	    where that exception has been thrown.
5118"-------------------------------------------------------------------------------
5119
5120XpathINIT
5121
5122function! FuncException()
5123    let g:exception = v:exception
5124endfunction
5125
5126function! FuncThrowpoint()
5127    let g:throwpoint = v:throwpoint
5128endfunction
5129
5130let scriptException  = MakeScript("FuncException")
5131let scriptThrowPoint = MakeScript("FuncThrowpoint")
5132
5133command! CmdException  let g:exception  = v:exception
5134command! CmdThrowpoint let g:throwpoint = v:throwpoint
5135
5136XloopINIT! 1 2
5137
5138function! CHECK(n, exception, throwname, throwline)
5139    XloopNEXT
5140    let error = 0
5141    if v:exception != a:exception
5142	Xout a:n.": v:exception is" v:exception "instead of" a:exception
5143	let error = 1
5144    endif
5145    if v:throwpoint !~ a:throwname
5146	let name = escape(a:throwname, '\')
5147	Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" name
5148	let error = 1
5149    endif
5150    if v:throwpoint !~ a:throwline
5151	let line = escape(a:throwline, '\')
5152	Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
5153	let error = 1
5154    endif
5155    if error
5156	Xloop 1					" X: 0
5157    endif
5158endfunction
5159
5160function! T(arg, line)
5161    if a:line == 2
5162	throw a:arg		" in line 2
5163    elseif a:line == 4
5164	throw a:arg		" in line 4
5165    elseif a:line == 6
5166	throw a:arg		" in line 6
5167    elseif a:line == 8
5168	throw a:arg		" in line 8
5169    endif
5170endfunction
5171
5172function! G(arg, line)
5173    call T(a:arg, a:line)
5174endfunction
5175
5176function! F(arg, line)
5177    call G(a:arg, a:line)
5178endfunction
5179
5180let scriptT = MakeScript("T")
5181let scriptG = MakeScript("G", scriptT)
5182let scriptF = MakeScript("F", scriptG)
5183
5184try
5185    Xpath 32768					" X: 32768
5186    call F("oops", 2)
5187catch /.*/
5188    Xpath 65536					" X: 65536
5189    let exception  = v:exception
5190    let throwpoint = v:throwpoint
5191    call CHECK(1, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5192    exec "let exception  = v:exception"
5193    exec "let throwpoint = v:throwpoint"
5194    call CHECK(2, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5195    CmdException
5196    CmdThrowpoint
5197    call CHECK(3, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5198    call FuncException()
5199    call FuncThrowpoint()
5200    call CHECK(4, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5201    exec "source" scriptException
5202    exec "source" scriptThrowPoint
5203    call CHECK(5, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5204    try
5205	Xpath 131072				" X: 131072
5206	call G("arrgh", 4)
5207    catch /.*/
5208	Xpath 262144				" X: 262144
5209	let exception  = v:exception
5210	let throwpoint = v:throwpoint
5211	call CHECK(6, "arrgh", '\<G\.\.T\>', '\<4\>')
5212	try
5213	    Xpath 524288			" X: 524288
5214	    let g:arg = "autsch"
5215	    let g:line = 6
5216	    exec "source" scriptF
5217	catch /.*/
5218	    Xpath 1048576			" X: 1048576
5219	    let exception  = v:exception
5220	    let throwpoint = v:throwpoint
5221	    " Symbolic links in tempname()s are not resolved, whereas resolving
5222	    " is done for v:throwpoint.  Resolve the temporary file name for
5223	    " scriptT, so that it can be matched against v:throwpoint.
5224	    call CHECK(7, "autsch", resolve(scriptT), '\<6\>')
5225	finally
5226	    Xpath 2097152			" X: 2097152
5227	    let exception  = v:exception
5228	    let throwpoint = v:throwpoint
5229	    call CHECK(8, "arrgh", '\<G\.\.T\>', '\<4\>')
5230	    try
5231		Xpath 4194304			" X: 4194304
5232		let g:arg = "brrrr"
5233		let g:line = 8
5234		exec "source" scriptG
5235	    catch /.*/
5236		Xpath 8388608			" X: 8388608
5237		let exception  = v:exception
5238		let throwpoint = v:throwpoint
5239		" Resolve scriptT for matching it against v:throwpoint.
5240		call CHECK(9, "brrrr", resolve(scriptT), '\<8\>')
5241	    finally
5242		Xpath 16777216			" X: 16777216
5243		let exception  = v:exception
5244		let throwpoint = v:throwpoint
5245		call CHECK(10, "arrgh", '\<G\.\.T\>', '\<4\>')
5246	    endtry
5247	    Xpath 33554432			" X: 33554432
5248	    let exception  = v:exception
5249	    let throwpoint = v:throwpoint
5250	    call CHECK(11, "arrgh", '\<G\.\.T\>', '\<4\>')
5251	endtry
5252	Xpath 67108864				" X: 67108864
5253	let exception  = v:exception
5254	let throwpoint = v:throwpoint
5255	call CHECK(12, "arrgh", '\<G\.\.T\>', '\<4\>')
5256    finally
5257	Xpath 134217728				" X: 134217728
5258	let exception  = v:exception
5259	let throwpoint = v:throwpoint
5260	call CHECK(13, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5261    endtry
5262    Xpath 268435456				" X: 268435456
5263    let exception  = v:exception
5264    let throwpoint = v:throwpoint
5265    call CHECK(14, "oops", '\<F\.\.G\.\.T\>', '\<2\>')
5266finally
5267    Xpath 536870912				" X: 536870912
5268    let exception  = v:exception
5269    let throwpoint = v:throwpoint
5270    call CHECK(15, "", '^$', '^$')
5271endtry
5272
5273Xpath 1073741824				" X: 1073741824
5274
5275unlet exception throwpoint
5276delfunction FuncException
5277delfunction FuncThrowpoint
5278call delete(scriptException)
5279call delete(scriptThrowPoint)
5280unlet scriptException scriptThrowPoint
5281delcommand CmdException
5282delcommand CmdThrowpoint
5283delfunction T
5284delfunction G
5285delfunction F
5286call delete(scriptT)
5287call delete(scriptG)
5288call delete(scriptF)
5289unlet scriptT scriptG scriptF
5290
5291Xcheck 2147450880
5292
5293
5294"-------------------------------------------------------------------------------
5295"
5296" Test 58:  v:exception and v:throwpoint for error/interrupt exceptions	    {{{1
5297"
5298"	    v:exception and v:throwpoint work also for error and interrupt
5299"	    exceptions.
5300"-------------------------------------------------------------------------------
5301
5302XpathINIT
5303
5304if ExtraVim()
5305
5306    function! T(line)
5307	if a:line == 2
5308	    delfunction T		" error (function in use) in line 2
5309	elseif a:line == 4
5310	    let dummy = 0		" INTERRUPT1 - interrupt in line 4
5311	endif
5312    endfunction
5313
5314    while 1
5315	try
5316	    Xpath 1				" X: 1
5317	    let caught = 0
5318	    call T(2)
5319	catch /.*/
5320	    let caught = 1
5321	    if v:exception !~ 'Vim(delfunction):'
5322		Xpath 2				" X: 0
5323	    endif
5324	    if v:throwpoint !~ '\<T\>'
5325		Xpath 4				" X: 0
5326	    endif
5327	    if v:throwpoint !~ '\<2\>'
5328		Xpath 8				" X: 0
5329	    endif
5330	finally
5331	    Xpath 16				" X: 16
5332	    if caught || $VIMNOERRTHROW
5333		Xpath 32			" X: 32
5334	    endif
5335	    if v:exception != ""
5336		Xpath 64			" X: 0
5337	    endif
5338	    if v:throwpoint != ""
5339		Xpath 128			" X: 0
5340	    endif
5341	    break		" discard error for $VIMNOERRTHROW
5342	endtry
5343    endwhile
5344
5345    Xpath 256					" X: 256
5346    if v:exception != ""
5347	Xpath 512				" X: 0
5348    endif
5349    if v:throwpoint != ""
5350	Xpath 1024				" X: 0
5351    endif
5352
5353    while 1
5354	try
5355	    Xpath 2048				" X: 2048
5356	    let caught = 0
5357	    call T(4)
5358	catch /.*/
5359	    let caught = 1
5360	    if v:exception != 'Vim:Interrupt'
5361		Xpath 4096			" X: 0
5362	    endif
5363	    if v:throwpoint !~ '\<T\>'
5364		Xpath 8192			" X: 0
5365	    endif
5366	    if v:throwpoint !~ '\<4\>'
5367		Xpath 16384			" X: 0
5368	    endif
5369	finally
5370	    Xpath 32768				" X: 32768
5371	    if caught || $VIMNOINTTHROW
5372		Xpath 65536			" X: 65536
5373	    endif
5374	    if v:exception != ""
5375		Xpath 131072			" X: 0
5376	    endif
5377	    if v:throwpoint != ""
5378		Xpath 262144			" X: 0
5379	    endif
5380	    break		" discard error for $VIMNOERRTHROW
5381	endtry
5382    endwhile
5383
5384    Xpath 524288				" X: 524288
5385    if v:exception != ""
5386	Xpath 1048576				" X: 0
5387    endif
5388    if v:throwpoint != ""
5389	Xpath 2097152				" X: 0
5390    endif
5391
5392endif
5393
5394Xcheck 624945
5395
5396
5397"-------------------------------------------------------------------------------
5398"
5399" Test 59:  v:exception and v:throwpoint when discarding exceptions	    {{{1
5400"
5401"	    When a :catch clause is left by a ":break" etc or an error or
5402"	    interrupt exception, v:exception and v:throwpoint are reset.  They
5403"	    are not affected by an exception that is discarded before being
5404"	    caught.
5405"-------------------------------------------------------------------------------
5406
5407XpathINIT
5408
5409if ExtraVim()
5410
5411    XloopINIT! 1 2
5412
5413    let sfile = expand("<sfile>")
5414
5415    function! LineNumber()
5416	return substitute(substitute(v:throwpoint, g:sfile, '', ""),
5417	    \ '\D*\(\d*\).*', '\1', "")
5418    endfunction
5419
5420    command! -nargs=1 SetLineNumber
5421	\ try | throw "line" | catch /.*/ | let <args> =  LineNumber() | endtry
5422
5423    " Check v:exception/v:throwpoint against second/fourth parameter if
5424    " specified, check for being empty else.
5425    function! CHECK(n, ...)
5426	XloopNEXT
5427	let exception = a:0 != 0 ? a:1 : ""	" second parameter (optional)
5428	let emsg      = a:0 != 0 ? a:2 : ""	" third parameter (optional)
5429	let line      = a:0 != 0 ? a:3 : 0	" fourth parameter (optional)
5430	let error = 0
5431	if emsg != ""
5432	    " exception is the error number, emsg the English error message text
5433	    if exception !~ '^E\d\+$'
5434		Xout "TODO: Add message number for:" emsg
5435	    elseif v:lang == "C" || v:lang =~ '^[Ee]n'
5436		if exception == "E492" && emsg == "Not an editor command"
5437		    let exception = '^Vim:' . exception . ': ' . emsg
5438		else
5439		    let exception = '^Vim(\a\+):' . exception . ': ' . emsg
5440		endif
5441	    else
5442		if exception == "E492"
5443		    let exception = '^Vim:' . exception
5444		else
5445		    let exception = '^Vim(\a\+):' . exception
5446		endif
5447	    endif
5448	endif
5449	if exception == "" && v:exception != ""
5450	    Xout a:n.": v:exception is set:" v:exception
5451	    let error = 1
5452	elseif exception != "" && v:exception !~ exception
5453	    Xout a:n.": v:exception (".v:exception.") does not match" exception
5454	    let error = 1
5455	endif
5456	if line == 0 && v:throwpoint != ""
5457	    Xout a:n.": v:throwpoint is set:" v:throwpoint
5458	    let error = 1
5459	elseif line != 0 && v:throwpoint !~ '\<' . line . '\>'
5460	    Xout a:n.": v:throwpoint (".v:throwpoint.") does not match" line
5461	    let error = 1
5462	endif
5463	if !error
5464	    Xloop 1				" X: 2097151
5465	endif
5466    endfunction
5467
5468    while 1
5469	try
5470	    throw "x1"
5471	catch /.*/
5472	    break
5473	endtry
5474    endwhile
5475    call CHECK(1)
5476
5477    while 1
5478	try
5479	    throw "x2"
5480	catch /.*/
5481	    break
5482	finally
5483	    call CHECK(2)
5484	endtry
5485	break
5486    endwhile
5487    call CHECK(3)
5488
5489    while 1
5490	try
5491	    let errcaught = 0
5492	    try
5493		try
5494		    throw "x3"
5495		catch /.*/
5496		    SetLineNumber line_before_error
5497		    asdf
5498		endtry
5499	    catch /.*/
5500		let errcaught = 1
5501		call CHECK(4, 'E492', "Not an editor command",
5502		    \ line_before_error + 1)
5503	    endtry
5504	finally
5505	    if !errcaught && $VIMNOERRTHROW
5506		call CHECK(4)
5507	    endif
5508	    break		" discard error for $VIMNOERRTHROW
5509	endtry
5510    endwhile
5511    call CHECK(5)
5512
5513    Xpath 2097152				" X: 2097152
5514
5515    while 1
5516	try
5517	    let intcaught = 0
5518	    try
5519		try
5520		    throw "x4"
5521		catch /.*/
5522		    SetLineNumber two_lines_before_interrupt
5523		    "INTERRUPT
5524		    let dummy = 0
5525		endtry
5526	    catch /.*/
5527		let intcaught = 1
5528		call CHECK(6, "Vim:Interrupt", '',
5529		    \ two_lines_before_interrupt + 2)
5530	    endtry
5531	finally
5532	    if !intcaught && $VIMNOINTTHROW
5533		call CHECK(6)
5534	    endif
5535	    break		" discard interrupt for $VIMNOINTTHROW
5536	endtry
5537    endwhile
5538    call CHECK(7)
5539
5540    Xpath 4194304				" X: 4194304
5541
5542    while 1
5543	try
5544	    let errcaught = 0
5545	    try
5546		try
5547"		    if 1
5548			SetLineNumber line_before_throw
5549			throw "x5"
5550		    " missing endif
5551		catch /.*/
5552		    Xpath 8388608			" X: 0
5553		endtry
5554	    catch /.*/
5555		let errcaught = 1
5556		call CHECK(8, 'E171', "Missing :endif", line_before_throw + 3)
5557	    endtry
5558	finally
5559	    if !errcaught && $VIMNOERRTHROW
5560		call CHECK(8)
5561	    endif
5562	    break		" discard error for $VIMNOERRTHROW
5563	endtry
5564    endwhile
5565    call CHECK(9)
5566
5567    Xpath 16777216				" X: 16777216
5568
5569    try
5570	while 1
5571	    try
5572		throw "x6"
5573	    finally
5574		break
5575	    endtry
5576	    break
5577	endwhile
5578    catch /.*/
5579	Xpath 33554432				" X: 0
5580    endtry
5581    call CHECK(10)
5582
5583    try
5584	while 1
5585	    try
5586		throw "x7"
5587	    finally
5588		break
5589	    endtry
5590	    break
5591	endwhile
5592    catch /.*/
5593	Xpath 67108864				" X: 0
5594    finally
5595	call CHECK(11)
5596    endtry
5597    call CHECK(12)
5598
5599    while 1
5600	try
5601	    let errcaught = 0
5602	    try
5603		try
5604		    throw "x8"
5605		finally
5606		    SetLineNumber line_before_error
5607		    asdf
5608		endtry
5609	    catch /.*/
5610		let errcaught = 1
5611		call CHECK(13, 'E492', "Not an editor command",
5612		    \ line_before_error + 1)
5613	    endtry
5614	finally
5615	    if !errcaught && $VIMNOERRTHROW
5616		call CHECK(13)
5617	    endif
5618	    break		" discard error for $VIMNOERRTHROW
5619	endtry
5620    endwhile
5621    call CHECK(14)
5622
5623    Xpath 134217728				" X: 134217728
5624
5625    while 1
5626	try
5627	    let intcaught = 0
5628	    try
5629		try
5630		    throw "x9"
5631		finally
5632		    SetLineNumber two_lines_before_interrupt
5633		    "INTERRUPT
5634		endtry
5635	    catch /.*/
5636		let intcaught = 1
5637		call CHECK(15, "Vim:Interrupt", '',
5638		    \ two_lines_before_interrupt + 2)
5639	    endtry
5640	finally
5641	    if !intcaught && $VIMNOINTTHROW
5642		call CHECK(15)
5643	    endif
5644	    break		" discard interrupt for $VIMNOINTTHROW
5645	endtry
5646    endwhile
5647    call CHECK(16)
5648
5649    Xpath 268435456				" X: 268435456
5650
5651    while 1
5652	try
5653	    let errcaught = 0
5654	    try
5655		try
5656"		    if 1
5657			SetLineNumber line_before_throw
5658			throw "x10"
5659		    " missing endif
5660		finally
5661		    call CHECK(17)
5662		endtry
5663	    catch /.*/
5664		let errcaught = 1
5665		call CHECK(18, 'E171', "Missing :endif", line_before_throw + 3)
5666	    endtry
5667	finally
5668	    if !errcaught && $VIMNOERRTHROW
5669		call CHECK(18)
5670	    endif
5671	    break		" discard error for $VIMNOERRTHROW
5672	endtry
5673    endwhile
5674    call CHECK(19)
5675
5676    Xpath 536870912				" X: 536870912
5677
5678    while 1
5679	try
5680	    let errcaught = 0
5681	    try
5682		try
5683"		    if 1
5684			SetLineNumber line_before_throw
5685			throw "x11"
5686		    " missing endif
5687		endtry
5688	    catch /.*/
5689		let errcaught = 1
5690		call CHECK(20, 'E171', "Missing :endif", line_before_throw + 3)
5691	    endtry
5692	finally
5693	    if !errcaught && $VIMNOERRTHROW
5694		call CHECK(20)
5695	    endif
5696	    break		" discard error for $VIMNOERRTHROW
5697	endtry
5698    endwhile
5699    call CHECK(21)
5700
5701    Xpath 1073741824				" X: 1073741824
5702
5703endif
5704
5705Xcheck 2038431743
5706
5707
5708"-------------------------------------------------------------------------------
5709"
5710" Test 60:  (Re)throwing v:exception; :echoerr.				    {{{1
5711"
5712"	    A user exception can be rethrown after catching by throwing
5713"	    v:exception.  An error or interrupt exception cannot be rethrown
5714"	    because Vim exceptions cannot be faked.  A Vim exception using the
5715"	    value of v:exception can, however, be triggered by the :echoerr
5716"	    command.
5717"-------------------------------------------------------------------------------
5718
5719XpathINIT
5720
5721try
5722    try
5723	Xpath 1					" X: 1
5724	throw "oops"
5725    catch /oops/
5726	Xpath 2					" X: 2
5727	throw v:exception	" rethrow user exception
5728    catch /.*/
5729	Xpath 4					" X: 0
5730    endtry
5731catch /^oops$/			" catches rethrown user exception
5732    Xpath 8					" X: 8
5733catch /.*/
5734    Xpath 16					" X: 0
5735endtry
5736
5737function! F()
5738    try
5739	let caught = 0
5740	try
5741	    Xpath 32				" X: 32
5742	    write /n/o/n/w/r/i/t/a/b/l/e/_/f/i/l/e
5743	    Xpath 64				" X: 0
5744	    Xout "did_emsg was reset before executing " .
5745		\ "BufWritePost autocommands."
5746	catch /^Vim(write):/
5747	    let caught = 1
5748	    throw v:exception	" throw error: cannot fake Vim exception
5749	catch /.*/
5750	    Xpath 128				" X: 0
5751	finally
5752	    Xpath 256				" X: 256
5753	    if !caught && !$VIMNOERRTHROW
5754		Xpath 512			" X: 0
5755	    endif
5756	endtry
5757    catch /^Vim(throw):/	" catches throw error
5758	let caught = caught + 1
5759    catch /.*/
5760	Xpath 1024				" X: 0
5761    finally
5762	Xpath 2048				" X: 2048
5763	if caught != 2
5764	    if !caught && !$VIMNOERRTHROW
5765		Xpath 4096			" X: 0
5766	    elseif caught
5767		Xpath 8192			" X: 0
5768	    endif
5769	    return		| " discard error for $VIMNOERRTHROW
5770	endif
5771    endtry
5772endfunction
5773
5774call F()
5775delfunction F
5776
5777function! G()
5778    try
5779	let caught = 0
5780	try
5781	    Xpath 16384				" X: 16384
5782	    asdf
5783	catch /^Vim/		" catch error exception
5784	    let caught = 1
5785	    " Trigger Vim error exception with value specified after :echoerr
5786	    let value = substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
5787	    echoerr value
5788	catch /.*/
5789	    Xpath 32768				" X: 0
5790	finally
5791	    Xpath 65536				" X: 65536
5792	    if !caught
5793		if !$VIMNOERRTHROW
5794		    Xpath 131072		" X: 0
5795		else
5796		    let value = "Error"
5797		    echoerr value
5798		endif
5799	    endif
5800	endtry
5801    catch /^Vim(echoerr):/
5802	let caught = caught + 1
5803	if v:exception !~ value
5804	    Xpath 262144			" X: 0
5805	endif
5806    catch /.*/
5807	Xpath 524288				" X: 0
5808    finally
5809	Xpath 1048576				" X: 1048576
5810	if caught != 2
5811	    if !caught && !$VIMNOERRTHROW
5812		Xpath 2097152			" X: 0
5813	    elseif caught
5814		Xpath 4194304			" X: 0
5815	    endif
5816	    return		| " discard error for $VIMNOERRTHROW
5817	endif
5818    endtry
5819endfunction
5820
5821call G()
5822delfunction G
5823
5824unlet! value caught
5825
5826if ExtraVim()
5827    try
5828	let errcaught = 0
5829	try
5830	    Xpath 8388608			" X: 8388608
5831	    let intcaught = 0
5832	    "INTERRUPT
5833	catch /^Vim:/		" catch interrupt exception
5834	    let intcaught = 1
5835	    " Trigger Vim error exception with value specified after :echoerr
5836	    echoerr substitute(v:exception, '^Vim\((.*)\)\=:', '', "")
5837	catch /.*/
5838	    Xpath 16777216			" X: 0
5839	finally
5840	    Xpath 33554432			" X: 33554432
5841	    if !intcaught
5842		if !$VIMNOINTTHROW
5843		    Xpath 67108864		" X: 0
5844		else
5845		    echoerr "Interrupt"
5846		endif
5847	    endif
5848	endtry
5849    catch /^Vim(echoerr):/
5850	let errcaught = 1
5851	if v:exception !~ "Interrupt"
5852	    Xpath 134217728			" X: 0
5853	endif
5854    finally
5855	Xpath 268435456				" X: 268435456
5856	if !errcaught && !$VIMNOERRTHROW
5857	    Xpath 536870912			" X: 0
5858	endif
5859    endtry
5860endif
5861
5862Xcheck 311511339
5863
5864
5865"-------------------------------------------------------------------------------
5866" Test 61:  Catching interrupt exceptions				    {{{1
5867"
5868"	    When an interrupt occurs inside a :try/:endtry region, an
5869"	    interrupt exception is thrown and can be caught.  Its value is
5870"	    "Vim:Interrupt".  If the interrupt occurs after an error or a :throw
5871"	    but before a matching :catch is reached, all following :catches of
5872"	    that try block are ignored, but the interrupt exception can be
5873"	    caught by the next surrounding try conditional.  An interrupt is
5874"	    ignored when there is a previous interrupt that has not been caught
5875"	    or causes a :finally clause to be executed.
5876"-------------------------------------------------------------------------------
5877
5878XpathINIT
5879
5880if ExtraVim()
5881
5882    while 1
5883	try
5884	    try
5885		Xpath 1				" X: 1
5886		let caught = 0
5887		"INTERRUPT
5888		Xpath 2				" X: 0
5889	    catch /^Vim:Interrupt$/
5890		let caught = 1
5891	    finally
5892		Xpath 4				" X: 4
5893		if caught || $VIMNOINTTHROW
5894		    Xpath 8			" X: 8
5895		endif
5896	    endtry
5897	catch /.*/
5898	    Xpath 16				" X: 0
5899	    Xout v:exception "in" v:throwpoint
5900	finally
5901	    break		" discard interrupt for $VIMNOINTTHROW
5902	endtry
5903    endwhile
5904
5905    while 1
5906	try
5907	    try
5908		let caught = 0
5909		try
5910		    Xpath 32			" X: 32
5911		    asdf
5912		    Xpath 64			" X: 0
5913		catch /do_not_catch/
5914		    Xpath 128			" X: 0
5915		catch /.*/	"INTERRUPT - throw interrupt if !$VIMNOERRTHROW
5916		    Xpath 256			" X: 0
5917		catch /.*/
5918		    Xpath 512			" X: 0
5919		finally		"INTERRUPT - throw interrupt if $VIMNOERRTHROW
5920		    Xpath 1024			" X: 1024
5921		endtry
5922	    catch /^Vim:Interrupt$/
5923		let caught = 1
5924	    finally
5925		Xpath 2048			" X: 2048
5926		if caught || $VIMNOINTTHROW
5927		    Xpath 4096			" X: 4096
5928		endif
5929	    endtry
5930	catch /.*/
5931	    Xpath 8192				" X: 0
5932	    Xout v:exception "in" v:throwpoint
5933	finally
5934	    break		" discard interrupt for $VIMNOINTTHROW
5935	endtry
5936    endwhile
5937
5938    while 1
5939	try
5940	    try
5941		let caught = 0
5942		try
5943		    Xpath 16384			" X: 16384
5944		    throw "x"
5945		    Xpath 32768			" X: 0
5946		catch /do_not_catch/
5947		    Xpath 65536			" X: 0
5948		catch /x/	"INTERRUPT
5949		    Xpath 131072		" X: 0
5950		catch /.*/
5951		    Xpath 262144		" X: 0
5952		endtry
5953	    catch /^Vim:Interrupt$/
5954		let caught = 1
5955	    finally
5956		Xpath 524288			" X: 524288
5957		if caught || $VIMNOINTTHROW
5958		    Xpath 1048576		" X: 1048576
5959		endif
5960	    endtry
5961	catch /.*/
5962	    Xpath 2097152			" X: 0
5963	    Xout v:exception "in" v:throwpoint
5964	finally
5965	    break		" discard interrupt for $VIMNOINTTHROW
5966	endtry
5967    endwhile
5968
5969    while 1
5970	try
5971	    let caught = 0
5972	    try
5973		Xpath 4194304			" X: 4194304
5974		"INTERRUPT
5975		Xpath 8388608			" X: 0
5976	    catch /do_not_catch/ "INTERRUPT
5977		Xpath 16777216			" X: 0
5978	    catch /^Vim:Interrupt$/
5979		let caught = 1
5980	    finally
5981		Xpath 33554432			" X: 33554432
5982		if caught || $VIMNOINTTHROW
5983		    Xpath 67108864		" X: 67108864
5984		endif
5985	    endtry
5986	catch /.*/
5987	    Xpath 134217728			" X: 0
5988	    Xout v:exception "in" v:throwpoint
5989	finally
5990	    break		" discard interrupt for $VIMNOINTTHROW
5991	endtry
5992    endwhile
5993
5994    Xpath 268435456				" X: 268435456
5995
5996endif
5997
5998Xcheck 374889517
5999
6000
6001"-------------------------------------------------------------------------------
6002" Test 62:  Catching error exceptions					    {{{1
6003"
6004"	    An error inside a :try/:endtry region is converted to an exception
6005"	    and can be caught.  The error exception has a "Vim(cmdname):" prefix
6006"	    where cmdname is the name of the failing command, or a "Vim:" prefix
6007"	    if no command name is known.  The "Vim" prefixes cannot be faked.
6008"-------------------------------------------------------------------------------
6009
6010XpathINIT
6011
6012function! MSG(enr, emsg)
6013    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
6014    if a:enr == ""
6015	Xout "TODO: Add message number for:" a:emsg
6016	let v:errmsg = ":" . v:errmsg
6017    endif
6018    let match = 1
6019    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
6020	let match = 0
6021	if v:errmsg == ""
6022	    Xout "Message missing."
6023	else
6024	    let v:errmsg = escape(v:errmsg, '"')
6025	    Xout "Unexpected message:" v:errmsg
6026	endif
6027    endif
6028    return match
6029endfunction
6030
6031while 1
6032    try
6033	try
6034	    let caught = 0
6035	    unlet novar
6036	catch /^Vim(unlet):/
6037	    let caught = 1
6038	    let v:errmsg = substitute(v:exception, '^Vim(unlet):', '', "")
6039	finally
6040	    Xpath 1				" X: 1
6041	    if !caught && !$VIMNOERRTHROW
6042		Xpath 2				" X: 0
6043	    endif
6044	    if !MSG('E108', "No such variable")
6045		Xpath 4				" X: 0
6046	    endif
6047	endtry
6048    catch /.*/
6049	Xpath 8					" X: 0
6050	Xout v:exception "in" v:throwpoint
6051    finally
6052	break		" discard error for $VIMNOERRTHROW
6053    endtry
6054endwhile
6055
6056while 1
6057    try
6058	try
6059	    let caught = 0
6060	    throw novar			" error in :throw
6061	catch /^Vim(throw):/
6062	    let caught = 1
6063	    let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
6064	finally
6065	    Xpath 16				" X: 16
6066	    if !caught && !$VIMNOERRTHROW
6067		Xpath 32			" X: 0
6068	    endif
6069	    if caught ? !MSG('E121', "Undefined variable")
6070			\ : !MSG('E15', "Invalid expression")
6071		Xpath 64			" X: 0
6072	    endif
6073	endtry
6074    catch /.*/
6075	Xpath 128				" X: 0
6076	Xout v:exception "in" v:throwpoint
6077    finally
6078	break		" discard error for $VIMNOERRTHROW
6079    endtry
6080endwhile
6081
6082while 1
6083    try
6084	try
6085	    let caught = 0
6086	    throw "Vim:faked"		" error: cannot fake Vim exception
6087	catch /^Vim(throw):/
6088	    let caught = 1
6089	    let v:errmsg = substitute(v:exception, '^Vim(throw):', '', "")
6090	finally
6091	    Xpath 256				" X: 256
6092	    if !caught && !$VIMNOERRTHROW
6093		Xpath 512			" X: 0
6094	    endif
6095	    if !MSG('E608', "Cannot :throw exceptions with 'Vim' prefix")
6096		Xpath 1024			" X: 0
6097	    endif
6098	endtry
6099    catch /.*/
6100	Xpath 2048				" X: 0
6101	Xout v:exception "in" v:throwpoint
6102    finally
6103	break		" discard error for $VIMNOERRTHROW
6104    endtry
6105endwhile
6106
6107function! F()
6108    while 1
6109    " Missing :endwhile
6110endfunction
6111
6112while 1
6113    try
6114	try
6115	    let caught = 0
6116	    call F()
6117	catch /^Vim(endfunction):/
6118	    let caught = 1
6119	    let v:errmsg = substitute(v:exception, '^Vim(endfunction):', '', "")
6120	finally
6121	    Xpath 4096				" X: 4096
6122	    if !caught && !$VIMNOERRTHROW
6123		Xpath 8192			" X: 0
6124	    endif
6125	    if !MSG('E170', "Missing :endwhile")
6126		Xpath 16384			" X: 0
6127	    endif
6128	endtry
6129    catch /.*/
6130	Xpath 32768				" X: 0
6131	Xout v:exception "in" v:throwpoint
6132    finally
6133	break		" discard error for $VIMNOERRTHROW
6134    endtry
6135endwhile
6136
6137while 1
6138    try
6139	try
6140	    let caught = 0
6141	    ExecAsScript F
6142	catch /^Vim:/
6143	    let caught = 1
6144	    let v:errmsg = substitute(v:exception, '^Vim:', '', "")
6145	finally
6146	    Xpath 65536				" X: 65536
6147	    if !caught && !$VIMNOERRTHROW
6148		Xpath 131072			" X: 0
6149	    endif
6150	    if !MSG('E170', "Missing :endwhile")
6151		Xpath 262144			" X: 0
6152	    endif
6153	endtry
6154    catch /.*/
6155	Xpath 524288				" X: 0
6156	Xout v:exception "in" v:throwpoint
6157    finally
6158	break		" discard error for $VIMNOERRTHROW
6159    endtry
6160endwhile
6161
6162function! G()
6163    call G()
6164endfunction
6165
6166while 1
6167    try
6168	let mfd_save = &mfd
6169	set mfd=3
6170	try
6171	    let caught = 0
6172	    call G()
6173	catch /^Vim(call):/
6174	    let caught = 1
6175	    let v:errmsg = substitute(v:exception, '^Vim(call):', '', "")
6176	finally
6177	    Xpath 1048576			" X: 1048576
6178	    if !caught && !$VIMNOERRTHROW
6179		Xpath 2097152			" X: 0
6180	    endif
6181	    if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
6182		Xpath 4194304			" X: 0
6183	    endif
6184	endtry
6185    catch /.*/
6186	Xpath 8388608				" X: 0
6187	Xout v:exception "in" v:throwpoint
6188    finally
6189	let &mfd = mfd_save
6190	break		" discard error for $VIMNOERRTHROW
6191    endtry
6192endwhile
6193
6194function! H()
6195    return H()
6196endfunction
6197
6198while 1
6199    try
6200	let mfd_save = &mfd
6201	set mfd=3
6202	try
6203	    let caught = 0
6204	    call H()
6205	catch /^Vim(return):/
6206	    let caught = 1
6207	    let v:errmsg = substitute(v:exception, '^Vim(return):', '', "")
6208	finally
6209	    Xpath 16777216			" X: 16777216
6210	    if !caught && !$VIMNOERRTHROW
6211		Xpath 33554432			" X: 0
6212	    endif
6213	    if !MSG('E132', "Function call depth is higher than 'maxfuncdepth'")
6214		Xpath 67108864			" X: 0
6215	    endif
6216	endtry
6217    catch /.*/
6218	Xpath 134217728				" X: 0
6219	Xout v:exception "in" v:throwpoint
6220    finally
6221	let &mfd = mfd_save
6222	break		" discard error for $VIMNOERRTHROW
6223    endtry
6224endwhile
6225
6226unlet! caught mfd_save
6227delfunction F
6228delfunction G
6229delfunction H
6230Xpath 268435456					" X: 268435456
6231
6232Xcheck 286331153
6233
6234" Leave MSG() for the next test.
6235
6236
6237"-------------------------------------------------------------------------------
6238" Test 63:  Suppressing error exceptions by :silent!.			    {{{1
6239"
6240"	    A :silent! command inside a :try/:endtry region suppresses the
6241"	    conversion of errors to an exception and the immediate abortion on
6242"	    error.  When the commands executed by the :silent! themselves open
6243"	    a new :try/:endtry region, conversion of errors to exception and
6244"	    immediate abortion is switched on again - until the next :silent!
6245"	    etc.  The :silent! has the effect of setting v:errmsg to the error
6246"	    message text (without displaying it) and continuing with the next
6247"	    script line.
6248"
6249"	    When a command triggering autocommands is executed by :silent!
6250"	    inside a :try/:endtry, the autocommand execution is not suppressed
6251"	    on error.
6252"
6253"	    This test reuses the function MSG() from the previous test.
6254"-------------------------------------------------------------------------------
6255
6256XpathINIT
6257
6258XloopINIT! 1 4
6259
6260let taken = ""
6261
6262function! S(n) abort
6263    XloopNEXT
6264    let g:taken = g:taken . "E" . a:n
6265    let v:errmsg = ""
6266    exec "asdf" . a:n
6267
6268    " Check that ":silent!" continues:
6269    Xloop 1
6270
6271    " Check that ":silent!" sets "v:errmsg":
6272    if MSG('E492', "Not an editor command")
6273	Xloop 2
6274    endif
6275endfunction
6276
6277function! Foo()
6278    while 1
6279	try
6280	    try
6281		let caught = 0
6282		" This is not silent:
6283		call S(3)				" X: 0 * 16
6284	    catch /^Vim:/
6285		let caught = 1
6286		let errmsg3 = substitute(v:exception, '^Vim:', '', "")
6287		silent! call S(4)			" X: 3 * 64
6288	    finally
6289		if !caught
6290		    let errmsg3 = v:errmsg
6291		    " Do call S(4) here if not executed in :catch.
6292		    silent! call S(4)
6293		endif
6294		Xpath 1048576			" X: 1048576
6295		if !caught && !$VIMNOERRTHROW
6296		    Xpath 2097152		" X: 0
6297		endif
6298		let v:errmsg = errmsg3
6299		if !MSG('E492', "Not an editor command")
6300		    Xpath 4194304		" X: 0
6301		endif
6302		silent! call S(5)			" X: 3 * 256
6303		" Break out of try conditionals that cover ":silent!".  This also
6304		" discards the aborting error when $VIMNOERRTHROW is non-zero.
6305		break
6306	    endtry
6307	catch /.*/
6308	    Xpath 8388608			" X: 0
6309	    Xout v:exception "in" v:throwpoint
6310	endtry
6311    endwhile
6312    " This is a double ":silent!" (see caller).
6313    silent! call S(6)					" X: 3 * 1024
6314endfunction
6315
6316function! Bar()
6317    try
6318	silent! call S(2)				" X: 3 * 4
6319							" X: 3 * 4096
6320	silent! execute "call Foo() | call S(7)"
6321	silent! call S(8)				" X: 3 * 16384
6322    endtry	" normal end of try cond that covers ":silent!"
6323    " This has a ":silent!" from the caller:
6324    call S(9)						" X: 3 * 65536
6325endfunction
6326
6327silent! call S(1)					" X: 3 * 1
6328silent! call Bar()
6329silent! call S(10)					" X: 3 * 262144
6330
6331let expected = "E1E2E3E4E5E6E7E8E9E10"
6332if taken != expected
6333    Xpath 16777216				" X: 0
6334    Xout "'taken' is" taken "instead of" expected
6335endif
6336
6337augroup TMP
6338    autocmd BufWritePost * Xpath 33554432	" X: 33554432
6339augroup END
6340
6341Xpath 67108864					" X: 67108864
6342write /i/m/p/o/s/s/i/b/l/e
6343Xpath 134217728					" X: 134217728
6344
6345autocmd! TMP
6346unlet! caught errmsg3 taken expected
6347delfunction S
6348delfunction Foo
6349delfunction Bar
6350delfunction MSG
6351
6352Xcheck 236978127
6353
6354
6355"-------------------------------------------------------------------------------
6356" Test 64:  Error exceptions after error, interrupt or :throw		    {{{1
6357"
6358"	    When an error occurs after an interrupt or a :throw but before
6359"	    a matching :catch is reached, all following :catches of that try
6360"	    block are ignored, but the error exception can be caught by the next
6361"	    surrounding try conditional.  Any previous error exception is
6362"	    discarded.  An error is ignored when there is a previous error that
6363"	    has not been caught.
6364"-------------------------------------------------------------------------------
6365
6366XpathINIT
6367
6368if ExtraVim()
6369
6370    while 1
6371	try
6372	    try
6373		Xpath 1				" X: 1
6374		let caught = 0
6375		while 1
6376"		    if 1
6377		    " Missing :endif
6378		endwhile	" throw error exception
6379	    catch /^Vim(/
6380		let caught = 1
6381	    finally
6382		Xpath 2				" X: 2
6383		if caught || $VIMNOERRTHROW
6384		    Xpath 4			" X: 4
6385		endif
6386	    endtry
6387	catch /.*/
6388	    Xpath 8				" X: 0
6389	    Xout v:exception "in" v:throwpoint
6390	finally
6391	    break		" discard error for $VIMNOERRTHROW
6392	endtry
6393    endwhile
6394
6395    while 1
6396	try
6397	    try
6398		Xpath 16			" X: 16
6399		let caught = 0
6400		try
6401"		    if 1
6402		    " Missing :endif
6403		catch /.*/	" throw error exception
6404		    Xpath 32			" X: 0
6405		catch /.*/
6406		    Xpath 64			" X: 0
6407		endtry
6408	    catch /^Vim(/
6409		let caught = 1
6410	    finally
6411		Xpath 128			" X: 128
6412		if caught || $VIMNOERRTHROW
6413		    Xpath 256			" X: 256
6414		endif
6415	    endtry
6416	catch /.*/
6417	    Xpath 512				" X: 0
6418	    Xout v:exception "in" v:throwpoint
6419	finally
6420	    break		" discard error for $VIMNOERRTHROW
6421	endtry
6422    endwhile
6423
6424    while 1
6425	try
6426	    try
6427		let caught = 0
6428		try
6429		    Xpath 1024			" X: 1024
6430		    "INTERRUPT
6431		catch /do_not_catch/
6432		    Xpath 2048			" X: 0
6433"		    if 1
6434		    " Missing :endif
6435		catch /.*/	" throw error exception
6436		    Xpath 4096			" X: 0
6437		catch /.*/
6438		    Xpath 8192			" X: 0
6439		endtry
6440	    catch /^Vim(/
6441		let caught = 1
6442	    finally
6443		Xpath 16384			" X: 16384
6444		if caught || $VIMNOERRTHROW
6445		    Xpath 32768			" X: 32768
6446		endif
6447	    endtry
6448	catch /.*/
6449	    Xpath 65536				" X: 0
6450	    Xout v:exception "in" v:throwpoint
6451	finally
6452	    break		" discard error for $VIMNOERRTHROW
6453	endtry
6454    endwhile
6455
6456    while 1
6457	try
6458	    try
6459		let caught = 0
6460		try
6461		    Xpath 131072		" X: 131072
6462		    throw "x"
6463		catch /do_not_catch/
6464		    Xpath 262144		" X: 0
6465"		    if 1
6466		    " Missing :endif
6467		catch /x/	" throw error exception
6468		    Xpath 524288		" X: 0
6469		catch /.*/
6470		   Xpath 1048576		" X: 0
6471		endtry
6472	    catch /^Vim(/
6473		let caught = 1
6474	    finally
6475		Xpath 2097152			" X: 2097152
6476		if caught || $VIMNOERRTHROW
6477		    Xpath 4194304		" X: 4194304
6478		endif
6479	    endtry
6480	catch /.*/
6481	    Xpath 8388608			" X: 0
6482	    Xout v:exception "in" v:throwpoint
6483	finally
6484	    break		" discard error for $VIMNOERRTHROW
6485	endtry
6486    endwhile
6487
6488    while 1
6489	try
6490	    try
6491		let caught = 0
6492		Xpath 16777216			" X: 16777216
6493"		endif		" :endif without :if; throw error exception
6494"		if 1
6495		" Missing :endif
6496	    catch /do_not_catch/ " ignore new error
6497		Xpath 33554432			" X: 0
6498	    catch /^Vim(endif):/
6499		let caught = 1
6500	    catch /^Vim(/
6501		Xpath 67108864			" X: 0
6502	    finally
6503		Xpath 134217728			" X: 134217728
6504		if caught || $VIMNOERRTHROW
6505		    Xpath 268435456		" X: 268435456
6506		endif
6507	    endtry
6508	catch /.*/
6509	    Xpath 536870912			" X: 0
6510	    Xout v:exception "in" v:throwpoint
6511	finally
6512	    break		" discard error for $VIMNOERRTHROW
6513	endtry
6514    endwhile
6515
6516    Xpath 1073741824				" X: 1073741824
6517
6518endif
6519
6520Xcheck 1499645335
6521
6522
6523"-------------------------------------------------------------------------------
6524" Test 65:  Errors in the /pattern/ argument of a :catch		    {{{1
6525"
6526"	    On an error in the /pattern/ argument of a :catch, the :catch does
6527"	    not match.  Any following :catches of the same :try/:endtry don't
6528"	    match either.  Finally clauses are executed.
6529"-------------------------------------------------------------------------------
6530
6531XpathINIT
6532
6533function! MSG(enr, emsg)
6534    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
6535    if a:enr == ""
6536	Xout "TODO: Add message number for:" a:emsg
6537	let v:errmsg = ":" . v:errmsg
6538    endif
6539    let match = 1
6540    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
6541	let match = 0
6542	if v:errmsg == ""
6543	    Xout "Message missing."
6544	else
6545	    let v:errmsg = escape(v:errmsg, '"')
6546	    Xout "Unexpected message:" v:errmsg
6547	endif
6548    endif
6549    return match
6550endfunction
6551
6552try
6553    try
6554	Xpath 1					" X: 1
6555	throw "oops"
6556    catch /^oops$/
6557	Xpath 2					" X: 2
6558    catch /\)/		" not checked; exception has already been caught
6559	Xpath 4					" X: 0
6560    endtry
6561    Xpath 8					" X: 8
6562catch /.*/
6563    Xpath 16					" X: 0
6564    Xout v:exception "in" v:throwpoint
6565endtry
6566
6567function! F()
6568    try
6569	let caught = 0
6570	try
6571	    try
6572		Xpath 32			" X: 32
6573		throw "ab"
6574	    catch /abc/	" does not catch
6575		Xpath 64			" X: 0
6576	    catch /\)/	" error; discards exception
6577		Xpath 128			" X: 0
6578	    catch /.*/	" not checked
6579		Xpath 256			" X: 0
6580	    finally
6581		Xpath 512			" X: 512
6582	    endtry
6583	    Xpath 1024				" X: 0
6584	catch /^ab$/	" checked, but original exception is discarded
6585	    Xpath 2048				" X: 0
6586	catch /^Vim(catch):/
6587	    let caught = 1
6588	    let v:errmsg = substitute(v:exception, '^Vim(catch):', '', "")
6589	finally
6590	    Xpath 4096				" X: 4096
6591	    if !caught && !$VIMNOERRTHROW
6592		Xpath 8192			" X: 0
6593	    endif
6594	    if caught ? !MSG('E55', 'Unmatched \\)')
6595			\ : !MSG('E475', "Invalid argument")
6596		Xpath 16384			" X: 0
6597	    endif
6598	    if !caught
6599		return	| " discard error
6600	    endif
6601	endtry
6602    catch /.*/
6603	Xpath 32768				" X: 0
6604	Xout v:exception "in" v:throwpoint
6605    endtry
6606endfunction
6607
6608call F()
6609Xpath 65536					" X: 65536
6610
6611delfunction MSG
6612delfunction F
6613unlet! caught
6614
6615Xcheck 70187
6616
6617
6618"-------------------------------------------------------------------------------
6619" Test 66:  Stop range :call on error, interrupt, or :throw		    {{{1
6620"
6621"	    When a function which is multiply called for a range since it
6622"	    doesn't handle the range itself has an error in a command
6623"	    dynamically enclosed by :try/:endtry or gets an interrupt or
6624"	    executes a :throw, no more calls for the remaining lines in the
6625"	    range are made.  On an error in a command not dynamically enclosed
6626"	    by :try/:endtry, the function is executed again for the remaining
6627"	    lines in the range.
6628"-------------------------------------------------------------------------------
6629
6630XpathINIT
6631
6632if ExtraVim()
6633
6634    let file = tempname()
6635    exec "edit" file
6636
6637    insert
6638line 1
6639line 2
6640line 3
6641.
6642
6643    XloopINIT! 1 2
6644
6645    let taken = ""
6646    let expected = "G1EF1E(1)F1E(2)F1E(3)G2EF2E(1)G3IF3I(1)G4TF4T(1)G5AF5A(1)"
6647
6648    function! F(reason, n) abort
6649	let g:taken = g:taken . "F" . a:n .
6650	    \ substitute(a:reason, '\(\l\).*', '\u\1', "") .
6651	    \ "(" . line(".") . ")"
6652
6653	if a:reason == "error"
6654	    asdf
6655	elseif a:reason == "interrupt"
6656	    "INTERRUPT
6657	    let dummy = 0
6658	elseif a:reason == "throw"
6659	    throw "xyz"
6660	elseif a:reason == "aborting error"
6661	    XloopNEXT
6662	    if g:taken != g:expected
6663		Xloop 1				" X: 0
6664		Xout "'taken' is" g:taken "instead of" g:expected
6665	    endif
6666	    try
6667		bwipeout!
6668		call delete(file)
6669		asdf
6670	    endtry
6671	endif
6672    endfunction
6673
6674    function! G(reason, n)
6675	let g:taken = g:taken . "G" . a:n .
6676	    \ substitute(a:reason, '\(\l\).*', '\u\1', "")
6677	1,3call F(a:reason, a:n)
6678    endfunction
6679
6680    Xpath 8					" X: 8
6681    call G("error", 1)
6682    try
6683	Xpath 16				" X: 16
6684	try
6685	    call G("error", 2)
6686	    Xpath 32				" X: 0
6687	finally
6688	    Xpath 64				" X: 64
6689	    try
6690		call G("interrupt", 3)
6691		Xpath 128			" X: 0
6692	    finally
6693		Xpath 256			" X: 256
6694		try
6695		    call G("throw", 4)
6696		    Xpath 512			" X: 0
6697		endtry
6698	    endtry
6699	endtry
6700    catch /xyz/
6701	Xpath 1024				" X: 1024
6702    catch /.*/
6703	Xpath 2048				" X: 0
6704	Xout v:exception "in" ExtraVimThrowpoint()
6705    endtry
6706    Xpath 4096					" X: 4096
6707    call G("aborting error", 5)
6708    Xpath 8192					" X: 0
6709    Xout "'taken' is" taken "instead of" expected
6710
6711endif
6712
6713Xcheck 5464
6714
6715
6716"-------------------------------------------------------------------------------
6717" Test 67:  :throw across :call command					    {{{1
6718"
6719"	    On a call command, an exception might be thrown when evaluating the
6720"	    function name, during evaluation of the arguments, or when the
6721"	    function is being executed.  The exception can be caught by the
6722"	    caller.
6723"-------------------------------------------------------------------------------
6724
6725XpathINIT
6726
6727function! THROW(x, n)
6728    if a:n == 1
6729	Xpath 1						" X: 1
6730    elseif a:n == 2
6731	Xpath 2						" X: 2
6732    elseif a:n == 3
6733	Xpath 4						" X: 4
6734    endif
6735    throw a:x
6736endfunction
6737
6738function! NAME(x, n)
6739    if a:n == 1
6740	Xpath 8						" X: 0
6741    elseif a:n == 2
6742	Xpath 16					" X: 16
6743    elseif a:n == 3
6744	Xpath 32					" X: 32
6745    elseif a:n == 4
6746	Xpath 64					" X: 64
6747    endif
6748    return a:x
6749endfunction
6750
6751function! ARG(x, n)
6752    if a:n == 1
6753	Xpath 128					" X: 0
6754    elseif a:n == 2
6755	Xpath 256					" X: 0
6756    elseif a:n == 3
6757	Xpath 512					" X: 512
6758    elseif a:n == 4
6759	Xpath 1024					" X: 1024
6760    endif
6761    return a:x
6762endfunction
6763
6764function! F(x, n)
6765    if a:n == 2
6766	Xpath 2048					" X: 0
6767    elseif a:n == 4
6768	Xpath 4096					" X: 4096
6769    endif
6770endfunction
6771
6772while 1
6773    try
6774	let error = 0
6775	let v:errmsg = ""
6776
6777	while 1
6778	    try
6779		Xpath 8192				" X: 8192
6780		call {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
6781		Xpath 16384				" X: 0
6782	    catch /^name$/
6783		Xpath 32768				" X: 32768
6784	    catch /.*/
6785		let error = 1
6786		Xout "1:" v:exception "in" v:throwpoint
6787	    finally
6788		if !error && $VIMNOERRTHROW && v:errmsg != ""
6789		    let error = 1
6790		    Xout "1:" v:errmsg
6791		endif
6792		if error
6793		    Xpath 65536				" X: 0
6794		endif
6795		let error = 0
6796		let v:errmsg = ""
6797		break		" discard error for $VIMNOERRTHROW
6798	    endtry
6799	endwhile
6800
6801	while 1
6802	    try
6803		Xpath 131072				" X: 131072
6804		call {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
6805		Xpath 262144				" X: 0
6806	    catch /^arg$/
6807		Xpath 524288				" X: 524288
6808	    catch /.*/
6809		let error = 1
6810		Xout "2:" v:exception "in" v:throwpoint
6811	    finally
6812		if !error && $VIMNOERRTHROW && v:errmsg != ""
6813		    let error = 1
6814		    Xout "2:" v:errmsg
6815		endif
6816		if error
6817		    Xpath 1048576			" X: 0
6818		endif
6819		let error = 0
6820		let v:errmsg = ""
6821		break		" discard error for $VIMNOERRTHROW
6822	    endtry
6823	endwhile
6824
6825	while 1
6826	    try
6827		Xpath 2097152				" X: 2097152
6828		call {NAME("THROW", 3)}(ARG("call", 3), 3)
6829		Xpath 4194304				" X: 0
6830	    catch /^call$/
6831		Xpath 8388608				" X: 8388608
6832	    catch /^0$/	    " default return value
6833		Xpath 16777216				" X: 0
6834		Xout "3:" v:throwpoint
6835	    catch /.*/
6836		let error = 1
6837		Xout "3:" v:exception "in" v:throwpoint
6838	    finally
6839		if !error && $VIMNOERRTHROW && v:errmsg != ""
6840		    let error = 1
6841		    Xout "3:" v:errmsg
6842		endif
6843		if error
6844		    Xpath 33554432			" X: 0
6845		endif
6846		let error = 0
6847		let v:errmsg = ""
6848		break		" discard error for $VIMNOERRTHROW
6849	    endtry
6850	endwhile
6851
6852	while 1
6853	    try
6854		Xpath 67108864				" X: 67108864
6855		call {NAME("F", 4)}(ARG(4711, 4), 4)
6856		Xpath 134217728				" X: 134217728
6857	    catch /.*/
6858		let error = 1
6859		Xout "4:" v:exception "in" v:throwpoint
6860	    finally
6861		if !error && $VIMNOERRTHROW && v:errmsg != ""
6862		    let error = 1
6863		    Xout "4:" v:errmsg
6864		endif
6865		if error
6866		    Xpath 268435456			" X: 0
6867		endif
6868		let error = 0
6869		let v:errmsg = ""
6870		break		" discard error for $VIMNOERRTHROW
6871	    endtry
6872	endwhile
6873
6874    catch /^0$/	    " default return value
6875	Xpath 536870912					" X: 0
6876	Xout v:throwpoint
6877    catch /.*/
6878	let error = 1
6879	Xout v:exception "in" v:throwpoint
6880    finally
6881	if !error && $VIMNOERRTHROW && v:errmsg != ""
6882	    let error = 1
6883	    Xout v:errmsg
6884	endif
6885	if error
6886	    Xpath 1073741824				" X: 0
6887	endif
6888	break		" discard error for $VIMNOERRTHROW
6889    endtry
6890endwhile
6891
6892unlet error
6893delfunction F
6894
6895Xcheck 212514423
6896
6897" Leave THROW(), NAME(), and ARG() for the next test.
6898
6899
6900"-------------------------------------------------------------------------------
6901" Test 68:  :throw across function calls in expressions			    {{{1
6902"
6903"	    On a function call within an expression, an exception might be
6904"	    thrown when evaluating the function name, during evaluation of the
6905"	    arguments, or when the function is being executed.  The exception
6906"	    can be caught by the caller.
6907"
6908"	    This test reuses the functions THROW(), NAME(), and ARG() from the
6909"	    previous test.
6910"-------------------------------------------------------------------------------
6911
6912XpathINIT
6913
6914function! F(x, n)
6915    if a:n == 2
6916	Xpath 2048					" X: 0
6917    elseif a:n == 4
6918	Xpath 4096					" X: 4096
6919    endif
6920    return a:x
6921endfunction
6922
6923unlet! var1 var2 var3 var4
6924
6925while 1
6926    try
6927	let error = 0
6928	let v:errmsg = ""
6929
6930	while 1
6931	    try
6932		Xpath 8192				" X: 8192
6933		let var1 = {NAME(THROW("name", 1), 1)}(ARG(4711, 1), 1)
6934		Xpath 16384				" X: 0
6935	    catch /^name$/
6936		Xpath 32768				" X: 32768
6937	    catch /.*/
6938		let error = 1
6939		Xout "1:" v:exception "in" v:throwpoint
6940	    finally
6941		if !error && $VIMNOERRTHROW && v:errmsg != ""
6942		    let error = 1
6943		    Xout "1:" v:errmsg
6944		endif
6945		if error
6946		    Xpath 65536				" X: 0
6947		endif
6948		let error = 0
6949		let v:errmsg = ""
6950		break		" discard error for $VIMNOERRTHROW
6951	    endtry
6952	endwhile
6953
6954	while 1
6955	    try
6956		Xpath 131072				" X: 131072
6957		let var2 = {NAME("F", 2)}(ARG(THROW("arg", 2), 2), 2)
6958		Xpath 262144				" X: 0
6959	    catch /^arg$/
6960		Xpath 524288				" X: 524288
6961	    catch /.*/
6962		let error = 1
6963		Xout "2:" v:exception "in" v:throwpoint
6964	    finally
6965		if !error && $VIMNOERRTHROW && v:errmsg != ""
6966		    let error = 1
6967		    Xout "2:" v:errmsg
6968		endif
6969		if error
6970		    Xpath 1048576			" X: 0
6971		endif
6972		let error = 0
6973		let v:errmsg = ""
6974		break		" discard error for $VIMNOERRTHROW
6975	    endtry
6976	endwhile
6977
6978	while 1
6979	    try
6980		Xpath 2097152				" X: 2097152
6981		let var3 = {NAME("THROW", 3)}(ARG("call", 3), 3)
6982		Xpath 4194304				" X: 0
6983	    catch /^call$/
6984		Xpath 8388608				" X: 8388608
6985	    catch /^0$/	    " default return value
6986		Xpath 16777216				" X: 0
6987		Xout "3:" v:throwpoint
6988	    catch /.*/
6989		let error = 1
6990		Xout "3:" v:exception "in" v:throwpoint
6991	    finally
6992		if !error && $VIMNOERRTHROW && v:errmsg != ""
6993		    let error = 1
6994		    Xout "3:" v:errmsg
6995		endif
6996		if error
6997		    Xpath 33554432			" X: 0
6998		endif
6999		let error = 0
7000		let v:errmsg = ""
7001		break		" discard error for $VIMNOERRTHROW
7002	    endtry
7003	endwhile
7004
7005	while 1
7006	    try
7007		Xpath 67108864				" X: 67108864
7008		let var4 = {NAME("F", 4)}(ARG(4711, 4), 4)
7009		Xpath 134217728				" X: 134217728
7010	    catch /.*/
7011		let error = 1
7012		Xout "4:" v:exception "in" v:throwpoint
7013	    finally
7014		if !error && $VIMNOERRTHROW && v:errmsg != ""
7015		    let error = 1
7016		    Xout "4:" v:errmsg
7017		endif
7018		if error
7019		    Xpath 268435456			" X: 0
7020		endif
7021		let error = 0
7022		let v:errmsg = ""
7023		break		" discard error for $VIMNOERRTHROW
7024	    endtry
7025	endwhile
7026
7027    catch /^0$/	    " default return value
7028	Xpath 536870912					" X: 0
7029	Xout v:throwpoint
7030    catch /.*/
7031	let error = 1
7032	Xout v:exception "in" v:throwpoint
7033    finally
7034	if !error && $VIMNOERRTHROW && v:errmsg != ""
7035	    let error = 1
7036	    Xout v:errmsg
7037	endif
7038	if error
7039	    Xpath 1073741824				" X: 0
7040	endif
7041	break		" discard error for $VIMNOERRTHROW
7042    endtry
7043endwhile
7044
7045if exists("var1") || exists("var2") || exists("var3") ||
7046	    \ !exists("var4") || var4 != 4711
7047    " The Xpath command does not accept 2^31 (negative); add explicitly:
7048    let Xpath = Xpath + 2147483648			" X: 0
7049    if exists("var1")
7050	Xout "var1 =" var1
7051    endif
7052    if exists("var2")
7053	Xout "var2 =" var2
7054    endif
7055    if exists("var3")
7056	Xout "var3 =" var3
7057    endif
7058    if !exists("var4")
7059	Xout "var4 unset"
7060    elseif var4 != 4711
7061	Xout "var4 =" var4
7062    endif
7063endif
7064
7065unlet! error var1 var2 var3 var4
7066delfunction THROW
7067delfunction NAME
7068delfunction ARG
7069delfunction F
7070
7071Xcheck 212514423
7072
7073
7074"-------------------------------------------------------------------------------
7075" Test 69:  :throw across :if, :elseif, :while				    {{{1
7076"
7077"	    On an :if, :elseif, or :while command, an exception might be thrown
7078"	    during evaluation of the expression to test.  The exception can be
7079"	    caught by the script.
7080"-------------------------------------------------------------------------------
7081
7082XpathINIT
7083
7084XloopINIT! 1 2
7085
7086function! THROW(x)
7087    XloopNEXT
7088    Xloop 1					" X: 1 + 2 + 4
7089    throw a:x
7090endfunction
7091
7092try
7093
7094    try
7095	Xpath 8					" X: 8
7096	if 4711 == THROW("if") + 111
7097	    Xpath 16				" X: 0
7098	else
7099	    Xpath 32				" X: 0
7100	endif
7101	Xpath 64				" X: 0
7102    catch /^if$/
7103	Xpath 128				" X: 128
7104    catch /.*/
7105	Xpath 256				" X: 0
7106	Xout "if:" v:exception "in" v:throwpoint
7107    endtry
7108
7109    try
7110	Xpath 512				" X: 512
7111	if 4711 == 4 + 7 + 1 + 1
7112	    Xpath 1024				" X: 0
7113	elseif 4711 == THROW("elseif") + 222
7114	    Xpath 2048				" X: 0
7115	else
7116	    Xpath 4096				" X: 0
7117	endif
7118	Xpath 8192				" X: 0
7119    catch /^elseif$/
7120	Xpath 16384				" X: 16384
7121    catch /.*/
7122	Xpath 32768				" X: 0
7123	Xout "elseif:" v:exception "in" v:throwpoint
7124    endtry
7125
7126    try
7127	Xpath 65536				" X: 65536
7128	while 4711 == THROW("while") + 4711
7129	    Xpath 131072			" X: 0
7130	    break
7131	endwhile
7132	Xpath 262144				" X: 0
7133    catch /^while$/
7134	Xpath 524288				" X: 524288
7135    catch /.*/
7136	Xpath 1048576				" X: 0
7137	Xout "while:" v:exception "in" v:throwpoint
7138    endtry
7139
7140catch /^0$/	    " default return value
7141    Xpath 2097152				" X: 0
7142    Xout v:throwpoint
7143catch /.*/
7144    Xout v:exception "in" v:throwpoint
7145    Xpath 4194304				" X: 0
7146endtry
7147
7148Xpath 8388608					" X: 8388608
7149
7150delfunction THROW
7151
7152Xcheck 8995471
7153
7154
7155"-------------------------------------------------------------------------------
7156" Test 70:  :throw across :return or :throw				    {{{1
7157"
7158"	    On a :return or :throw command, an exception might be thrown during
7159"	    evaluation of the expression to return or throw, respectively.  The
7160"	    exception can be caught by the script.
7161"-------------------------------------------------------------------------------
7162
7163XpathINIT
7164
7165let taken = ""
7166
7167function! THROW(x, n)
7168    let g:taken = g:taken . "T" . a:n
7169    throw a:x
7170endfunction
7171
7172function! F(x, y, n)
7173    let g:taken = g:taken . "F" . a:n
7174    return a:x + THROW(a:y, a:n)
7175endfunction
7176
7177function! G(x, y, n)
7178    let g:taken = g:taken . "G" . a:n
7179    throw a:x . THROW(a:y, a:n)
7180    return a:x
7181endfunction
7182
7183try
7184    try
7185	Xpath 1					" X: 1
7186	call F(4711, "return", 1)
7187	Xpath 2					" X: 0
7188    catch /^return$/
7189	Xpath 4					" X: 4
7190    catch /.*/
7191	Xpath 8					" X: 0
7192	Xout "return:" v:exception "in" v:throwpoint
7193    endtry
7194
7195    try
7196	Xpath 16				" X: 16
7197	let var = F(4712, "return-var", 2)
7198	Xpath 32				" X: 0
7199    catch /^return-var$/
7200	Xpath 64				" X: 64
7201    catch /.*/
7202	Xpath 128				" X: 0
7203	Xout "return-var:" v:exception "in" v:throwpoint
7204    finally
7205	unlet! var
7206    endtry
7207
7208    try
7209	Xpath 256				" X: 256
7210	throw "except1" . THROW("throw1", 3)
7211	Xpath 512				" X: 0
7212    catch /^except1/
7213	Xpath 1024				" X: 0
7214    catch /^throw1$/
7215	Xpath 2048				" X: 2048
7216    catch /.*/
7217	Xpath 4096				" X: 0
7218	Xout "throw1:" v:exception "in" v:throwpoint
7219    endtry
7220
7221    try
7222	Xpath 8192				" X: 8192
7223	call G("except2", "throw2", 4)
7224	Xpath 16384				" X: 0
7225    catch /^except2/
7226	Xpath 32768				" X: 0
7227    catch /^throw2$/
7228	Xpath 65536				" X: 65536
7229    catch /.*/
7230	Xpath 131072				" X: 0
7231	Xout "throw2:" v:exception "in" v:throwpoint
7232    endtry
7233
7234    try
7235	Xpath 262144				" X: 262144
7236	let var = G("except3", "throw3", 5)
7237	Xpath 524288				" X: 0
7238    catch /^except3/
7239	Xpath 1048576				" X: 0
7240    catch /^throw3$/
7241	Xpath 2097152				" X: 2097152
7242    catch /.*/
7243	Xpath 4194304				" X: 0
7244	Xout "throw3:" v:exception "in" v:throwpoint
7245    finally
7246	unlet! var
7247    endtry
7248
7249    let expected = "F1T1F2T2T3G4T4G5T5"
7250    if taken != expected
7251	Xpath 8388608				" X: 0
7252	Xout "'taken' is" taken "instead of" expected
7253    endif
7254
7255catch /^0$/	    " default return value
7256    Xpath 16777216				" X: 0
7257    Xout v:throwpoint
7258catch /.*/
7259    Xpath 33554432				" X: 0
7260    Xout v:exception "in" v:throwpoint
7261endtry
7262
7263Xpath 67108864					" X: 67108864
7264
7265unlet taken expected
7266delfunction THROW
7267delfunction F
7268delfunction G
7269
7270Xcheck 69544277
7271
7272
7273"-------------------------------------------------------------------------------
7274" Test 71:  :throw across :echo variants and :execute			    {{{1
7275"
7276"	    On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
7277"	    exception might be thrown during evaluation of the arguments to
7278"	    be displayed or executed as a command, respectively.  Any following
7279"	    arguments are not evaluated, then.  The exception can be caught by
7280"	    the script.
7281"-------------------------------------------------------------------------------
7282
7283XpathINIT
7284
7285let taken = ""
7286
7287function! THROW(x, n)
7288    let g:taken = g:taken . "T" . a:n
7289    throw a:x
7290endfunction
7291
7292function! F(n)
7293    let g:taken = g:taken . "F" . a:n
7294    return "F" . a:n
7295endfunction
7296
7297try
7298    try
7299	Xpath 1					" X: 1
7300	echo "echo" . THROW("echo-except", 1) F(1)
7301	Xpath 2					" X: 0
7302    catch /^echo-except$/
7303	Xpath 4					" X: 4
7304    catch /.*/
7305	Xpath 8					" X: 0
7306	Xout "echo:" v:exception "in" v:throwpoint
7307    endtry
7308
7309    try
7310	Xpath 16				" X: 16
7311	echon "echon" . THROW("echon-except", 2) F(2)
7312	Xpath 32				" X: 0
7313    catch /^echon-except$/
7314	Xpath 64				" X: 64
7315    catch /.*/
7316	Xpath 128				" X: 0
7317	Xout "echon:" v:exception "in" v:throwpoint
7318    endtry
7319
7320    try
7321	Xpath 256				" X: 256
7322	echomsg "echomsg" . THROW("echomsg-except", 3) F(3)
7323	Xpath 512				" X: 0
7324    catch /^echomsg-except$/
7325	Xpath 1024				" X: 1024
7326    catch /.*/
7327	Xpath 2048				" X: 0
7328	Xout "echomsg:" v:exception "in" v:throwpoint
7329    endtry
7330
7331    try
7332	Xpath 4096				" X: 4096
7333	echoerr "echoerr" . THROW("echoerr-except", 4) F(4)
7334	Xpath 8192				" X: 0
7335    catch /^echoerr-except$/
7336	Xpath 16384				" X: 16384
7337    catch /Vim/
7338	Xpath 32768				" X: 0
7339    catch /echoerr/
7340	Xpath 65536				" X: 0
7341    catch /.*/
7342	Xpath 131072				" X: 0
7343	Xout "echoerr:" v:exception "in" v:throwpoint
7344    endtry
7345
7346    try
7347	Xpath 262144				" X: 262144
7348	execute "echo 'execute" . THROW("execute-except", 5) F(5) "'"
7349	Xpath 524288				" X: 0
7350    catch /^execute-except$/
7351	Xpath 1048576				" X: 1048576
7352    catch /.*/
7353	Xpath 2097152				" X: 0
7354	Xout "execute:" v:exception "in" v:throwpoint
7355    endtry
7356
7357    let expected = "T1T2T3T4T5"
7358    if taken != expected
7359	Xpath 4194304				" X: 0
7360	Xout "'taken' is" taken "instead of" expected
7361    endif
7362
7363catch /^0$/	    " default return value
7364    Xpath 8388608				" X: 0
7365    Xout v:throwpoint
7366catch /.*/
7367    Xpath 16777216				" X: 0
7368    Xout v:exception "in" v:throwpoint
7369endtry
7370
7371Xpath 33554432					" X: 33554432
7372
7373unlet taken expected
7374delfunction THROW
7375delfunction F
7376
7377Xcheck 34886997
7378
7379
7380"-------------------------------------------------------------------------------
7381" Test 72:  :throw across :let or :unlet				    {{{1
7382"
7383"	    On a :let command, an exception might be thrown during evaluation
7384"	    of the expression to assign.  On an :let or :unlet command, the
7385"	    evaluation of the name of the variable to be assigned or list or
7386"	    deleted, respectively, may throw an exception.  Any following
7387"	    arguments are not evaluated, then.  The exception can be caught by
7388"	    the script.
7389"-------------------------------------------------------------------------------
7390
7391XpathINIT
7392
7393let throwcount = 0
7394
7395function! THROW(x)
7396    let g:throwcount = g:throwcount + 1
7397    throw a:x
7398endfunction
7399
7400try
7401    try
7402	let $VAR = "old_value"
7403	Xpath 1					" X: 1
7404	let $VAR = "let(" . THROW("var") . ")"
7405	Xpath 2					" X: 0
7406    catch /^var$/
7407	Xpath 4					" X: 4
7408    finally
7409	if $VAR != "old_value"
7410	    Xpath 8				" X: 0
7411	endif
7412    endtry
7413
7414    try
7415	let @a = "old_value"
7416	Xpath 16				" X: 16
7417	let @a = "let(" . THROW("reg") . ")"
7418	Xpath 32				" X: 0
7419    catch /^reg$/
7420	try
7421	    Xpath 64				" X: 64
7422	    let @A = "let(" . THROW("REG") . ")"
7423	    Xpath 128				" X: 0
7424	catch /^REG$/
7425	    Xpath 256				" X: 256
7426	endtry
7427    finally
7428	if @a != "old_value"
7429	    Xpath 512				" X: 0
7430	endif
7431	if @A != "old_value"
7432	    Xpath 1024				" X: 0
7433	endif
7434    endtry
7435
7436    try
7437	let saved_gpath = &g:path
7438	let saved_lpath = &l:path
7439	Xpath 2048				" X: 2048
7440	let &path = "let(" . THROW("opt") . ")"
7441	Xpath 4096				" X: 0
7442    catch /^opt$/
7443	try
7444	    Xpath 8192				" X: 8192
7445	    let &g:path = "let(" . THROW("gopt") . ")"
7446	    Xpath 16384				" X: 0
7447	catch /^gopt$/
7448	    try
7449		Xpath 32768			" X: 32768
7450		let &l:path = "let(" . THROW("lopt") . ")"
7451		Xpath 65536			" X: 0
7452	    catch /^lopt$/
7453		Xpath 131072			" X: 131072
7454	    endtry
7455	endtry
7456    finally
7457	if &g:path != saved_gpath || &l:path != saved_lpath
7458	    Xpath 262144			" X: 0
7459	endif
7460	let &g:path = saved_gpath
7461	let &l:path = saved_lpath
7462    endtry
7463
7464    unlet! var1 var2 var3
7465
7466    try
7467	Xpath 524288				" X: 524288
7468	let var1 = "let(" . THROW("var1") . ")"
7469	Xpath 1048576				" X: 0
7470    catch /^var1$/
7471	Xpath 2097152				" X: 2097152
7472    finally
7473	if exists("var1")
7474	    Xpath 4194304			" X: 0
7475	endif
7476    endtry
7477
7478    try
7479	let var2 = "old_value"
7480	Xpath 8388608				" X: 8388608
7481	let var2 = "let(" . THROW("var2"). ")"
7482	Xpath 16777216				" X: 0
7483    catch /^var2$/
7484	Xpath 33554432				" X: 33554432
7485    finally
7486	if var2 != "old_value"
7487	    Xpath 67108864			" X: 0
7488	endif
7489    endtry
7490
7491    try
7492	Xpath 134217728				" X: 134217728
7493	let var{THROW("var3")} = 4711
7494	Xpath 268435456				" X: 0
7495    catch /^var3$/
7496	Xpath 536870912				" X: 536870912
7497    endtry
7498
7499    let addpath = ""
7500
7501    function ADDPATH(p)
7502	let g:addpath = g:addpath . a:p
7503    endfunction
7504
7505    try
7506	call ADDPATH("T1")
7507	let var{THROW("var4")} var{ADDPATH("T2")} | call ADDPATH("T3")
7508	call ADDPATH("T4")
7509    catch /^var4$/
7510	call ADDPATH("T5")
7511    endtry
7512
7513    try
7514	call ADDPATH("T6")
7515	unlet var{THROW("var5")} var{ADDPATH("T7")} | call ADDPATH("T8")
7516	call ADDPATH("T9")
7517    catch /^var5$/
7518	call ADDPATH("T10")
7519    endtry
7520
7521    if addpath != "T1T5T6T10" || throwcount != 11
7522	throw "addpath: " . addpath . ", throwcount: " . throwcount
7523    endif
7524
7525    Xpath 1073741824				" X: 1073741824
7526
7527catch /.*/
7528    " The Xpath command does not accept 2^31 (negative); add explicitly:
7529    let Xpath = Xpath + 2147483648		" X: 0
7530    Xout v:exception "in" v:throwpoint
7531endtry
7532
7533unlet! var1 var2 var3 addpath throwcount
7534delfunction THROW
7535
7536Xcheck 1789569365
7537
7538
7539"-------------------------------------------------------------------------------
7540" Test 73:  :throw across :function, :delfunction			    {{{1
7541"
7542"	    The :function and :delfunction commands may cause an expression
7543"	    specified in braces to be evaluated.  During evaluation, an
7544"	    exception might be thrown.  The exception can be caught by the
7545"	    script.
7546"-------------------------------------------------------------------------------
7547
7548XpathINIT
7549
7550let taken = ""
7551
7552function! THROW(x, n)
7553    let g:taken = g:taken . "T" . a:n
7554    throw a:x
7555endfunction
7556
7557function! EXPR(x, n)
7558    let g:taken = g:taken . "E" . a:n
7559    if a:n % 2 == 0
7560	call THROW(a:x, a:n)
7561    endif
7562    return 2 - a:n % 2
7563endfunction
7564
7565try
7566    try
7567	" Define function.
7568	Xpath 1					" X: 1
7569	function! F0()
7570	endfunction
7571	Xpath 2					" X: 2
7572	function! F{EXPR("function-def-ok", 1)}()
7573	endfunction
7574	Xpath 4					" X: 4
7575	function! F{EXPR("function-def", 2)}()
7576	endfunction
7577	Xpath 8					" X: 0
7578    catch /^function-def-ok$/
7579	Xpath 16				" X: 0
7580    catch /^function-def$/
7581	Xpath 32				" X: 32
7582    catch /.*/
7583	Xpath 64				" X: 0
7584	Xout "def:" v:exception "in" v:throwpoint
7585    endtry
7586
7587    try
7588	" List function.
7589	Xpath 128				" X: 128
7590	function F0
7591	Xpath 256				" X: 256
7592	function F{EXPR("function-lst-ok", 3)}
7593	Xpath 512				" X: 512
7594	function F{EXPR("function-lst", 4)}
7595	Xpath 1024				" X: 0
7596    catch /^function-lst-ok$/
7597	Xpath 2048				" X: 0
7598    catch /^function-lst$/
7599	Xpath 4096				" X: 4096
7600    catch /.*/
7601	Xpath 8192				" X: 0
7602	Xout "lst:" v:exception "in" v:throwpoint
7603    endtry
7604
7605    try
7606	" Delete function
7607	Xpath 16384				" X: 16384
7608	delfunction F0
7609	Xpath 32768				" X: 32768
7610	delfunction F{EXPR("function-del-ok", 5)}
7611	Xpath 65536				" X: 65536
7612	delfunction F{EXPR("function-del", 6)}
7613	Xpath 131072				" X: 0
7614    catch /^function-del-ok$/
7615	Xpath 262144				" X: 0
7616    catch /^function-del$/
7617	Xpath 524288				" X: 524288
7618    catch /.*/
7619	Xpath 1048576				" X: 0
7620	Xout "del:" v:exception "in" v:throwpoint
7621    endtry
7622
7623    let expected = "E1E2T2E3E4T4E5E6T6"
7624    if taken != expected
7625	Xpath 2097152				" X: 0
7626	Xout "'taken' is" taken "instead of" expected
7627    endif
7628
7629catch /.*/
7630    Xpath 4194304				" X: 0
7631    Xout v:exception "in" v:throwpoint
7632endtry
7633
7634Xpath 8388608					" X: 8388608
7635
7636unlet taken expected
7637delfunction THROW
7638delfunction EXPR
7639
7640Xcheck 9032615
7641
7642
7643"-------------------------------------------------------------------------------
7644" Test 74:  :throw across builtin functions and commands		    {{{1
7645"
7646"	    Some functions like exists(), searchpair() take expression
7647"	    arguments, other functions or commands like substitute() or
7648"	    :substitute cause an expression (specified in the regular
7649"	    expression) to be evaluated.  During evaluation an exception
7650"	    might be thrown.  The exception can be caught by the script.
7651"-------------------------------------------------------------------------------
7652
7653XpathINIT
7654
7655let taken = ""
7656
7657function! THROW(x, n)
7658    let g:taken = g:taken . "T" . a:n
7659    throw a:x
7660endfunction
7661
7662function! EXPR(x, n)
7663    let g:taken = g:taken . "E" . a:n
7664    call THROW(a:x . a:n, a:n)
7665    return "EXPR"
7666endfunction
7667
7668function! SKIP(x, n)
7669    let g:taken = g:taken . "S" . a:n . "(" . line(".")
7670    let theline = getline(".")
7671    if theline =~ "skip"
7672	let g:taken = g:taken . "s)"
7673	return 1
7674    elseif theline =~ "throw"
7675	let g:taken = g:taken . "t)"
7676	call THROW(a:x . a:n, a:n)
7677    else
7678	let g:taken = g:taken . ")"
7679	return 0
7680    endif
7681endfunction
7682
7683function! SUBST(x, n)
7684    let g:taken = g:taken . "U" . a:n . "(" . line(".")
7685    let theline = getline(".")
7686    if theline =~ "not"	    " SUBST() should not be called for this line
7687	let g:taken = g:taken . "n)"
7688	call THROW(a:x . a:n, a:n)
7689    elseif theline =~ "throw"
7690	let g:taken = g:taken . "t)"
7691	call THROW(a:x . a:n, a:n)
7692    else
7693	let g:taken = g:taken . ")"
7694	return "replaced"
7695    endif
7696endfunction
7697
7698try
7699    try
7700	Xpath 1					" X: 1
7701	let result = exists('*{EXPR("exists", 1)}')
7702	Xpath 2					" X: 0
7703    catch /^exists1$/
7704	Xpath 4					" X: 4
7705	try
7706	    let result = exists('{EXPR("exists", 2)}')
7707	    Xpath 8				" X: 0
7708	catch /^exists2$/
7709	    Xpath 16				" X: 16
7710	catch /.*/
7711	    Xpath 32				" X: 0
7712	    Xout "exists2:" v:exception "in" v:throwpoint
7713	endtry
7714    catch /.*/
7715	Xpath 64				" X: 0
7716	Xout "exists1:" v:exception "in" v:throwpoint
7717    endtry
7718
7719    try
7720	let file = tempname()
7721	exec "edit" file
7722	insert
7723begin
7724    xx
7725middle 3
7726    xx
7727middle 5 skip
7728    xx
7729middle 7 throw
7730    xx
7731end
7732.
7733	normal! gg
7734	Xpath 128				" X: 128
7735	let result =
7736	    \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 3)')
7737	Xpath 256				" X: 256
7738	let result =
7739	    \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 4)')
7740	Xpath 512				" X: 0
7741	let result =
7742	    \ searchpair("begin", "middle", "end", '', 'SKIP("searchpair", 5)')
7743	Xpath 1024				" X: 0
7744    catch /^searchpair[35]$/
7745	Xpath 2048				" X: 0
7746    catch /^searchpair4$/
7747	Xpath 4096				" X: 4096
7748    catch /.*/
7749	Xpath 8192				" X: 0
7750	Xout "searchpair:" v:exception "in" v:throwpoint
7751    finally
7752	bwipeout!
7753	call delete(file)
7754    endtry
7755
7756    try
7757	let file = tempname()
7758	exec "edit" file
7759	insert
7760subst 1
7761subst 2
7762not
7763subst 4
7764subst throw
7765subst 6
7766.
7767	normal! gg
7768	Xpath 16384				" X: 16384
7769	1,2substitute/subst/\=SUBST("substitute", 6)/
7770	try
7771	    Xpath 32768				" X: 32768
7772	    try
7773		let v:errmsg = ""
7774		3substitute/subst/\=SUBST("substitute", 7)/
7775	    finally
7776		if v:errmsg != ""
7777		    " If exceptions are not thrown on errors, fake the error
7778		    " exception in order to get the same execution path.
7779		    throw "faked Vim(substitute)"
7780		endif
7781	    endtry
7782	catch /Vim(substitute)/	    " Pattern not found ('e' flag missing)
7783	    Xpath 65536				" X: 65536
7784	    3substitute/subst/\=SUBST("substitute", 8)/e
7785	    Xpath 131072			" X: 131072
7786	endtry
7787	Xpath 262144				" X: 262144
7788	4,6substitute/subst/\=SUBST("substitute", 9)/
7789	Xpath 524288				" X: 0
7790    catch /^substitute[678]/
7791	Xpath 1048576				" X: 0
7792    catch /^substitute9/
7793	Xpath 2097152				" X: 2097152
7794    finally
7795	bwipeout!
7796	call delete(file)
7797    endtry
7798
7799    try
7800	Xpath 4194304				" X: 4194304
7801	let var = substitute("sub", "sub", '\=THROW("substitute()y", 10)', '')
7802	Xpath 8388608				" X: 0
7803    catch /substitute()y/
7804	Xpath 16777216				" X: 16777216
7805    catch /.*/
7806	Xpath 33554432				" X: 0
7807	Xout "substitute()y:" v:exception "in" v:throwpoint
7808    endtry
7809
7810    try
7811	Xpath 67108864				" X: 67108864
7812	let var = substitute("not", "sub", '\=THROW("substitute()n", 11)', '')
7813	Xpath 134217728				" X: 134217728
7814    catch /substitute()n/
7815	Xpath 268435456				" X: 0
7816    catch /.*/
7817	Xpath 536870912				" X: 0
7818	Xout "substitute()n:" v:exception "in" v:throwpoint
7819    endtry
7820
7821    let expected = "E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10"
7822    if taken != expected
7823	Xpath 1073741824			" X: 0
7824	Xout "'taken' is" taken "instead of" expected
7825    endif
7826
7827catch /.*/
7828    " The Xpath command does not accept 2^31 (negative); add explicitly:
7829    let Xpath = Xpath + 2147483648		" X: 0
7830    Xout v:exception "in" v:throwpoint
7831endtry
7832
7833unlet result var taken expected
7834delfunction THROW
7835delfunction EXPR
7836delfunction SKIP
7837delfunction SUBST
7838
7839Xcheck 224907669
7840
7841
7842"-------------------------------------------------------------------------------
7843" Test 75:  Errors in builtin functions.				    {{{1
7844"
7845"	    On an error in a builtin function called inside a :try/:endtry
7846"	    region, the evaluation of the expression calling that function and
7847"	    the command containing that expression are abandoned.  The error can
7848"	    be caught as an exception.
7849"
7850"	    A simple :call of the builtin function is a trivial case.  If the
7851"	    builtin function is called in the argument list of another function,
7852"	    no further arguments are evaluated, and the other function is not
7853"	    executed.  If the builtin function is called from the argument of
7854"	    a :return command, the :return command is not executed.  If the
7855"	    builtin function is called from the argument of a :throw command,
7856"	    the :throw command is not executed.  The evaluation of the
7857"	    expression calling the builtin function is abandoned.
7858"-------------------------------------------------------------------------------
7859
7860XpathINIT
7861
7862function! F1(arg1)
7863    Xpath 1					" X: 0
7864endfunction
7865
7866function! F2(arg1, arg2)
7867    Xpath 2					" X: 0
7868endfunction
7869
7870function! G()
7871    Xpath 4					" X: 0
7872endfunction
7873
7874function! H()
7875    Xpath 8					" X: 0
7876endfunction
7877
7878function! R()
7879    while 1
7880	try
7881	    let caught = 0
7882	    let v:errmsg = ""
7883	    Xpath 16				" X: 16
7884	    return append(1, "s")
7885	catch /E21/
7886	    let caught = 1
7887	catch /.*/
7888	    Xpath 32				" X: 0
7889	finally
7890	    Xpath 64				" X: 64
7891	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7892		Xpath 128			" X: 128
7893	    endif
7894	    break		" discard error for $VIMNOERRTHROW
7895	endtry
7896    endwhile
7897    Xpath 256					" X: 256
7898endfunction
7899
7900try
7901    set noma	" let append() fail with "E21"
7902
7903    while 1
7904	try
7905	    let caught = 0
7906	    let v:errmsg = ""
7907	    Xpath 512				" X: 512
7908	    call append(1, "s")
7909	catch /E21/
7910	    let caught = 1
7911	catch /.*/
7912	    Xpath 1024				" X: 0
7913	finally
7914	    Xpath 2048				" X: 2048
7915	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7916		Xpath 4096			" X: 4096
7917	    endif
7918	    break		" discard error for $VIMNOERRTHROW
7919	endtry
7920    endwhile
7921
7922    while 1
7923	try
7924	    let caught = 0
7925	    let v:errmsg = ""
7926	    Xpath 8192				" X: 8192
7927	    call F1('x' . append(1, "s"))
7928	catch /E21/
7929	    let caught = 1
7930	catch /.*/
7931	    Xpath 16384				" X: 0
7932	finally
7933	    Xpath 32768				" X: 32768
7934	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7935		Xpath 65536			" X: 65536
7936	    endif
7937	    break		" discard error for $VIMNOERRTHROW
7938	endtry
7939    endwhile
7940
7941    while 1
7942	try
7943	    let caught = 0
7944	    let v:errmsg = ""
7945	    Xpath 131072			" X: 131072
7946	    call F2('x' . append(1, "s"), G())
7947	catch /E21/
7948	    let caught = 1
7949	catch /.*/
7950	    Xpath 262144			" X: 0
7951	finally
7952	    Xpath 524288			" X: 524288
7953	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7954		Xpath 1048576			" X: 1048576
7955	    endif
7956	    break		" discard error for $VIMNOERRTHROW
7957	endtry
7958    endwhile
7959
7960    call R()
7961
7962    while 1
7963	try
7964	    let caught = 0
7965	    let v:errmsg = ""
7966	    Xpath 2097152			" X: 2097152
7967	    throw "T" . append(1, "s")
7968	catch /E21/
7969	    let caught = 1
7970	catch /^T.*/
7971	    Xpath 4194304			" X: 0
7972	catch /.*/
7973	    Xpath 8388608			" X: 0
7974	finally
7975	    Xpath 16777216			" X: 16777216
7976	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7977		Xpath 33554432			" X: 33554432
7978	    endif
7979	    break		" discard error for $VIMNOERRTHROW
7980	endtry
7981    endwhile
7982
7983    while 1
7984	try
7985	    let caught = 0
7986	    let v:errmsg = ""
7987	    Xpath 67108864			" X: 67108864
7988	    let x = "a"
7989	    let x = x . "b" . append(1, "s") . H()
7990	catch /E21/
7991	    let caught = 1
7992	catch /.*/
7993	    Xpath 134217728			" X: 0
7994	finally
7995	    Xpath 268435456			" X: 268435456
7996	    if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
7997		Xpath 536870912			" X: 536870912
7998	    endif
7999	    if x == "a"
8000		Xpath 1073741824		" X: 1073741824
8001	    endif
8002	    break		" discard error for $VIMNOERRTHROW
8003	endtry
8004    endwhile
8005catch /.*/
8006    " The Xpath command does not accept 2^31 (negative); add explicitly:
8007    let Xpath = Xpath + 2147483648		" X: 0
8008    Xout v:exception "in" v:throwpoint
8009finally
8010    set ma&
8011endtry
8012
8013unlet! caught x
8014delfunction F1
8015delfunction F2
8016delfunction G
8017delfunction H
8018delfunction R
8019
8020Xcheck 2000403408
8021
8022
8023"-------------------------------------------------------------------------------
8024" Test 76:  Errors, interrupts, :throw during expression evaluation	    {{{1
8025"
8026"	    When a function call made during expression evaluation is aborted
8027"	    due to an error inside a :try/:endtry region or due to an interrupt
8028"	    or a :throw, the expression evaluation is aborted as well.	No
8029"	    message is displayed for the cancelled expression evaluation.  On an
8030"	    error not inside :try/:endtry, the expression evaluation continues.
8031"-------------------------------------------------------------------------------
8032
8033XpathINIT
8034
8035if ExtraVim()
8036
8037    let taken = ""
8038
8039    function! ERR(n)
8040	let g:taken = g:taken . "E" . a:n
8041	asdf
8042    endfunction
8043
8044    function! ERRabort(n) abort
8045	let g:taken = g:taken . "A" . a:n
8046	asdf
8047    endfunction	" returns -1; may cause follow-up msg for illegal var/func name
8048
8049    function! WRAP(n, arg)
8050	let g:taken = g:taken . "W" . a:n
8051	let g:saved_errmsg = v:errmsg
8052	return arg
8053    endfunction
8054
8055    function! INT(n)
8056	let g:taken = g:taken . "I" . a:n
8057	"INTERRUPT9
8058	let dummy = 0
8059    endfunction
8060
8061    function! THR(n)
8062	let g:taken = g:taken . "T" . a:n
8063	throw "should not be caught"
8064    endfunction
8065
8066    function! CONT(n)
8067	let g:taken = g:taken . "C" . a:n
8068    endfunction
8069
8070    function! MSG(n)
8071	let g:taken = g:taken . "M" . a:n
8072	let errmsg = (a:n >= 37 && a:n <= 44) ? g:saved_errmsg : v:errmsg
8073	let msgptn = (a:n >= 10 && a:n <= 27) ? "^$" : "asdf"
8074	if errmsg !~ msgptn
8075	    let g:taken = g:taken . "x"
8076	    Xout "Expr" a:n.": Unexpected message:" v:errmsg
8077	endif
8078	let v:errmsg = ""
8079	let g:saved_errmsg = ""
8080    endfunction
8081
8082    let v:errmsg = ""
8083
8084    try
8085	let t = 1
8086	XloopINIT 1 2
8087	while t <= 9
8088	    Xloop 1				" X: 511
8089	    try
8090		if t == 1
8091		    let v{ERR(t) + CONT(t)} = 0
8092		elseif t == 2
8093		    let v{ERR(t) + CONT(t)}
8094		elseif t == 3
8095		    let var = exists('v{ERR(t) + CONT(t)}')
8096		elseif t == 4
8097		    unlet v{ERR(t) + CONT(t)}
8098		elseif t == 5
8099		    function F{ERR(t) + CONT(t)}()
8100		    endfunction
8101		elseif t == 6
8102		    function F{ERR(t) + CONT(t)}
8103		elseif t == 7
8104		    let var = exists('*F{ERR(t) + CONT(t)}')
8105		elseif t == 8
8106		    delfunction F{ERR(t) + CONT(t)}
8107		elseif t == 9
8108		    let var = ERR(t) + CONT(t)
8109		endif
8110	    catch /asdf/
8111		" v:errmsg is not set when the error message is converted to an
8112		" exception.  Set it to the original error message.
8113		let v:errmsg = substitute(v:exception, '^Vim:', '', "")
8114	    catch /^Vim\((\a\+)\)\=:/
8115		" An error exception has been thrown after the original error.
8116		let v:errmsg = ""
8117	    finally
8118		call MSG(t)
8119		let t = t + 1
8120		XloopNEXT
8121		continue	" discard an aborting error
8122	    endtry
8123	endwhile
8124    catch /.*/
8125	Xpath 512				" X: 0
8126	Xout v:exception "in" ExtraVimThrowpoint()
8127    endtry
8128
8129    try
8130	let t = 10
8131	XloopINIT 1024 2
8132	while t <= 18
8133	    Xloop 1				" X: 1024 * 511
8134	    try
8135		if t == 10
8136		    let v{INT(t) + CONT(t)} = 0
8137		elseif t == 11
8138		    let v{INT(t) + CONT(t)}
8139		elseif t == 12
8140		    let var = exists('v{INT(t) + CONT(t)}')
8141		elseif t == 13
8142		    unlet v{INT(t) + CONT(t)}
8143		elseif t == 14
8144		    function F{INT(t) + CONT(t)}()
8145		    endfunction
8146		elseif t == 15
8147		    function F{INT(t) + CONT(t)}
8148		elseif t == 16
8149		    let var = exists('*F{INT(t) + CONT(t)}')
8150		elseif t == 17
8151		    delfunction F{INT(t) + CONT(t)}
8152		elseif t == 18
8153		    let var = INT(t) + CONT(t)
8154		endif
8155	    catch /^Vim\((\a\+)\)\=:\(Interrupt\)\@!/
8156		" An error exception has been triggered after the interrupt.
8157		let v:errmsg = substitute(v:exception,
8158		    \ '^Vim\((\a\+)\)\=:', '', "")
8159	    finally
8160		call MSG(t)
8161		let t = t + 1
8162		XloopNEXT
8163		continue	" discard interrupt
8164	    endtry
8165	endwhile
8166    catch /.*/
8167	Xpath 524288				" X: 0
8168	Xout v:exception "in" ExtraVimThrowpoint()
8169    endtry
8170
8171    try
8172	let t = 19
8173	XloopINIT 1048576 2
8174	while t <= 27
8175	    Xloop 1				" X: 1048576 * 511
8176	    try
8177		if t == 19
8178		    let v{THR(t) + CONT(t)} = 0
8179		elseif t == 20
8180		    let v{THR(t) + CONT(t)}
8181		elseif t == 21
8182		    let var = exists('v{THR(t) + CONT(t)}')
8183		elseif t == 22
8184		    unlet v{THR(t) + CONT(t)}
8185		elseif t == 23
8186		    function F{THR(t) + CONT(t)}()
8187		    endfunction
8188		elseif t == 24
8189		    function F{THR(t) + CONT(t)}
8190		elseif t == 25
8191		    let var = exists('*F{THR(t) + CONT(t)}')
8192		elseif t == 26
8193		    delfunction F{THR(t) + CONT(t)}
8194		elseif t == 27
8195		    let var = THR(t) + CONT(t)
8196		endif
8197	    catch /^Vim\((\a\+)\)\=:/
8198		" An error exception has been triggered after the :throw.
8199		let v:errmsg = substitute(v:exception,
8200		    \ '^Vim\((\a\+)\)\=:', '', "")
8201	    finally
8202		call MSG(t)
8203		let t = t + 1
8204		XloopNEXT
8205		continue	" discard exception
8206	    endtry
8207	endwhile
8208    catch /.*/
8209	Xpath 536870912				" X: 0
8210	Xout v:exception "in" ExtraVimThrowpoint()
8211    endtry
8212
8213    let v{ERR(28) + CONT(28)} = 0
8214    call MSG(28)
8215    let v{ERR(29) + CONT(29)}
8216    call MSG(29)
8217    let var = exists('v{ERR(30) + CONT(30)}')
8218    call MSG(30)
8219    unlet v{ERR(31) + CONT(31)}
8220    call MSG(31)
8221    function F{ERR(32) + CONT(32)}()
8222    endfunction
8223    call MSG(32)
8224    function F{ERR(33) + CONT(33)}
8225    call MSG(33)
8226    let var = exists('*F{ERR(34) + CONT(34)}')
8227    call MSG(34)
8228    delfunction F{ERR(35) + CONT(35)}
8229    call MSG(35)
8230    let var = ERR(36) + CONT(36)
8231    call MSG(36)
8232
8233    let saved_errmsg = ""
8234
8235    let v{WRAP(37, ERRabort(37)) + CONT(37)} = 0
8236    call MSG(37)
8237    let v{WRAP(38, ERRabort(38)) + CONT(38)}
8238    call MSG(38)
8239    let var = exists('v{WRAP(39, ERRabort(39)) + CONT(39)}')
8240    call MSG(39)
8241    unlet v{WRAP(40, ERRabort(40)) + CONT(40)}
8242    call MSG(40)
8243    function F{WRAP(41, ERRabort(41)) + CONT(41)}()
8244    endfunction
8245    call MSG(41)
8246    function F{WRAP(42, ERRabort(42)) + CONT(42)}
8247    call MSG(42)
8248    let var = exists('*F{WRAP(43, ERRabort(43)) + CONT(43)}')
8249    call MSG(43)
8250    delfunction F{WRAP(44, ERRabort(44)) + CONT(44)}
8251    call MSG(44)
8252    let var = ERRabort(45) + CONT(45)
8253    call MSG(45)
8254
8255    Xpath 1073741824				" X: 1073741824
8256
8257    let expected = ""
8258	\ . "E1M1E2M2E3M3E4M4E5M5E6M6E7M7E8M8E9M9"
8259	\ . "I10M10I11M11I12M12I13M13I14M14I15M15I16M16I17M17I18M18"
8260	\ . "T19M19T20M20T21M21T22M22T23M23T24M24T25M25T26M26T27M27"
8261	\ . "E28C28M28E29C29M29E30C30M30E31C31M31E32C32M32E33C33M33"
8262	\ . "E34C34M34E35C35M35E36C36M36"
8263	\ . "A37W37C37M37A38W38C38M38A39W39C39M39A40W40C40M40A41W41C41M41"
8264	\ . "A42W42C42M42A43W43C43M43A44W44C44M44A45C45M45"
8265
8266    if taken != expected
8267	" The Xpath command does not accept 2^31 (negative); display explicitly:
8268	exec "!echo 2147483648 >>" . g:ExtraVimResult
8269						" X: 0
8270	Xout "'taken' is" taken "instead of" expected
8271	if substitute(taken,
8272	\ '\(.*\)E3C3M3x\(.*\)E30C30M30x\(.*\)A39C39M39x\(.*\)',
8273	\ '\1E3M3\2E30C30M30\3A39C39M39\4',
8274	\ "") == expected
8275	    Xout "Is ++emsg_skip for var with expr_start non-NULL"
8276		\ "in f_exists ok?"
8277	endif
8278    endif
8279
8280    unlet! v var saved_errmsg taken expected
8281    call delete(WA_t5)
8282    call delete(WA_t14)
8283    call delete(WA_t23)
8284    unlet! WA_t5 WA_t14 WA_t23
8285    delfunction WA_t5
8286    delfunction WA_t14
8287    delfunction WA_t23
8288
8289endif
8290
8291Xcheck 1610087935
8292
8293
8294"-------------------------------------------------------------------------------
8295" Test 77:  Errors, interrupts, :throw in name{brace-expression}	    {{{1
8296"
8297"	    When a function call made during evaluation of an expression in
8298"	    braces as part of a function name after ":function" is aborted due
8299"	    to an error inside a :try/:endtry region or due to an interrupt or
8300"	    a :throw, the expression evaluation is aborted as well, and the
8301"	    function definition is ignored, skipping all commands to the
8302"	    ":endfunction".  On an error not inside :try/:endtry, the expression
8303"	    evaluation continues and the function gets defined, and can be
8304"	    called and deleted.
8305"-------------------------------------------------------------------------------
8306
8307XpathINIT
8308
8309XloopINIT 1 4
8310
8311function! ERR() abort
8312    Xloop 1					" X: 1 + 4 + 16 + 64
8313    asdf
8314endfunction		" returns -1
8315
8316function! OK()
8317    Xloop 2					" X: 2 * (1 + 4 + 16)
8318    let v:errmsg = ""
8319    return 0
8320endfunction
8321
8322let v:errmsg = ""
8323
8324Xpath 4096					" X: 4096
8325function! F{1 + ERR() + OK()}(arg)
8326    " F0 should be defined.
8327    if exists("a:arg") && a:arg == "calling"
8328	Xpath 8192				" X: 8192
8329    else
8330	Xpath 16384				" X: 0
8331    endif
8332endfunction
8333if v:errmsg != ""
8334    Xpath 32768					" X: 0
8335endif
8336XloopNEXT
8337
8338Xpath 65536					" X: 65536
8339call F{1 + ERR() + OK()}("calling")
8340if v:errmsg != ""
8341    Xpath 131072				" X: 0
8342endif
8343XloopNEXT
8344
8345Xpath 262144					" X: 262144
8346delfunction F{1 + ERR() + OK()}
8347if v:errmsg != ""
8348    Xpath 524288				" X: 0
8349endif
8350XloopNEXT
8351
8352try
8353    while 1
8354	let caught = 0
8355	try
8356	    Xpath 1048576			" X: 1048576
8357	    function! G{1 + ERR() + OK()}(arg)
8358		" G0 should not be defined, and the function body should be
8359		" skipped.
8360		if exists("a:arg") && a:arg == "calling"
8361		    Xpath 2097152		" X: 0
8362		else
8363		    Xpath 4194304		" X: 0
8364		endif
8365		" Use an unmatched ":finally" to check whether the body is
8366		" skipped when an error occurs in ERR().  This works whether or
8367		" not the exception is converted to an exception.
8368		finally
8369		    Xpath 8388608		" X: 0
8370		    Xout "Body of G{1 + ERR() + OK()}() not skipped"
8371		    " Discard the aborting error or exception, and break the
8372		    " while loop.
8373		    break
8374		" End the try conditional and start a new one to avoid
8375		" ":catch after :finally" errors.
8376		endtry
8377		try
8378		Xpath 16777216			" X: 0
8379	    endfunction
8380
8381	    " When the function was not defined, this won't be reached - whether
8382	    " the body was skipped or not.  When the function was defined, it
8383	    " can be called and deleted here.
8384	    Xpath 33554432			" X: 0
8385	    Xout "G0() has been defined"
8386	    XloopNEXT
8387	    try
8388		call G{1 + ERR() + OK()}("calling")
8389	    catch /.*/
8390		Xpath 67108864			" X: 0
8391	    endtry
8392	    Xpath 134217728			" X: 0
8393	    XloopNEXT
8394	    try
8395		delfunction G{1 + ERR() + OK()}
8396	    catch /.*/
8397		Xpath 268435456			" X: 0
8398	    endtry
8399	catch /asdf/
8400	    " Jumped to when the function is not defined and the body is
8401	    " skipped.
8402	    let caught = 1
8403	catch /.*/
8404	    Xpath 536870912			" X: 0
8405	finally
8406	    if !caught && !$VIMNOERRTHROW
8407		Xpath 1073741824		" X: 0
8408	    endif
8409	    break		" discard error for $VIMNOERRTHROW
8410	endtry			" jumped to when the body is not skipped
8411    endwhile
8412catch /.*/
8413    " The Xpath command does not accept 2^31 (negative); add explicitly:
8414    let Xpath = Xpath + 2147483648		" X: 0
8415    Xout "Body of G{1 + ERR() + OK()}() not skipped, exception caught"
8416    Xout v:exception "in" v:throwpoint
8417endtry
8418
8419Xcheck 1388671
8420
8421
8422"-------------------------------------------------------------------------------
8423" Test 78:  Messages on parsing errors in expression evaluation		    {{{1
8424"
8425"	    When an expression evaluation detects a parsing error, an error
8426"	    message is given and converted to an exception, and the expression
8427"	    evaluation is aborted.
8428"-------------------------------------------------------------------------------
8429
8430XpathINIT
8431
8432if ExtraVim()
8433
8434    let taken = ""
8435
8436    function! F(n)
8437	let g:taken = g:taken . "F" . a:n
8438    endfunction
8439
8440    function! MSG(n, enr, emsg)
8441	let g:taken = g:taken . "M" . a:n
8442	let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8443	if a:enr == ""
8444	    Xout "TODO: Add message number for:" a:emsg
8445	    let v:errmsg = ":" . v:errmsg
8446	endif
8447	if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
8448	    if v:errmsg == ""
8449		Xout "Expr" a:n.": Message missing."
8450		let g:taken = g:taken . "x"
8451	    else
8452		let v:errmsg = escape(v:errmsg, '"')
8453		Xout "Expr" a:n.": Unexpected message:" v:errmsg
8454		Xout "Expected: " . a:enr . ': ' . a:emsg
8455		let g:taken = g:taken . "X"
8456	    endif
8457	endif
8458    endfunction
8459
8460    function! CONT(n)
8461	let g:taken = g:taken . "C" . a:n
8462    endfunction
8463
8464    let v:errmsg = ""
8465    XloopINIT 1 2
8466
8467    try
8468	let t = 1
8469	while t <= 14
8470	    let g:taken = g:taken . "T" . t
8471	    let v:errmsg = ""
8472	    try
8473		let caught = 0
8474		if t == 1
8475		    let v{novar + CONT(t)} = 0
8476		elseif t == 2
8477		    let v{novar + CONT(t)}
8478		elseif t == 3
8479		    let var = exists('v{novar + CONT(t)}')
8480		elseif t == 4
8481		    unlet v{novar + CONT(t)}
8482		elseif t == 5
8483		    function F{novar + CONT(t)}()
8484		    endfunction
8485		elseif t == 6
8486		    function F{novar + CONT(t)}
8487		elseif t == 7
8488		    let var = exists('*F{novar + CONT(t)}')
8489		elseif t == 8
8490		    delfunction F{novar + CONT(t)}
8491		elseif t == 9
8492		    echo novar + CONT(t)
8493		elseif t == 10
8494		    echo v{novar + CONT(t)}
8495		elseif t == 11
8496		    echo F{novar + CONT(t)}
8497		elseif t == 12
8498		    let var = novar + CONT(t)
8499		elseif t == 13
8500		    let var = v{novar + CONT(t)}
8501		elseif t == 14
8502		    let var = F{novar + CONT(t)}()
8503		endif
8504	    catch /^Vim\((\a\+)\)\=:/
8505		" v:errmsg is not set when the error message is converted to an
8506		" exception.  Set it to the original error message.
8507		let v:errmsg = substitute(v:exception,
8508		    \ '^Vim\((\a\+)\)\=:', '', "")
8509		let caught = 1
8510	    finally
8511		if t <= 8 && t != 3 && t != 7
8512		    call MSG(t, 'E475', 'Invalid argument\>')
8513		else
8514		    if !caught	" no error exceptions ($VIMNOERRTHROW set)
8515			call MSG(t, 'E15', "Invalid expression")
8516		    else
8517			call MSG(t, 'E121', "Undefined variable")
8518		    endif
8519		endif
8520		let t = t + 1
8521		XloopNEXT
8522		continue	" discard an aborting error
8523	    endtry
8524	endwhile
8525    catch /.*/
8526	Xloop 1					" X: 0
8527	Xout t.":" v:exception "in" ExtraVimThrowpoint()
8528    endtry
8529
8530    function! T(n, expr, enr, emsg)
8531	try
8532	    let g:taken = g:taken . "T" . a:n
8533	    let v:errmsg = ""
8534	    try
8535		let caught = 0
8536		execute "let var = " . a:expr
8537	    catch /^Vim\((\a\+)\)\=:/
8538		" v:errmsg is not set when the error message is converted to an
8539		" exception.  Set it to the original error message.
8540		let v:errmsg = substitute(v:exception,
8541		    \ '^Vim\((\a\+)\)\=:', '', "")
8542		let caught = 1
8543	    finally
8544		if !caught	" no error exceptions ($VIMNOERRTHROW set)
8545		    call MSG(a:n, 'E15', "Invalid expression")
8546		else
8547		    call MSG(a:n, a:enr, a:emsg)
8548		endif
8549		XloopNEXT
8550		" Discard an aborting error:
8551		return
8552	    endtry
8553	catch /.*/
8554	    Xloop 1				" X: 0
8555	    Xout a:n.":" v:exception "in" ExtraVimThrowpoint()
8556	endtry
8557    endfunction
8558
8559    call T(15, 'Nofunc() + CONT(15)',	'E117',	"Unknown function")
8560    call T(16, 'F(1 2 + CONT(16))',	'E116',	"Invalid arguments")
8561    call T(17, 'F(1, 2) + CONT(17)',	'E118',	"Too many arguments")
8562    call T(18, 'F() + CONT(18)',	'E119',	"Not enough arguments")
8563    call T(19, '{(1} + CONT(19)',	'E110',	"Missing ')'")
8564    call T(20, '("abc"[1) + CONT(20)',	'E111',	"Missing ']'")
8565    call T(21, '(1 +) + CONT(21)',	'E15',	"Invalid expression")
8566    call T(22, '1 2 + CONT(22)',	'E15',	"Invalid expression")
8567    call T(23, '(1 ? 2) + CONT(23)',	'E109',	"Missing ':' after '?'")
8568    call T(24, '("abc) + CONT(24)',	'E114',	"Missing quote")
8569    call T(25, "('abc) + CONT(25)",	'E115',	"Missing quote")
8570    call T(26, '& + CONT(26)',		'E112', "Option name missing")
8571    call T(27, '&asdf + CONT(27)',	'E113', "Unknown option")
8572
8573    Xpath 134217728				" X: 134217728
8574
8575    let expected = ""
8576	\ . "T1M1T2M2T3M3T4M4T5M5T6M6T7M7T8M8T9M9T10M10T11M11T12M12T13M13T14M14"
8577	\ . "T15M15T16M16T17M17T18M18T19M19T20M20T21M21T22M22T23M23T24M24T25M25"
8578	\ . "T26M26T27M27"
8579
8580    if taken != expected
8581	Xpath 268435456				" X: 0
8582	Xout "'taken' is" taken "instead of" expected
8583	if substitute(taken, '\(.*\)T3M3x\(.*\)', '\1T3M3\2', "") == expected
8584	    Xout "Is ++emsg_skip for var with expr_start non-NULL"
8585		\ "in f_exists ok?"
8586	endif
8587    endif
8588
8589    unlet! var caught taken expected
8590    call delete(WA_t5)
8591    unlet! WA_t5
8592    delfunction WA_t5
8593
8594endif
8595
8596Xcheck 134217728
8597
8598
8599"-------------------------------------------------------------------------------
8600" Test 79:  Throwing one of several errors for the same command		    {{{1
8601"
8602"	    When several errors appear in a row (for instance during expression
8603"	    evaluation), the first as the most specific one is used when
8604"	    throwing an error exception.  If, however, a syntax error is
8605"	    detected afterwards, this one is used for the error exception.
8606"	    On a syntax error, the next command is not executed, on a normal
8607"	    error, however, it is (relevant only in a function without the
8608"	    "abort" flag).  v:errmsg is not set.
8609"
8610"	    If throwing error exceptions is configured off, v:errmsg is always
8611"	    set to the latest error message, that is, to the more general
8612"	    message or the syntax error, respectively.
8613"-------------------------------------------------------------------------------
8614
8615XpathINIT
8616
8617XloopINIT 1 2
8618
8619function! NEXT(cmd)
8620    exec a:cmd . " | Xloop 1"
8621endfunction
8622
8623call NEXT('echo novar')				" X: 1 *  1  (checks nextcmd)
8624XloopNEXT
8625call NEXT('let novar #')			" X: 0 *  2  (skips nextcmd)
8626XloopNEXT
8627call NEXT('unlet novar #')			" X: 0 *  4  (skips nextcmd)
8628XloopNEXT
8629call NEXT('let {novar}')			" X: 0 *  8  (skips nextcmd)
8630XloopNEXT
8631call NEXT('unlet{ novar}')			" X: 0 * 16  (skips nextcmd)
8632
8633function! EXEC(cmd)
8634    exec a:cmd
8635endfunction
8636
8637function! MATCH(expected, msg, enr, emsg)
8638    let msg = a:msg
8639    if a:enr == ""
8640	Xout "TODO: Add message number for:" a:emsg
8641	let msg = ":" . msg
8642    endif
8643    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8644    if msg !~ '^'.a:enr.':' || (english && msg !~ a:emsg)
8645	let match =  0
8646	if a:expected		" no match although expected
8647	    if a:msg == ""
8648		Xout "Message missing."
8649	    else
8650		let msg = escape(msg, '"')
8651		Xout "Unexpected message:" msg
8652		Xout "Expected:" a:enr . ": " . a:emsg
8653	    endif
8654	endif
8655    else
8656	let match =  1
8657	if !a:expected		" match although not expected
8658	    let msg = escape(msg, '"')
8659	    Xout "Unexpected message:" msg
8660	    Xout "Expected none."
8661	endif
8662    endif
8663    return match
8664endfunction
8665
8666try
8667
8668    while 1				" dummy loop
8669	try
8670	    let v:errmsg = ""
8671	    let caught = 0
8672	    let thrmsg = ""
8673	    call EXEC('echo novar')	" normal error
8674	catch /^Vim\((\a\+)\)\=:/
8675	    let caught = 1
8676	    let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8677	finally
8678	    Xpath 32				" X: 32
8679	    if !caught
8680		if !$VIMNOERRTHROW
8681		    Xpath 64			" X: 0
8682		endif
8683	    elseif !MATCH(1, thrmsg, 'E121', "Undefined variable")
8684	    \ || v:errmsg != ""
8685		Xpath 128			" X: 0
8686	    endif
8687	    if !caught && !MATCH(1, v:errmsg, 'E15', "Invalid expression")
8688		Xpath 256			" X: 0
8689	    endif
8690	    break			" discard error if $VIMNOERRTHROW == 1
8691	endtry
8692    endwhile
8693
8694    Xpath 512					" X: 512
8695    let cmd = "let"
8696    XloopINIT 1024 32
8697    while cmd != ""
8698	try
8699	    let v:errmsg = ""
8700	    let caught = 0
8701	    let thrmsg = ""
8702	    call EXEC(cmd . ' novar #')		" normal plus syntax error
8703	catch /^Vim\((\a\+)\)\=:/
8704	    let caught = 1
8705	    let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8706	finally
8707	    Xloop 1				" X: 1024 * (1 + 32)
8708	    if !caught
8709		if !$VIMNOERRTHROW
8710		    Xloop 2			" X: 0
8711		endif
8712	    else
8713		if cmd == "let"
8714		    let match = MATCH(0, thrmsg, 'E106', "Unknown variable")
8715		elseif cmd == "unlet"
8716		    let match = MATCH(0, thrmsg, 'E108', "No such variable")
8717		endif
8718		if match					" normal error
8719		    Xloop 4			" X: 0
8720		endif
8721		if !MATCH(1, thrmsg, 'E488', "Trailing characters")
8722		\|| v:errmsg != ""
8723								" syntax error
8724		    Xloop 8			" X: 0
8725		endif
8726	    endif
8727	    if !caught && !MATCH(1, v:errmsg, 'E488', "Trailing characters")
8728								" last error
8729		Xloop 16			" X: 0
8730	    endif
8731	    if cmd == "let"
8732		let cmd = "unlet"
8733	    else
8734		let cmd = ""
8735	    endif
8736	    XloopNEXT
8737	    continue			" discard error if $VIMNOERRTHROW == 1
8738	endtry
8739    endwhile
8740
8741    Xpath 1048576				" X: 1048576
8742    let cmd = "let"
8743    XloopINIT 2097152 32
8744    while cmd != ""
8745	try
8746	    let v:errmsg = ""
8747	    let caught = 0
8748	    let thrmsg = ""
8749	    call EXEC(cmd . ' {novar}')		" normal plus syntax error
8750	catch /^Vim\((\a\+)\)\=:/
8751	    let caught = 1
8752	    let thrmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8753	finally
8754	    Xloop 1				" X: 2097152 * (1 + 32)
8755	    if !caught
8756		if !$VIMNOERRTHROW
8757		    Xloop 2			" X: 0
8758		endif
8759	    else
8760		if MATCH(0, thrmsg, 'E121', "Undefined variable") " normal error
8761		    Xloop 4			" X: 0
8762		endif
8763		if !MATCH(1, thrmsg, 'E475', 'Invalid argument\>')
8764		\ || v:errmsg != ""				  " syntax error
8765		    Xloop 8			" X: 0
8766		endif
8767	    endif
8768	    if !caught && !MATCH(1, v:errmsg, 'E475', 'Invalid argument\>')
8769								" last error
8770		Xloop 16			" X: 0
8771	    endif
8772	    if cmd == "let"
8773		let cmd = "unlet"
8774	    else
8775		let cmd = ""
8776	    endif
8777	    XloopNEXT
8778	    continue			" discard error if $VIMNOERRTHROW == 1
8779	endtry
8780    endwhile
8781
8782catch /.*/
8783    " The Xpath command does not accept 2^31 (negative); add explicitly:
8784    let Xpath = Xpath + 2147483648		" X: 0
8785    Xout v:exception "in" v:throwpoint
8786endtry
8787
8788unlet! next_command thrmsg match
8789delfunction NEXT
8790delfunction EXEC
8791delfunction MATCH
8792
8793Xcheck 70288929
8794
8795
8796"-------------------------------------------------------------------------------
8797" Test 80:  Syntax error in expression for illegal :elseif		    {{{1
8798"
8799"	    If there is a syntax error in the expression after an illegal
8800"	    :elseif, an error message is given (or an error exception thrown)
8801"	    for the illegal :elseif rather than the expression error.
8802"-------------------------------------------------------------------------------
8803
8804XpathINIT
8805
8806function! MSG(enr, emsg)
8807    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
8808    if a:enr == ""
8809	Xout "TODO: Add message number for:" a:emsg
8810	let v:errmsg = ":" . v:errmsg
8811    endif
8812    let match = 1
8813    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
8814	let match = 0
8815	if v:errmsg == ""
8816	    Xout "Message missing."
8817	else
8818	    let v:errmsg = escape(v:errmsg, '"')
8819	    Xout "Unexpected message:" v:errmsg
8820	endif
8821    endif
8822    return match
8823endfunction
8824
8825let v:errmsg = ""
8826if 0
8827else
8828elseif 1 ||| 2
8829endif
8830Xpath 1						" X: 1
8831if !MSG('E584', ":elseif after :else")
8832    Xpath 2					" X: 0
8833endif
8834
8835let v:errmsg = ""
8836if 1
8837else
8838elseif 1 ||| 2
8839endif
8840Xpath 4						" X: 4
8841if !MSG('E584', ":elseif after :else")
8842    Xpath 8					" X: 0
8843endif
8844
8845let v:errmsg = ""
8846elseif 1 ||| 2
8847Xpath 16					" X: 16
8848if !MSG('E582', ":elseif without :if")
8849    Xpath 32					" X: 0
8850endif
8851
8852let v:errmsg = ""
8853while 1
8854    elseif 1 ||| 2
8855endwhile
8856Xpath 64					" X: 64
8857if !MSG('E582', ":elseif without :if")
8858    Xpath 128					" X: 0
8859endif
8860
8861while 1
8862    try
8863	try
8864	    let v:errmsg = ""
8865	    let caught = 0
8866	    if 0
8867	    else
8868	    elseif 1 ||| 2
8869	    endif
8870	catch /^Vim\((\a\+)\)\=:/
8871	    let caught = 1
8872	    let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8873	finally
8874	    Xpath 256				" X: 256
8875	    if !caught && !$VIMNOERRTHROW
8876		Xpath 512			" X: 0
8877	    endif
8878	    if !MSG('E584', ":elseif after :else")
8879		Xpath 1024			" X: 0
8880	    endif
8881	endtry
8882    catch /.*/
8883	Xpath 2048				" X: 0
8884	Xout v:exception "in" v:throwpoint
8885    finally
8886	break		" discard error for $VIMNOERRTHROW
8887    endtry
8888endwhile
8889
8890while 1
8891    try
8892	try
8893	    let v:errmsg = ""
8894	    let caught = 0
8895	    if 1
8896	    else
8897	    elseif 1 ||| 2
8898	    endif
8899	catch /^Vim\((\a\+)\)\=:/
8900	    let caught = 1
8901	    let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8902	finally
8903	    Xpath 4096				" X: 4096
8904	    if !caught && !$VIMNOERRTHROW
8905		Xpath 8192			" X: 0
8906	    endif
8907	    if !MSG('E584', ":elseif after :else")
8908		Xpath 16384			" X: 0
8909	    endif
8910	endtry
8911    catch /.*/
8912	Xpath 32768				" X: 0
8913	Xout v:exception "in" v:throwpoint
8914    finally
8915	break		" discard error for $VIMNOERRTHROW
8916    endtry
8917endwhile
8918
8919while 1
8920    try
8921	try
8922	    let v:errmsg = ""
8923	    let caught = 0
8924	    elseif 1 ||| 2
8925	catch /^Vim\((\a\+)\)\=:/
8926	    let caught = 1
8927	    let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8928	finally
8929	    Xpath 65536				" X: 65536
8930	    if !caught && !$VIMNOERRTHROW
8931		Xpath 131072			" X: 0
8932	    endif
8933	    if !MSG('E582', ":elseif without :if")
8934		Xpath 262144			" X: 0
8935	    endif
8936	endtry
8937    catch /.*/
8938	Xpath 524288				" X: 0
8939	Xout v:exception "in" v:throwpoint
8940    finally
8941	break		" discard error for $VIMNOERRTHROW
8942    endtry
8943endwhile
8944
8945while 1
8946    try
8947	try
8948	    let v:errmsg = ""
8949	    let caught = 0
8950	    while 1
8951		elseif 1 ||| 2
8952	    endwhile
8953	catch /^Vim\((\a\+)\)\=:/
8954	    let caught = 1
8955	    let v:errmsg = substitute(v:exception, '^Vim\((\a\+)\)\=:', '', "")
8956	finally
8957	    Xpath 1048576			" X: 1048576
8958	    if !caught && !$VIMNOERRTHROW
8959		Xpath 2097152			" X: 0
8960	    endif
8961	    if !MSG('E582', ":elseif without :if")
8962		Xpath 4194304			" X: 0
8963	    endif
8964	endtry
8965    catch /.*/
8966	Xpath 8388608				" X: 0
8967	Xout v:exception "in" v:throwpoint
8968    finally
8969	break		" discard error for $VIMNOERRTHROW
8970    endtry
8971endwhile
8972
8973Xpath 16777216					" X: 16777216
8974
8975unlet! caught
8976delfunction MSG
8977
8978Xcheck 17895765
8979
8980
8981"-------------------------------------------------------------------------------
8982" Test 81:  Discarding exceptions after an error or interrupt		    {{{1
8983"
8984"	    When an exception is thrown from inside a :try conditional without
8985"	    :catch and :finally clauses and an error or interrupt occurs before
8986"	    the :endtry is reached, the exception is discarded.
8987"-------------------------------------------------------------------------------
8988
8989XpathINIT
8990
8991if ExtraVim()
8992    try
8993	Xpath 1					" X: 1
8994	try
8995	    Xpath 2				" X: 2
8996	    throw "arrgh"
8997	    Xpath 4				" X: 0
8998"	    if 1
8999		Xpath 8				" X: 0
9000	    " error after :throw: missing :endif
9001	endtry
9002	Xpath 16				" X: 0
9003    catch /arrgh/
9004	Xpath 32				" X: 0
9005    endtry
9006    Xpath 64					" X: 0
9007endif
9008
9009if ExtraVim()
9010    try
9011	Xpath 128				" X: 128
9012	try
9013	    Xpath 256				" X: 256
9014	    throw "arrgh"
9015	    Xpath 512				" X: 0
9016	endtry		" INTERRUPT
9017	Xpath 1024				" X: 0
9018    catch /arrgh/
9019	Xpath 2048				" X: 0
9020    endtry
9021    Xpath 4096					" X: 0
9022endif
9023
9024Xcheck 387
9025
9026
9027"-------------------------------------------------------------------------------
9028" Test 82:  Ignoring :catch clauses after an error or interrupt		    {{{1
9029"
9030"	    When an exception is thrown and an error or interrupt occurs before
9031"	    the matching :catch clause is reached, the exception is discarded
9032"	    and the :catch clause is ignored (also for the error or interrupt
9033"	    exception being thrown then).
9034"-------------------------------------------------------------------------------
9035
9036XpathINIT
9037
9038if ExtraVim()
9039    try
9040	try
9041	    Xpath 1				" X: 1
9042	    throw "arrgh"
9043	    Xpath 2				" X: 0
9044"	    if 1
9045		Xpath 4				" X: 0
9046		" error after :throw: missing :endif
9047	catch /.*/
9048	    Xpath 8				" X: 0
9049	    Xout v:exception "in" ExtraVimThrowpoint()
9050	catch /.*/
9051	    Xpath 16				" X: 0
9052	    Xout v:exception "in" ExtraVimThrowpoint()
9053	endtry
9054	Xpath 32				" X: 0
9055    catch /arrgh/
9056	Xpath 64				" X: 0
9057    endtry
9058    Xpath 128					" X: 0
9059endif
9060
9061if ExtraVim()
9062    function! E()
9063	try
9064	    try
9065		Xpath 256			" X: 256
9066		throw "arrgh"
9067		Xpath 512			" X: 0
9068"		if 1
9069		    Xpath 1024			" X: 0
9070		    " error after :throw: missing :endif
9071	    catch /.*/
9072		Xpath 2048			" X: 0
9073		Xout v:exception "in" ExtraVimThrowpoint()
9074	    catch /.*/
9075		Xpath 4096			" X: 0
9076		Xout v:exception "in" ExtraVimThrowpoint()
9077	    endtry
9078	    Xpath 8192				" X: 0
9079	catch /arrgh/
9080	    Xpath 16384				" X: 0
9081	endtry
9082    endfunction
9083
9084    call E()
9085    Xpath 32768					" X: 0
9086endif
9087
9088if ExtraVim()
9089    try
9090	try
9091	    Xpath 65536				" X: 65536
9092	    throw "arrgh"
9093	    Xpath 131072			" X: 0
9094	catch /.*/	"INTERRUPT
9095	    Xpath 262144			" X: 0
9096	    Xout v:exception "in" ExtraVimThrowpoint()
9097	catch /.*/
9098	    Xpath 524288			" X: 0
9099	    Xout v:exception "in" ExtraVimThrowpoint()
9100	endtry
9101	Xpath 1048576				" X: 0
9102    catch /arrgh/
9103	Xpath 2097152				" X: 0
9104    endtry
9105    Xpath 4194304				" X: 0
9106endif
9107
9108if ExtraVim()
9109    function I()
9110	try
9111	    try
9112		Xpath 8388608			" X: 8388608
9113		throw "arrgh"
9114		Xpath 16777216			" X: 0
9115	    catch /.*/	"INTERRUPT
9116		Xpath 33554432			" X: 0
9117		Xout v:exception "in" ExtraVimThrowpoint()
9118	    catch /.*/
9119		Xpath 67108864			" X: 0
9120		Xout v:exception "in" ExtraVimThrowpoint()
9121	    endtry
9122	    Xpath 134217728			" X: 0
9123	catch /arrgh/
9124	    Xpath 268435456			" X: 0
9125	endtry
9126    endfunction
9127
9128    call I()
9129    Xpath 536870912				" X: 0
9130endif
9131
9132Xcheck 8454401
9133
9134
9135"-------------------------------------------------------------------------------
9136" Test 83:  Executing :finally clauses after an error or interrupt	    {{{1
9137"
9138"	    When an exception is thrown and an error or interrupt occurs before
9139"	    the :finally of the innermost :try is reached, the exception is
9140"	    discarded and the :finally clause is executed.
9141"-------------------------------------------------------------------------------
9142
9143XpathINIT
9144
9145if ExtraVim()
9146    try
9147	Xpath 1					" X: 1
9148	try
9149	    Xpath 2				" X: 2
9150	    throw "arrgh"
9151	    Xpath 4				" X: 0
9152"	    if 1
9153		Xpath 8				" X: 0
9154	    " error after :throw: missing :endif
9155	finally
9156	    Xpath 16				" X: 16
9157	endtry
9158	Xpath 32				" X: 0
9159    catch /arrgh/
9160	Xpath 64				" X: 0
9161    endtry
9162    Xpath 128					" X: 0
9163endif
9164
9165if ExtraVim()
9166    try
9167	Xpath 256				" X: 256
9168	try
9169	    Xpath 512				" X: 512
9170	    throw "arrgh"
9171	    Xpath 1024				" X: 0
9172	finally		"INTERRUPT
9173	    Xpath 2048				" X: 2048
9174	endtry
9175	Xpath 4096				" X: 0
9176    catch /arrgh/
9177	Xpath 8192				" X: 0
9178    endtry
9179    Xpath 16384					" X: 0
9180endif
9181
9182Xcheck 2835
9183
9184
9185"-------------------------------------------------------------------------------
9186" Test 84:  Exceptions in autocommand sequences.			    {{{1
9187"
9188"	    When an exception occurs in a sequence of autocommands for
9189"	    a specific event, the rest of the sequence is not executed.  The
9190"	    command that triggered the autocommand execution aborts, and the
9191"	    exception is propagated to the caller.
9192"
9193"	    For the FuncUndefined event under a function call expression or
9194"	    :call command, the function is not executed, even when it has
9195"	    been defined by the autocommands before the exception occurred.
9196"-------------------------------------------------------------------------------
9197
9198XpathINIT
9199
9200if ExtraVim()
9201
9202    function! INT()
9203	"INTERRUPT
9204	let dummy = 0
9205    endfunction
9206
9207    aug TMP
9208	autocmd!
9209
9210	autocmd User x1 Xpath 1			" X: 1
9211	autocmd User x1 throw "x1"
9212	autocmd User x1 Xpath 2			" X: 0
9213
9214	autocmd User x2 Xpath 4			" X: 4
9215	autocmd User x2 asdf
9216	autocmd User x2 Xpath 8			" X: 0
9217
9218	autocmd User x3 Xpath 16		" X: 16
9219	autocmd User x3 call INT()
9220	autocmd User x3 Xpath 32		" X: 0
9221
9222	autocmd FuncUndefined U1 function! U1()
9223	autocmd FuncUndefined U1     Xpath 64	" X: 0
9224	autocmd FuncUndefined U1 endfunction
9225	autocmd FuncUndefined U1 Xpath 128	" X: 128
9226	autocmd FuncUndefined U1 throw "U1"
9227	autocmd FuncUndefined U1 Xpath 256	" X: 0
9228
9229	autocmd FuncUndefined U2 function! U2()
9230	autocmd FuncUndefined U2     Xpath 512	" X: 0
9231	autocmd FuncUndefined U2 endfunction
9232	autocmd FuncUndefined U2 Xpath 1024	" X: 1024
9233	autocmd FuncUndefined U2 ASDF
9234	autocmd FuncUndefined U2 Xpath 2048	" X: 0
9235
9236	autocmd FuncUndefined U3 function! U3()
9237	autocmd FuncUndefined U3     Xpath 4096	" X: 0
9238	autocmd FuncUndefined U3 endfunction
9239	autocmd FuncUndefined U3 Xpath 8192	" X: 8192
9240	autocmd FuncUndefined U3 call INT()
9241	autocmd FuncUndefined U3 Xpath 16384	" X: 0
9242    aug END
9243
9244    try
9245	try
9246	    Xpath 32768				" X: 32768
9247	    doautocmd User x1
9248	catch /x1/
9249	    Xpath 65536				" X: 65536
9250	endtry
9251
9252	while 1
9253	    try
9254		Xpath 131072			" X: 131072
9255		let caught = 0
9256		doautocmd User x2
9257	    catch /asdf/
9258		let caught = 1
9259	    finally
9260		Xpath 262144			" X: 262144
9261		if !caught && !$VIMNOERRTHROW
9262		    Xpath 524288		" X: 0
9263		    " Propagate uncaught error exception,
9264		else
9265		    " ... but break loop for caught error exception,
9266		    " or discard error and break loop if $VIMNOERRTHROW
9267		    break
9268		endif
9269	    endtry
9270	endwhile
9271
9272	while 1
9273	    try
9274		Xpath 1048576			" X: 1048576
9275		let caught = 0
9276		doautocmd User x3
9277	    catch /Vim:Interrupt/
9278		let caught = 1
9279	    finally
9280		Xpath 2097152			" X: 2097152
9281		if !caught && !$VIMNOINTTHROW
9282		    Xpath 4194304		" X: 0
9283		    " Propagate uncaught interrupt exception,
9284		else
9285		    " ... but break loop for caught interrupt exception,
9286		    " or discard interrupt and break loop if $VIMNOINTTHROW
9287		    break
9288		endif
9289	    endtry
9290	endwhile
9291
9292	if exists("*U1") | delfunction U1 | endif
9293	if exists("*U2") | delfunction U2 | endif
9294	if exists("*U3") | delfunction U3 | endif
9295
9296	try
9297	    Xpath 8388608			" X: 8388608
9298	    call U1()
9299	catch /U1/
9300	    Xpath 16777216			" X: 16777216
9301	endtry
9302
9303	while 1
9304	    try
9305		Xpath 33554432			" X: 33554432
9306		let caught = 0
9307		call U2()
9308	    catch /ASDF/
9309		let caught = 1
9310	    finally
9311		Xpath 67108864			" X: 67108864
9312		if !caught && !$VIMNOERRTHROW
9313		    Xpath 134217728		" X: 0
9314		    " Propagate uncaught error exception,
9315		else
9316		    " ... but break loop for caught error exception,
9317		    " or discard error and break loop if $VIMNOERRTHROW
9318		    break
9319		endif
9320	    endtry
9321	endwhile
9322
9323	while 1
9324	    try
9325		Xpath 268435456			" X: 268435456
9326		let caught = 0
9327		call U3()
9328	    catch /Vim:Interrupt/
9329		let caught = 1
9330	    finally
9331		Xpath 536870912			" X: 536870912
9332		if !caught && !$VIMNOINTTHROW
9333		    Xpath 1073741824		" X: 0
9334		    " Propagate uncaught interrupt exception,
9335		else
9336		    " ... but break loop for caught interrupt exception,
9337		    " or discard interrupt and break loop if $VIMNOINTTHROW
9338		    break
9339		endif
9340	    endtry
9341	endwhile
9342    catch /.*/
9343	" The Xpath command does not accept 2^31 (negative); display explicitly:
9344	exec "!echo 2147483648 >>" . g:ExtraVimResult
9345	Xout "Caught" v:exception "in" v:throwpoint
9346    endtry
9347
9348    unlet caught
9349    delfunction INT
9350    delfunction U1
9351    delfunction U2
9352    delfunction U3
9353    au! TMP
9354    aug! TMP
9355endif
9356
9357Xcheck 934782101
9358
9359
9360"-------------------------------------------------------------------------------
9361" Test 85:  Error exceptions in autocommands for I/O command events	    {{{1
9362"
9363"	    When an I/O command is inside :try/:endtry, autocommands to be
9364"	    executed after it should be skipped on an error (exception) in the
9365"	    command itself or in autocommands to be executed before the command.
9366"	    In the latter case, the I/O command should not be executed either.
9367"	    Example 1: BufWritePre, :write, BufWritePost
9368"	    Example 2: FileReadPre, :read, FileReadPost.
9369"-------------------------------------------------------------------------------
9370
9371XpathINIT
9372
9373function! MSG(enr, emsg)
9374    let english = v:lang == "C" || v:lang =~ '^[Ee]n'
9375    if a:enr == ""
9376	Xout "TODO: Add message number for:" a:emsg
9377	let v:errmsg = ":" . v:errmsg
9378    endif
9379    let match = 1
9380    if v:errmsg !~ '^'.a:enr.':' || (english && v:errmsg !~ a:emsg)
9381	let match = 0
9382	if v:errmsg == ""
9383	    Xout "Message missing."
9384	else
9385	    let v:errmsg = escape(v:errmsg, '"')
9386	    Xout "Unexpected message:" v:errmsg
9387	endif
9388    endif
9389    return match
9390endfunction
9391
9392" Remove the autocommands for the events specified as arguments in all used
9393" autogroups.
9394function! Delete_autocommands(...)
9395    let augfile = tempname()
9396    while 1
9397	try
9398	    exec "redir >" . augfile
9399	    aug
9400	    redir END
9401	    exec "edit" augfile
9402	    g/^$/d
9403	    norm G$
9404	    let wrap = "w"
9405	    while search('\%(  \|^\)\@<=.\{-}\%(  \)\@=', wrap) > 0
9406		let wrap = "W"
9407		exec "norm y/  \n"
9408		let argno = 1
9409		while argno <= a:0
9410		    exec "au!" escape(@", " ") a:{argno}
9411		    let argno = argno + 1
9412		endwhile
9413	    endwhile
9414	catch /.*/
9415	finally
9416	    bwipeout!
9417	    call delete(augfile)
9418	    break		" discard errors for $VIMNOERRTHROW
9419	endtry
9420    endwhile
9421endfunction
9422
9423call Delete_autocommands("BufWritePre", "BufWritePost")
9424
9425while 1
9426    try
9427	try
9428	    let post = 0
9429	    aug TMP
9430		au! BufWritePost * let post = 1
9431	    aug END
9432	    let caught = 0
9433	    write /n/o/n/e/x/i/s/t/e/n/t
9434	catch /^Vim(write):/
9435	    let caught = 1
9436	    let v:errmsg = substitute(v:exception, '^Vim(write):', '', "")
9437	finally
9438	    Xpath 1				" X: 1
9439	    if !caught && !$VIMNOERRTHROW
9440		Xpath 2				" X: 0
9441	    endif
9442	    let v:errmsg = substitute(v:errmsg, '^"/n/o/n/e/x/i/s/t/e/n/t" ',
9443		\ '', "")
9444	    if !MSG('E212', "Can't open file for writing")
9445		Xpath 4				" X: 0
9446	    endif
9447	    if post
9448		Xpath 8				" X: 0
9449		Xout "BufWritePost commands executed after write error"
9450	    endif
9451	    au! TMP
9452	    aug! TMP
9453	endtry
9454    catch /.*/
9455	Xpath 16				" X: 0
9456	Xout v:exception "in" v:throwpoint
9457    finally
9458	break		" discard error for $VIMNOERRTHROW
9459    endtry
9460endwhile
9461
9462while 1
9463    try
9464	try
9465	    let post = 0
9466	    aug TMP
9467		au! BufWritePre  * asdf
9468		au! BufWritePost * let post = 1
9469	    aug END
9470	    let tmpfile = tempname()
9471	    let caught = 0
9472	    exec "write" tmpfile
9473	catch /^Vim\((write)\)\=:/
9474	    let caught = 1
9475	    let v:errmsg = substitute(v:exception, '^Vim\((write)\)\=:', '', "")
9476	finally
9477	    Xpath 32				" X: 32
9478	    if !caught && !$VIMNOERRTHROW
9479		Xpath 64			" X: 0
9480	    endif
9481	    let v:errmsg = substitute(v:errmsg, '^"'.tmpfile.'" ', '', "")
9482	    if !MSG('E492', "Not an editor command")
9483		Xpath 128			" X: 0
9484	    endif
9485	    if filereadable(tmpfile)
9486		Xpath 256			" X: 0
9487		Xout ":write command not suppressed after BufWritePre error"
9488	    endif
9489	    if post
9490		Xpath 512			" X: 0
9491		Xout "BufWritePost commands executed after BufWritePre error"
9492	    endif
9493	    au! TMP
9494	    aug! TMP
9495	endtry
9496    catch /.*/
9497	Xpath 1024				" X: 0
9498	Xout v:exception "in" v:throwpoint
9499    finally
9500	break		" discard error for $VIMNOERRTHROW
9501    endtry
9502endwhile
9503
9504call delete(tmpfile)
9505
9506call Delete_autocommands("BufWritePre", "BufWritePost",
9507    \ "BufReadPre", "BufReadPost", "FileReadPre", "FileReadPost")
9508
9509while 1
9510    try
9511	try
9512	    let post = 0
9513	    aug TMP
9514		au! FileReadPost * let post = 1
9515	    aug END
9516	    let caught = 0
9517	    read /n/o/n/e/x/i/s/t/e/n/t
9518	catch /^Vim(read):/
9519	    let caught = 1
9520	    let v:errmsg = substitute(v:exception, '^Vim(read):', '', "")
9521	finally
9522	    Xpath 2048				" X: 2048
9523	    if !caught && !$VIMNOERRTHROW
9524		Xpath 4096			" X: 0
9525	    endif
9526	    let v:errmsg = substitute(v:errmsg, ' /n/o/n/e/x/i/s/t/e/n/t$',
9527		\ '', "")
9528	    if !MSG('E484', "Can't open file")
9529		Xpath 8192			" X: 0
9530	    endif
9531	    if post
9532		Xpath 16384			" X: 0
9533		Xout "FileReadPost commands executed after write error"
9534	    endif
9535	    au! TMP
9536	    aug! TMP
9537	endtry
9538    catch /.*/
9539	Xpath 32768				" X: 0
9540	Xout v:exception "in" v:throwpoint
9541    finally
9542	break		" discard error for $VIMNOERRTHROW
9543    endtry
9544endwhile
9545
9546while 1
9547    try
9548	let infile = tempname()
9549	let tmpfile = tempname()
9550	exec "!echo XYZ >" . infile
9551	exec "edit" tmpfile
9552	try
9553	    Xpath 65536				" X: 65536
9554	    try
9555		let post = 0
9556		aug TMP
9557		    au! FileReadPre  * asdf
9558		    au! FileReadPost * let post = 1
9559		aug END
9560		let caught = 0
9561		exec "0read" infile
9562	    catch /^Vim\((read)\)\=:/
9563		let caught = 1
9564		let v:errmsg = substitute(v:exception, '^Vim\((read)\)\=:', '',
9565		    \ "")
9566	    finally
9567		Xpath 131072			" X: 131072
9568		if !caught && !$VIMNOERRTHROW
9569		    Xpath 262144		" X: 0
9570		endif
9571		let v:errmsg = substitute(v:errmsg, ' '.infile.'$', '', "")
9572		if !MSG('E492', "Not an editor command")
9573		    Xpath 524288		" X: 0
9574		endif
9575		if getline("1") == "XYZ"
9576		    Xpath 1048576		" X: 0
9577		    Xout ":read command not suppressed after FileReadPre error"
9578		endif
9579		if post
9580		    Xpath 2097152		" X: 0
9581		    Xout "FileReadPost commands executed after " .
9582			\ "FileReadPre error"
9583		endif
9584		au! TMP
9585		aug! TMP
9586	    endtry
9587	finally
9588	    bwipeout!
9589	endtry
9590    catch /.*/
9591	Xpath 4194304				" X: 0
9592	Xout v:exception "in" v:throwpoint
9593    finally
9594	break		" discard error for $VIMNOERRTHROW
9595    endtry
9596endwhile
9597
9598call delete(infile)
9599call delete(tmpfile)
9600unlet! caught post infile tmpfile
9601delfunction MSG
9602delfunction Delete_autocommands
9603
9604Xcheck 198689
9605
9606
9607"-------------------------------------------------------------------------------
9608" Test 86:  $VIMNOERRTHROW and $VIMNOINTTHROW support			    {{{1
9609"
9610"	    It is possible to configure Vim for throwing exceptions on error
9611"	    or interrupt, controlled by variables $VIMNOERRTHROW and
9612"	    $VIMNOINTTHROW.  This is just for increasing the number of tests.
9613"	    All tests here should run for all four combinations of setting
9614"	    these variables to 0 or 1.  The variables are intended for the
9615"	    development phase only.  In the final release, Vim should be
9616"	    configured to always use error and interrupt exceptions.
9617"
9618"	    The test result is "OK",
9619"
9620"		- if the $VIMNOERRTHROW and the $VIMNOINTTHROW control are not
9621"		  configured and exceptions are thrown on error and on
9622"		  interrupt.
9623"
9624"		- if the $VIMNOERRTHROW or the $VIMNOINTTHROW control is
9625"		  configured and works as intended.
9626"
9627"	    What actually happens, is shown in the test output.
9628"
9629"	    Otherwise, the test result is "FAIL", and the test output describes
9630"	    the problem.
9631"
9632" IMPORTANT:  This must be the last test because it sets $VIMNOERRTHROW and
9633"	      $VIMNOINTTHROW.
9634"-------------------------------------------------------------------------------
9635
9636XpathINIT
9637
9638if ExtraVim()
9639
9640    function! ThrowOnError()
9641	XloopNEXT
9642	let caught = 0
9643	try
9644	    Xloop 1				" X: 1 + 8 + 64
9645	    asdf
9646	catch /.*/
9647	    let caught = 1	" error exception caught
9648	finally
9649	    Xloop 2				" X: 2 + 16 + 128
9650	    return caught	" discard aborting error
9651	endtry
9652	Xloop 4					" X: 0
9653    endfunction
9654
9655    let quits_skipped = 0
9656
9657    function! ThrowOnInterrupt()
9658	XloopNEXT
9659	let caught = 0
9660	try
9661	    Xloop 1				" X: (1 + 8 + 64) * 512
9662	    "INTERRUPT3
9663	    let dummy = 0
9664	    let g:quits_skipped = g:quits_skipped + 1
9665	catch /.*/
9666	    let caught = 1	" interrupt exception caught
9667	finally
9668	    Xloop 2				" X: (2 + 16 + 128) * 512
9669	    return caught	" discard interrupt
9670	endtry
9671	Xloop 4					" X: 0
9672    endfunction
9673
9674    function! CheckThrow(Type)
9675	execute 'return ThrowOn' . a:Type . '()'
9676    endfunction
9677
9678    function! CheckConfiguration(type)	    " type is "error" or "interrupt"
9679
9680	let type = a:type
9681	let Type = substitute(type, '.*', '\u&', "")
9682	let VAR = '$VIMNO' . substitute(type, '\(...\).*', '\U\1', "") . 'THROW'
9683
9684	if type == "error"
9685	    XloopINIT! 1 8
9686	elseif type == "interrupt"
9687	    XloopINIT! 512 8
9688	endif
9689
9690	exec 'let requested_for_tests = exists(VAR) && ' . VAR . ' == 0'
9691	exec 'let suppressed_for_tests = ' . VAR . ' != 0'
9692	let used_in_tests = CheckThrow(Type)
9693
9694	exec 'let ' . VAR . ' = 0'
9695	let request_works = CheckThrow(Type)
9696
9697	exec 'let ' . VAR . ' = 1'
9698	let suppress_works = !CheckThrow(Type)
9699
9700	if type == "error"
9701	    XloopINIT! 262144 8
9702	elseif type == "interrupt"
9703	    XloopINIT! 2097152 8
9704
9705	    if g:quits_skipped != 0
9706		Xloop 1				" X: 0*2097152
9707		Xout "Test environment error.  Interrupt breakpoints skipped: "
9708		    \ . g:quits_skipped . ".\n"
9709		    \ . "Cannot check whether interrupt exceptions are thrown."
9710		return
9711	    endif
9712	endif
9713
9714	let failure =
9715	    \ !suppressed_for_tests && !used_in_tests
9716	    \ || !request_works
9717
9718	let contradiction =
9719	    \ used_in_tests
9720		\ ? suppressed_for_tests && !request_works
9721		\ : !suppressed_for_tests
9722
9723	if failure
9724	    " Failure in configuration.
9725	    Xloop 2				" X: 0 * 2*  (262144 + 2097152)
9726	elseif contradiction
9727	    " Failure in test logic.  Should not happen.
9728	    Xloop 4				" X: 0 * 4 * (262144 + 2097152)
9729	endif
9730
9731	let var_control_configured =
9732	    \ request_works != used_in_tests
9733	    \ || suppress_works == used_in_tests
9734
9735	let var_control_not_configured =
9736	    \ requested_for_tests || suppressed_for_tests
9737		\ ? request_works && !suppress_works
9738		\ : request_works == used_in_tests
9739		    \ && suppress_works != used_in_tests
9740
9741	let with = used_in_tests ? "with" : "without"
9742
9743	let set = suppressed_for_tests ? "non-zero" :
9744	    \ requested_for_tests ? "0" : "unset"
9745
9746	let although = contradiction && !var_control_not_configured
9747	    \ ? ",\nalthough "
9748	    \ : ".\n"
9749
9750	let output = "All tests were run " . with . " throwing exceptions on "
9751	    \ . type . although
9752
9753	if !var_control_not_configured
9754	    let output = output . VAR . " was " . set . "."
9755
9756	    if !request_works && !requested_for_tests
9757		let output = output .
9758		    \ "\n" . Type . " exceptions are not thrown when " . VAR .
9759		    \ " is\nset to 0."
9760	    endif
9761
9762	    if !suppress_works && (!used_in_tests ||
9763	    \ !request_works &&
9764	    \ !requested_for_tests && !suppressed_for_tests)
9765		let output = output .
9766		    \ "\n" . Type . " exceptions are thrown when " . VAR .
9767		    \ " is set to 1."
9768	    endif
9769
9770	    if !failure && var_control_configured
9771		let output = output .
9772		    \ "\nRun tests also with " . substitute(VAR, '^\$', '', "")
9773		    \ . "=" . used_in_tests . "."
9774		    \ . "\nThis is for testing in the development phase only."
9775		    \ . "  Remove the \n"
9776		    \ . VAR . " control in the final release."
9777	    endif
9778	else
9779	    let output = output .
9780		\ "The " . VAR . " control is not configured."
9781	endif
9782
9783	Xout output
9784    endfunction
9785
9786    call CheckConfiguration("error")
9787    Xpath 16777216				" X: 16777216
9788    call CheckConfiguration("interrupt")
9789    Xpath 33554432				" X: 33554432
9790endif
9791
9792Xcheck 50443995
9793
9794" IMPORTANT: No test should be added after this test because it changes
9795"	     $VIMNOERRTHROW and $VIMNOINTTHROW.
9796
9797
9798"-------------------------------------------------------------------------------
9799" Modelines								    {{{1
9800" vim: ts=8 sw=4 tw=80 fdm=marker
9801" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "")
9802"-------------------------------------------------------------------------------
9803