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