1" Test try-catch-finally exception handling
2" Most of this was formerly in test49.
3
4source check.vim
5source shared.vim
6
7"-------------------------------------------------------------------------------
8" Test environment							    {{{1
9"-------------------------------------------------------------------------------
10
11com!		   XpathINIT  let g:Xpath = ''
12com! -nargs=1 -bar Xpath      let g:Xpath = g:Xpath . <args>
13
14" Test 25:  Executing :finally clauses on normal control flow		    {{{1
15"
16"	    Control flow in a :try conditional should always fall through to its
17"	    :finally clause.  A :finally clause of a :try conditional inside an
18"	    inactive conditional should never be executed.
19"-------------------------------------------------------------------------------
20
21func T25_F()
22  let loops = 3
23  while loops > 0
24    Xpath 'a' . loops
25    if loops >= 2
26      try
27        Xpath 'b' . loops
28        if loops == 2
29          try
30            Xpath 'c' . loops
31          finally
32            Xpath 'd' . loops
33          endtry
34        endif
35      finally
36        Xpath 'e' . loops
37        if loops == 2
38          try
39            Xpath 'f' . loops
40          finally
41            Xpath 'g' . loops
42          endtry
43        endif
44      endtry
45    endif
46    Xpath 'h' . loops
47    let loops = loops - 1
48  endwhile
49  Xpath 'i'
50endfunc
51
52func T25_G()
53  if 1
54    try
55      Xpath 'A'
56      call T25_F()
57      Xpath 'B'
58    finally
59      Xpath 'C'
60    endtry
61  else
62    try
63      Xpath 'D'
64    finally
65      Xpath 'E'
66    endtry
67  endif
68endfunc
69
70func Test_finally()
71  XpathINIT
72  call T25_G()
73  call assert_equal('Aa3b3e3h3a2b2c2d2e2f2g2h2a1h1iBC', g:Xpath)
74endfunc
75
76
77"-------------------------------------------------------------------------------
78" Test 26:  Executing :finally clauses after :continue or :break	    {{{1
79"
80"	    For a :continue or :break dynamically enclosed in a :try/:endtry
81"	    region inside the next surrounding :while/:endwhile, if the
82"	    :continue/:break is before the :finally, the :finally clause is
83"	    executed first.  If the :continue/:break is after the :finally, the
84"	    :finally clause is broken (like an :if/:endif region).
85"-------------------------------------------------------------------------------
86
87func T26_F()
88  try
89    let loops = 3
90    while loops > 0
91      try
92        try
93          if loops == 2
94            Xpath 'a' . loops
95            let loops = loops - 1
96            continue
97          elseif loops == 1
98            Xpath 'b' . loops
99            break
100            finish
101          endif
102          Xpath 'c' . loops
103        endtry
104      finally
105        Xpath 'd' . loops
106      endtry
107      Xpath 'e' . loops
108      let loops = loops - 1
109    endwhile
110    Xpath 'f'
111  finally
112    Xpath 'g'
113    let loops = 3
114    while loops > 0
115      try
116      finally
117        try
118          if loops == 2
119            Xpath 'h' . loops
120            let loops = loops - 1
121            continue
122          elseif loops == 1
123            Xpath 'i' . loops
124            break
125            finish
126          endif
127        endtry
128        Xpath 'j' . loops
129      endtry
130      Xpath 'k' . loops
131      let loops = loops - 1
132    endwhile
133    Xpath 'l'
134  endtry
135  Xpath 'm'
136endfunc
137
138func Test_finally_after_continue()
139  XpathINIT
140  call T26_F()
141  call assert_equal('c3d3e3a2d1b1d1fgj3k3h2i1lm', g:Xpath)
142endfunc
143
144
145"-------------------------------------------------------------------------------
146" Test 32:  Remembering the :return value on :finally			    {{{1
147"
148"	    If a :finally clause is executed due to a :return specifying
149"	    a value, this is the value visible to the caller if not overwritten
150"	    by a new :return in the :finally clause.  A :return without a value
151"	    in the :finally clause overwrites with value 0.
152"-------------------------------------------------------------------------------
153
154func T32_F()
155  try
156    Xpath 'a'
157    try
158      Xpath 'b'
159      return "ABCD"
160      Xpath 'c'
161    finally
162      Xpath 'd'
163    endtry
164    Xpath 'e'
165  finally
166    Xpath 'f'
167  endtry
168  Xpath 'g'
169endfunc
170
171func T32_G()
172  try
173    Xpath 'h'
174    return 8
175    Xpath 'i'
176  finally
177    Xpath 'j'
178    return 16 + strlen(T32_F())
179    Xpath 'k'
180  endtry
181  Xpath 'l'
182endfunc
183
184func T32_H()
185  try
186    Xpath 'm'
187    return 32
188    Xpath 'n'
189  finally
190    Xpath 'o'
191    return
192    Xpath 'p'
193  endtry
194  Xpath 'q'
195endfunc
196
197func T32_I()
198  try
199    Xpath 'r'
200  finally
201    Xpath 's'
202    return T32_G() + T32_H() + 64
203    Xpath 't'
204  endtry
205  Xpath 'u'
206endfunc
207
208func Test_finally_return()
209  XpathINIT
210  call assert_equal(84, T32_I())
211  call assert_equal('rshjabdfmo', g:Xpath)
212endfunc
213
214"-------------------------------------------------------------------------------
215" Test 33:  :return under :execute or user command and :finally		    {{{1
216"
217"	    A :return command may be executed under an ":execute" or from
218"	    a user command.  Executing of :finally clauses and passing through
219"	    the return code works also then.
220"-------------------------------------------------------------------------------
221
222func T33_F()
223  try
224    RETURN 10
225    Xpath 'a'
226  finally
227    Xpath 'b'
228  endtry
229  Xpath 'c'
230endfunc
231
232func T33_G()
233  try
234    RETURN 20
235    Xpath 'd'
236  finally
237    Xpath 'e'
238    RETURN 30
239    Xpath 'f'
240  endtry
241  Xpath 'g'
242endfunc
243
244func T33_H()
245  try
246    execute "try | return 40 | finally | return 50 | endtry"
247    Xpath 'h'
248  finally
249    Xpath 'i'
250  endtry
251  Xpath 'j'
252endfunc
253
254func T33_I()
255  try
256    execute "try | return 60 | finally | return 70 | endtry"
257    Xpath 'k'
258  finally
259    Xpath 'l'
260    execute "try | return 80 | finally | return 90 | endtry"
261    Xpath 'm'
262  endtry
263  Xpath 'n'
264endfunc
265
266func T33_J()
267  try
268    RETURN 100
269    Xpath 'o'
270  finally
271    Xpath 'p'
272    return
273    Xpath 'q'
274  endtry
275  Xpath 'r'
276endfunc
277
278func T33_K()
279  try
280    execute "try | return 110 | finally | return 120 | endtry"
281    Xpath 's'
282  finally
283    Xpath 't'
284    execute "try | return 130 | finally | return | endtry"
285    Xpath 'u'
286  endtry
287  Xpath 'v'
288endfunc
289
290func T33_L()
291  try
292    return
293    Xpath 'w'
294  finally
295    Xpath 'x'
296    RETURN 140
297    Xpath 'y'
298  endtry
299  Xpath 'z'
300endfunc
301
302func T33_M()
303  try
304    return
305    Xpath 'A'
306  finally
307    Xpath 'B'
308    execute "try | return 150 | finally | return 160 | endtry"
309    Xpath 'C'
310  endtry
311  Xpath 'D'
312endfunc
313
314func T33_N()
315  RETURN 170
316endfunc
317
318func T33_O()
319  execute "try | return 180 | finally | return 190 | endtry"
320endfunc
321
322func Test_finally_cmd_return()
323  command! -nargs=? RETURN
324        \ try | return <args> | finally | return <args> * 2 | endtry
325  XpathINIT
326  call assert_equal(20, T33_F())
327  call assert_equal(60, T33_G())
328  call assert_equal(50, T33_H())
329  call assert_equal(90, T33_I())
330  call assert_equal(0, T33_J())
331  call assert_equal(0, T33_K())
332  call assert_equal(280, T33_L())
333  call assert_equal(160, T33_M())
334  call assert_equal(340, T33_N())
335  call assert_equal(190, T33_O())
336  call assert_equal('beilptxB', g:Xpath)
337  delcommand RETURN
338endfunc
339
340
341"-------------------------------------------------------------------------------
342" Test 41:  Skipped :throw finding next command				    {{{1
343"
344"	    A :throw in an inactive conditional must not hide a following
345"	    command.
346"-------------------------------------------------------------------------------
347
348func T41_F()
349  Xpath 'a'
350  if 0 | throw 'never' | endif | Xpath 'b'
351  Xpath 'c'
352endfunc
353
354func T41_G()
355  Xpath 'd'
356  while 0 | throw 'never' | endwhile | Xpath 'e'
357  Xpath 'f'
358endfunc
359
360func T41_H()
361  Xpath 'g'
362  if 0 | try | throw 'never' | endtry | endif | Xpath 'h'
363  Xpath 'i'
364endfunc
365
366func Test_throw_inactive_cond()
367  XpathINIT
368  try
369    Xpath 'j'
370    call T41_F()
371    Xpath 'k'
372  catch /.*/
373    Xpath 'l'
374    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
375  endtry
376
377  try
378    Xpath 'm'
379    call T41_G()
380    Xpath 'n'
381  catch /.*/
382    Xpath 'o'
383    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
384  endtry
385
386  try
387    Xpath 'p'
388    call T41_H()
389    Xpath 'q'
390  catch /.*/
391    Xpath 'r'
392    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
393  endtry
394
395  call assert_equal('jabckmdefnpghiq', g:Xpath)
396endfunc
397
398
399"-------------------------------------------------------------------------------
400" Test 42:  Catching number and string exceptions			    {{{1
401"
402"	    When a number is thrown, it is converted to a string exception.
403"	    Numbers and strings may be caught by specifying a regular exception
404"	    as argument to the :catch command.
405"-------------------------------------------------------------------------------
406
407
408func T42_F()
409  try
410
411    try
412      Xpath 'a'
413      throw 4711
414      Xpath 'b'
415    catch /4711/
416      Xpath 'c'
417    endtry
418
419    try
420      Xpath 'd'
421      throw 4711
422      Xpath 'e'
423    catch /^4711$/
424      Xpath 'f'
425    endtry
426
427    try
428      Xpath 'g'
429      throw 4711
430      Xpath 'h'
431    catch /\d/
432      Xpath 'i'
433    endtry
434
435    try
436      Xpath 'j'
437      throw 4711
438      Xpath 'k'
439    catch /^\d\+$/
440      Xpath 'l'
441    endtry
442
443    try
444      Xpath 'm'
445      throw "arrgh"
446      Xpath 'n'
447    catch /arrgh/
448      Xpath 'o'
449    endtry
450
451    try
452      Xpath 'p'
453      throw "arrgh"
454      Xpath 'q'
455    catch /^arrgh$/
456      Xpath 'r'
457    endtry
458
459    try
460      Xpath 's'
461      throw "arrgh"
462      Xpath 't'
463    catch /\l/
464      Xpath 'u'
465    endtry
466
467    try
468      Xpath 'v'
469      throw "arrgh"
470      Xpath 'w'
471    catch /^\l\+$/
472      Xpath 'x'
473    endtry
474
475    try
476      try
477        Xpath 'y'
478        throw "ARRGH"
479        Xpath 'z'
480      catch /^arrgh$/
481        Xpath 'A'
482      endtry
483    catch /^\carrgh$/
484      Xpath 'B'
485    endtry
486
487    try
488      Xpath 'C'
489      throw ""
490      Xpath 'D'
491    catch /^$/
492      Xpath 'E'
493    endtry
494
495  catch /.*/
496    Xpath 'F'
497    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
498  endtry
499endfunc
500
501func Test_catch_number_string()
502  XpathINIT
503  call T42_F()
504  call assert_equal('acdfgijlmoprsuvxyBCE', g:Xpath)
505endfunc
506
507
508"-------------------------------------------------------------------------------
509" Test 43:  Selecting the correct :catch clause				    {{{1
510"
511"	    When an exception is thrown and there are multiple :catch clauses,
512"	    the first matching one is taken.
513"-------------------------------------------------------------------------------
514
515func T43_F()
516  let loops = 3
517  while loops > 0
518    try
519      if loops == 3
520        Xpath 'a' . loops
521        throw "a"
522        Xpath 'b' . loops
523      elseif loops == 2
524        Xpath 'c' . loops
525        throw "ab"
526        Xpath 'd' . loops
527      elseif loops == 1
528        Xpath 'e' . loops
529        throw "abc"
530        Xpath 'f' . loops
531      endif
532    catch /abc/
533      Xpath 'g' . loops
534    catch /ab/
535      Xpath 'h' . loops
536    catch /.*/
537      Xpath 'i' . loops
538    catch /a/
539      Xpath 'j' . loops
540    endtry
541
542    let loops = loops - 1
543  endwhile
544  Xpath 'k'
545endfunc
546
547func Test_multi_catch()
548  XpathINIT
549  call T43_F()
550  call assert_equal('a3i3c2h2e1g1k', g:Xpath)
551endfunc
552
553
554"-------------------------------------------------------------------------------
555" Test 44:  Missing or empty :catch patterns				    {{{1
556"
557"	    A missing or empty :catch pattern means the same as /.*/, that is,
558"	    catches everything.  To catch only empty exceptions, /^$/ must be
559"	    used.  A :catch with missing, empty, or /.*/ argument also works
560"	    when followed by another command separated by a bar on the same
561"	    line.  :catch patterns cannot be specified between ||.  But other
562"	    pattern separators can be used instead of //.
563"-------------------------------------------------------------------------------
564
565func T44_F()
566  try
567    try
568      Xpath 'a'
569      throw ""
570    catch /^$/
571      Xpath 'b'
572    endtry
573
574    try
575      Xpath 'c'
576      throw ""
577    catch /.*/
578      Xpath 'd'
579    endtry
580
581    try
582      Xpath 'e'
583      throw ""
584    catch //
585      Xpath 'f'
586    endtry
587
588    try
589      Xpath 'g'
590      throw ""
591    catch
592      Xpath 'h'
593    endtry
594
595    try
596      Xpath 'i'
597      throw "oops"
598    catch /^$/
599      Xpath 'j'
600    catch /.*/
601      Xpath 'k'
602    endtry
603
604    try
605      Xpath 'l'
606      throw "arrgh"
607    catch /^$/
608      Xpath 'm'
609    catch //
610      Xpath 'n'
611    endtry
612
613    try
614      Xpath 'o'
615      throw "brrr"
616    catch /^$/
617      Xpath 'p'
618    catch
619      Xpath 'q'
620    endtry
621
622    try | Xpath 'r' | throw "x" | catch /.*/ | Xpath 's' | endtry
623
624    try | Xpath 't' | throw "y" | catch // | Xpath 'u' | endtry
625
626    while 1
627      try
628        let caught = 0
629        let v:errmsg = ""
630        " Extra try level:  if ":catch" without arguments below raises
631        " a syntax error because it misinterprets the "Xpath" as a pattern,
632        " let it be caught by the ":catch /.*/" below.
633        try
634          try | Xpath 'v' | throw "z" | catch | Xpath 'w' | :
635          endtry
636        endtry
637      catch /.*/
638        let caught = 1
639        call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
640      finally
641        if $VIMNOERRTHROW && v:errmsg != ""
642          call assert_report(v:errmsg)
643        endif
644        if caught || $VIMNOERRTHROW && v:errmsg != ""
645          Xpath 'x'
646        endif
647        break		" discard error for $VIMNOERRTHROW
648      endtry
649    endwhile
650
651    let cologne = 4711
652    try
653      try
654        Xpath 'y'
655        throw "throw cologne"
656        " Next lines catches all and throws 4711:
657      catch |throw cologne|
658        Xpath 'z'
659      endtry
660    catch /4711/
661      Xpath 'A'
662    endtry
663
664    try
665      Xpath 'B'
666      throw "plus"
667    catch +plus+
668      Xpath 'C'
669    endtry
670
671    Xpath 'D'
672  catch /.*/
673    Xpath 'E'
674    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
675  endtry
676endfunc
677
678func Test_empty_catch()
679  XpathINIT
680  call T44_F()
681  call assert_equal('abcdefghiklnoqrstuvwyABCD', g:Xpath)
682endfunc
683
684
685"-------------------------------------------------------------------------------
686" Test 45:  Catching exceptions from nested :try blocks			    {{{1
687"
688"	    When :try blocks are nested, an exception is caught by the innermost
689"	    try conditional that has a matching :catch clause.
690"-------------------------------------------------------------------------------
691
692func T45_F()
693  let loops = 3
694  while loops > 0
695    try
696      try
697        try
698          try
699            if loops == 3
700              Xpath 'a' . loops
701              throw "a"
702              Xpath 'b' . loops
703            elseif loops == 2
704              Xpath 'c' . loops
705              throw "ab"
706              Xpath 'd' . loops
707            elseif loops == 1
708              Xpath 'e' . loops
709              throw "abc"
710              Xpath 'f' . loops
711            endif
712          catch /abc/
713            Xpath 'g' . loops
714          endtry
715        catch /ab/
716          Xpath 'h' . loops
717        endtry
718      catch /.*/
719        Xpath 'i' . loops
720      endtry
721    catch /a/
722      Xpath 'j' . loops
723    endtry
724
725    let loops = loops - 1
726  endwhile
727  Xpath 'k'
728endfunc
729
730func Test_catch_from_nested_try()
731  XpathINIT
732  call T45_F()
733  call assert_equal('a3i3c2h2e1g1k', g:Xpath)
734endfunc
735
736
737"-------------------------------------------------------------------------------
738" Test 46:  Executing :finally after a :throw in nested :try		    {{{1
739"
740"	    When an exception is thrown from within nested :try blocks, the
741"	    :finally clauses of the non-catching try conditionals should be
742"	    executed before the matching :catch of the next surrounding :try
743"	    gets the control.  If this also has a :finally clause, it is
744"	    executed afterwards.
745"-------------------------------------------------------------------------------
746
747func T46_F()
748  let sum = 0
749
750  try
751    Xpath 'a'
752    try
753      Xpath 'b'
754      try
755        Xpath 'c'
756        try
757          Xpath 'd'
758          throw "ABC"
759          Xpath 'e'
760        catch /xyz/
761          Xpath 'f'
762        finally
763          Xpath 'g'
764          if sum != 0
765            Xpath 'h'
766          endif
767          let sum = sum + 1
768        endtry
769        Xpath 'i'
770      catch /123/
771        Xpath 'j'
772      catch /321/
773        Xpath 'k'
774      finally
775        Xpath 'l'
776        if sum != 1
777          Xpath 'm'
778        endif
779        let sum = sum + 2
780      endtry
781      Xpath 'n'
782    finally
783      Xpath 'o'
784      if sum != 3
785        Xpath 'p'
786      endif
787      let sum = sum + 4
788    endtry
789    Xpath 'q'
790  catch /ABC/
791    Xpath 'r'
792    if sum != 7
793      Xpath 's'
794    endif
795    let sum = sum + 8
796  finally
797    Xpath 't'
798    if sum != 15
799      Xpath 'u'
800    endif
801    let sum = sum + 16
802  endtry
803  Xpath 'v'
804  if sum != 31
805    Xpath 'w'
806  endif
807endfunc
808
809func Test_finally_after_throw()
810  XpathINIT
811  call T46_F()
812  call assert_equal('abcdglortv', g:Xpath)
813endfunc
814
815
816"-------------------------------------------------------------------------------
817" Test 47:  Throwing exceptions from a :catch clause			    {{{1
818"
819"	    When an exception is thrown from a :catch clause, it should not be
820"	    caught by a :catch of the same :try conditional.  After executing
821"	    the :finally clause (if present), surrounding try conditionals
822"	    should be checked for a matching :catch.
823"-------------------------------------------------------------------------------
824
825func T47_F()
826  Xpath 'a'
827  try
828    Xpath 'b'
829    try
830      Xpath 'c'
831      try
832        Xpath 'd'
833        throw "x1"
834        Xpath 'e'
835      catch /x1/
836        Xpath 'f'
837        try
838          Xpath 'g'
839          throw "x2"
840          Xpath 'h'
841        catch /x1/
842          Xpath 'i'
843        catch /x2/
844          Xpath 'j'
845          try
846            Xpath 'k'
847            throw "x3"
848            Xpath 'l'
849          catch /x1/
850            Xpath 'm'
851          catch /x2/
852            Xpath 'n'
853          finally
854            Xpath 'o'
855          endtry
856          Xpath 'p'
857        catch /x3/
858          Xpath 'q'
859        endtry
860        Xpath 'r'
861      catch /x1/
862        Xpath 's'
863      catch /x2/
864        Xpath 't'
865      catch /x3/
866        Xpath 'u'
867      finally
868        Xpath 'v'
869      endtry
870      Xpath 'w'
871    catch /x1/
872      Xpath 'x'
873    catch /x2/
874      Xpath 'y'
875    catch /x3/
876      Xpath 'z'
877    endtry
878    Xpath 'A'
879  catch /.*/
880    Xpath 'B'
881    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
882  endtry
883  Xpath 'C'
884endfunc
885
886func Test_throw_from_catch()
887  XpathINIT
888  call T47_F()
889  call assert_equal('abcdfgjkovzAC', g:Xpath)
890endfunc
891
892
893"-------------------------------------------------------------------------------
894" Test 48:  Throwing exceptions from a :finally clause			    {{{1
895"
896"	    When an exception is thrown from a :finally clause, it should not be
897"	    caught by a :catch of the same :try conditional.  Surrounding try
898"	    conditionals should be checked for a matching :catch.  A previously
899"	    thrown exception is discarded.
900"-------------------------------------------------------------------------------
901
902func T48_F()
903  try
904
905    try
906      try
907        Xpath 'a'
908      catch /x1/
909        Xpath 'b'
910      finally
911        Xpath 'c'
912        throw "x1"
913        Xpath 'd'
914      endtry
915      Xpath 'e'
916    catch /x1/
917      Xpath 'f'
918    endtry
919    Xpath 'g'
920
921    try
922      try
923        Xpath 'h'
924        throw "x2"
925        Xpath 'i'
926      catch /x2/
927        Xpath 'j'
928      catch /x3/
929        Xpath 'k'
930      finally
931        Xpath 'l'
932        throw "x3"
933        Xpath 'm'
934      endtry
935      Xpath 'n'
936    catch /x2/
937      Xpath 'o'
938    catch /x3/
939      Xpath 'p'
940    endtry
941    Xpath 'q'
942
943    try
944      try
945        try
946          Xpath 'r'
947          throw "x4"
948          Xpath 's'
949        catch /x5/
950          Xpath 't'
951        finally
952          Xpath 'u'
953          throw "x5"	" discards 'x4'
954          Xpath 'v'
955        endtry
956        Xpath 'w'
957      catch /x4/
958        Xpath 'x'
959      finally
960        Xpath 'y'
961      endtry
962      Xpath 'z'
963    catch /x5/
964      Xpath 'A'
965    endtry
966    Xpath 'B'
967
968  catch /.*/
969    Xpath 'C'
970    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
971  endtry
972  Xpath 'D'
973endfunc
974
975func Test_throw_from_finally()
976  XpathINIT
977  call T48_F()
978  call assert_equal('acfghjlpqruyABD', g:Xpath)
979endfunc
980
981
982"-------------------------------------------------------------------------------
983" Test 51:  Throwing exceptions across :execute and user commands	    {{{1
984"
985"	    A :throw command may be executed under an ":execute" or from
986"	    a user command.
987"-------------------------------------------------------------------------------
988
989func T51_F()
990  command! -nargs=? THROW1    throw <args> | throw 1
991  command! -nargs=? THROW2    try | throw <args> | endtry | throw 2
992  command! -nargs=? THROW3    try | throw 3 | catch /3/ | throw <args> | endtry
993  command! -nargs=? THROW4    try | throw 4 | finally   | throw <args> | endtry
994
995  try
996
997    try
998      try
999        Xpath 'a'
1000        THROW1 "A"
1001      catch /A/
1002        Xpath 'b'
1003      endtry
1004    catch /1/
1005      Xpath 'c'
1006    endtry
1007
1008    try
1009      try
1010        Xpath 'd'
1011        THROW2 "B"
1012      catch /B/
1013        Xpath 'e'
1014      endtry
1015    catch /2/
1016      Xpath 'f'
1017    endtry
1018
1019    try
1020      try
1021        Xpath 'g'
1022        THROW3 "C"
1023      catch /C/
1024        Xpath 'h'
1025      endtry
1026    catch /3/
1027      Xpath 'i'
1028    endtry
1029
1030    try
1031      try
1032        Xpath 'j'
1033        THROW4 "D"
1034      catch /D/
1035        Xpath 'k'
1036      endtry
1037    catch /4/
1038      Xpath 'l'
1039    endtry
1040
1041    try
1042      try
1043        Xpath 'm'
1044        execute 'throw "E" | throw 5'
1045      catch /E/
1046        Xpath 'n'
1047      endtry
1048    catch /5/
1049      Xpath 'o'
1050    endtry
1051
1052    try
1053      try
1054        Xpath 'p'
1055        execute 'try | throw "F" | endtry | throw 6'
1056      catch /F/
1057        Xpath 'q'
1058      endtry
1059    catch /6/
1060      Xpath 'r'
1061    endtry
1062
1063    try
1064      try
1065        Xpath 's'
1066        execute'try | throw 7 | catch /7/ | throw "G" | endtry'
1067      catch /G/
1068        Xpath 't'
1069      endtry
1070    catch /7/
1071      Xpath 'u'
1072    endtry
1073
1074    try
1075      try
1076        Xpath 'v'
1077        execute 'try | throw 8 | finally   | throw "H" | endtry'
1078      catch /H/
1079        Xpath 'w'
1080      endtry
1081    catch /8/
1082      Xpath 'x'
1083    endtry
1084
1085  catch /.*/
1086    Xpath 'y'
1087    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1088  endtry
1089
1090  Xpath 'z'
1091
1092  delcommand THROW1
1093  delcommand THROW2
1094  delcommand THROW3
1095  delcommand THROW4
1096endfunc
1097
1098func Test_throw_across_commands()
1099  XpathINIT
1100  call T51_F()
1101  call assert_equal('abdeghjkmnpqstvwz', g:Xpath)
1102endfunc
1103
1104
1105
1106"-------------------------------------------------------------------------------
1107" Test 69:  :throw across :if, :elseif, :while				    {{{1
1108"
1109"	    On an :if, :elseif, or :while command, an exception might be thrown
1110"	    during evaluation of the expression to test.  The exception can be
1111"	    caught by the script.
1112"-------------------------------------------------------------------------------
1113
1114func T69_throw(x)
1115  Xpath 'x'
1116  throw a:x
1117endfunc
1118
1119func Test_throw_ifelsewhile()
1120  XpathINIT
1121
1122  try
1123    try
1124      Xpath 'a'
1125      if 111 == T69_throw("if") + 111
1126        Xpath 'b'
1127      else
1128        Xpath 'c'
1129      endif
1130      Xpath 'd'
1131    catch /^if$/
1132      Xpath 'e'
1133    catch /.*/
1134      Xpath 'f'
1135      call assert_report("if: " . v:exception . " in " . v:throwpoint)
1136    endtry
1137
1138    try
1139      Xpath 'g'
1140      if v:false
1141        Xpath 'h'
1142      elseif 222 == T69_throw("elseif") + 222
1143        Xpath 'i'
1144      else
1145        Xpath 'j'
1146      endif
1147      Xpath 'k'
1148    catch /^elseif$/
1149      Xpath 'l'
1150    catch /.*/
1151      Xpath 'm'
1152      call assert_report("elseif: " . v:exception . " in " . v:throwpoint)
1153    endtry
1154
1155    try
1156      Xpath 'n'
1157      while 333 == T69_throw("while") + 333
1158        Xpath 'o'
1159        break
1160      endwhile
1161      Xpath 'p'
1162    catch /^while$/
1163      Xpath 'q'
1164    catch /.*/
1165      Xpath 'r'
1166      call assert_report("while: " .. v:exception .. " in " .. v:throwpoint)
1167    endtry
1168  catch /^0$/	    " default return value
1169    Xpath 's'
1170    call assert_report(v:throwpoint)
1171  catch /.*/
1172    call assert_report(v:exception .. " in " .. v:throwpoint)
1173    Xpath 't'
1174  endtry
1175
1176  call assert_equal('axegxlnxq', g:Xpath)
1177endfunc
1178
1179
1180"-------------------------------------------------------------------------------
1181" Test 70:  :throw across :return or :throw				    {{{1
1182"
1183"	    On a :return or :throw command, an exception might be thrown during
1184"	    evaluation of the expression to return or throw, respectively.  The
1185"	    exception can be caught by the script.
1186"-------------------------------------------------------------------------------
1187
1188let T70_taken = ""
1189
1190func T70_throw(x, n)
1191    let g:T70_taken = g:T70_taken . "T" . a:n
1192    throw a:x
1193endfunc
1194
1195func T70_F(x, y, n)
1196    let g:T70_taken = g:T70_taken . "F" . a:n
1197    return a:x + T70_throw(a:y, a:n)
1198endfunc
1199
1200func T70_G(x, y, n)
1201    let g:T70_taken = g:T70_taken . "G" . a:n
1202    throw a:x . T70_throw(a:y, a:n)
1203    return a:x
1204endfunc
1205
1206func Test_throwreturn()
1207  XpathINIT
1208
1209  try
1210    try
1211      Xpath 'a'
1212      call T70_F(4711, "return", 1)
1213      Xpath 'b'
1214    catch /^return$/
1215      Xpath 'c'
1216    catch /.*/
1217      Xpath 'd'
1218      call assert_report("return: " .. v:exception .. " in " .. v:throwpoint)
1219    endtry
1220
1221    try
1222      Xpath 'e'
1223      let var = T70_F(4712, "return-var", 2)
1224      Xpath 'f'
1225    catch /^return-var$/
1226      Xpath 'g'
1227    catch /.*/
1228      Xpath 'h'
1229      call assert_report("return-var: " . v:exception . " in " . v:throwpoint)
1230    finally
1231      unlet! var
1232    endtry
1233
1234    try
1235      Xpath 'i'
1236      throw "except1" . T70_throw("throw1", 3)
1237      Xpath 'j'
1238    catch /^except1/
1239      Xpath 'k'
1240    catch /^throw1$/
1241      Xpath 'l'
1242    catch /.*/
1243      Xpath 'm'
1244      call assert_report("throw1: " .. v:exception .. " in " .. v:throwpoint)
1245    endtry
1246
1247    try
1248      Xpath 'n'
1249      call T70_G("except2", "throw2", 4)
1250      Xpath 'o'
1251    catch /^except2/
1252      Xpath 'p'
1253    catch /^throw2$/
1254      Xpath 'q'
1255    catch /.*/
1256      Xpath 'r'
1257      call assert_report("throw2: " .. v:exception .. " in " .. v:throwpoint)
1258    endtry
1259
1260    try
1261      Xpath 's'
1262      let var = T70_G("except3", "throw3", 5)
1263      Xpath 't'
1264    catch /^except3/
1265      Xpath 'u'
1266    catch /^throw3$/
1267      Xpath 'v'
1268    catch /.*/
1269      Xpath 'w'
1270      call assert_report("throw3: " .. v:exception .. " in " .. v:throwpoint)
1271    finally
1272      unlet! var
1273    endtry
1274
1275    call assert_equal('F1T1F2T2T3G4T4G5T5', g:T70_taken)
1276    Xpath 'x'
1277  catch /^0$/	    " default return value
1278    Xpath 'y'
1279    call assert_report(v:throwpoint)
1280  catch /.*/
1281    Xpath 'z'
1282    call assert_report('Caught' .. v:exception .. ' in ' .. v:throwpoint)
1283  endtry
1284
1285  call assert_equal('acegilnqsvx', g:Xpath)
1286endfunc
1287
1288"-------------------------------------------------------------------------------
1289" Test 71:  :throw across :echo variants and :execute			    {{{1
1290"
1291"	    On an :echo, :echon, :echomsg, :echoerr, or :execute command, an
1292"	    exception might be thrown during evaluation of the arguments to
1293"	    be displayed or executed as a command, respectively.  Any following
1294"	    arguments are not evaluated, then.  The exception can be caught by
1295"	    the script.
1296"-------------------------------------------------------------------------------
1297
1298let T71_taken = ""
1299
1300func T71_throw(x, n)
1301    let g:T71_taken = g:T71_taken . "T" . a:n
1302    throw a:x
1303endfunc
1304
1305func T71_F(n)
1306    let g:T71_taken = g:T71_taken . "F" . a:n
1307    return "F" . a:n
1308endfunc
1309
1310func Test_throw_echo()
1311  XpathINIT
1312
1313  try
1314    try
1315      Xpath 'a'
1316      echo 'echo ' . T71_throw("echo-except", 1) . T71_F(1)
1317      Xpath 'b'
1318    catch /^echo-except$/
1319      Xpath 'c'
1320    catch /.*/
1321      Xpath 'd'
1322      call assert_report("echo: " .. v:exception .. " in " .. v:throwpoint)
1323    endtry
1324
1325    try
1326      Xpath 'e'
1327      echon "echon " . T71_throw("echon-except", 2) . T71_F(2)
1328      Xpath 'f'
1329    catch /^echon-except$/
1330      Xpath 'g'
1331    catch /.*/
1332      Xpath 'h'
1333      call assert_report('echon: ' . v:exception . ' in ' . v:throwpoint)
1334    endtry
1335
1336    try
1337      Xpath 'i'
1338      echomsg "echomsg " . T71_throw("echomsg-except", 3) . T71_F(3)
1339      Xpath 'j'
1340    catch /^echomsg-except$/
1341      Xpath 'k'
1342    catch /.*/
1343      Xpath 'l'
1344      call assert_report('echomsg: ' . v:exception . ' in ' . v:throwpoint)
1345    endtry
1346
1347    try
1348      Xpath 'm'
1349      echoerr "echoerr " . T71_throw("echoerr-except", 4) . T71_F(4)
1350      Xpath 'n'
1351    catch /^echoerr-except$/
1352      Xpath 'o'
1353    catch /Vim/
1354      Xpath 'p'
1355    catch /echoerr/
1356      Xpath 'q'
1357    catch /.*/
1358      Xpath 'r'
1359      call assert_report('echoerr: ' . v:exception . ' in ' . v:throwpoint)
1360    endtry
1361
1362    try
1363      Xpath 's'
1364      execute "echo 'execute " . T71_throw("execute-except", 5) . T71_F(5) "'"
1365      Xpath 't'
1366    catch /^execute-except$/
1367      Xpath 'u'
1368    catch /.*/
1369      Xpath 'v'
1370      call assert_report('execute: ' . v:exception . ' in ' . v:throwpoint)
1371    endtry
1372
1373    call assert_equal('T1T2T3T4T5', g:T71_taken)
1374    Xpath 'w'
1375  catch /^0$/	    " default return value
1376    Xpath 'x'
1377    call assert_report(v:throwpoint)
1378  catch /.*/
1379    Xpath 'y'
1380    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1381  endtry
1382
1383  call assert_equal('acegikmosuw', g:Xpath)
1384endfunc
1385
1386
1387"-------------------------------------------------------------------------------
1388" Test 72:  :throw across :let or :unlet				    {{{1
1389"
1390"	    On a :let command, an exception might be thrown during evaluation
1391"	    of the expression to assign.  On an :let or :unlet command, the
1392"	    evaluation of the name of the variable to be assigned or list or
1393"	    deleted, respectively, may throw an exception.  Any following
1394"	    arguments are not evaluated, then.  The exception can be caught by
1395"	    the script.
1396"-------------------------------------------------------------------------------
1397
1398let throwcount = 0
1399
1400func T72_throw(x)
1401  let g:throwcount = g:throwcount + 1
1402  throw a:x
1403endfunc
1404
1405let T72_addpath = ''
1406
1407func T72_addpath(p)
1408  let g:T72_addpath = g:T72_addpath . a:p
1409endfunc
1410
1411func Test_throw_let()
1412  XpathINIT
1413
1414  try
1415    try
1416      let $VAR = 'old_value'
1417      Xpath 'a'
1418      let $VAR = 'let(' . T72_throw('var') . ')'
1419      Xpath 'b'
1420    catch /^var$/
1421      Xpath 'c'
1422    finally
1423      call assert_equal('old_value', $VAR)
1424    endtry
1425
1426    try
1427      let @a = 'old_value'
1428      Xpath 'd'
1429      let @a = 'let(' . T72_throw('reg') . ')'
1430      Xpath 'e'
1431    catch /^reg$/
1432      try
1433        Xpath 'f'
1434        let @A = 'let(' . T72_throw('REG') . ')'
1435        Xpath 'g'
1436      catch /^REG$/
1437        Xpath 'h'
1438      endtry
1439    finally
1440      call assert_equal('old_value', @a)
1441      call assert_equal('old_value', @A)
1442    endtry
1443
1444    try
1445      let saved_gpath = &g:path
1446      let saved_lpath = &l:path
1447      Xpath 'i'
1448      let &path = 'let(' . T72_throw('opt') . ')'
1449      Xpath 'j'
1450    catch /^opt$/
1451      try
1452        Xpath 'k'
1453        let &g:path = 'let(' . T72_throw('gopt') . ')'
1454        Xpath 'l'
1455      catch /^gopt$/
1456        try
1457          Xpath 'm'
1458          let &l:path = 'let(' . T72_throw('lopt') . ')'
1459          Xpath 'n'
1460        catch /^lopt$/
1461          Xpath 'o'
1462        endtry
1463      endtry
1464    finally
1465      call assert_equal(saved_gpath, &g:path)
1466      call assert_equal(saved_lpath, &l:path)
1467      let &g:path = saved_gpath
1468      let &l:path = saved_lpath
1469    endtry
1470
1471    unlet! var1 var2 var3
1472
1473    try
1474      Xpath 'p'
1475      let var1 = 'let(' . T72_throw('var1') . ')'
1476      Xpath 'q'
1477    catch /^var1$/
1478      Xpath 'r'
1479    finally
1480      call assert_true(!exists('var1'))
1481    endtry
1482
1483    try
1484      let var2 = 'old_value'
1485      Xpath 's'
1486      let var2 = 'let(' . T72_throw('var2'). ')'
1487      Xpath 't'
1488    catch /^var2$/
1489      Xpath 'u'
1490    finally
1491      call assert_equal('old_value', var2)
1492    endtry
1493
1494    try
1495      Xpath 'v'
1496      let var{T72_throw('var3')} = 4711
1497      Xpath 'w'
1498    catch /^var3$/
1499      Xpath 'x'
1500    endtry
1501
1502    try
1503      call T72_addpath('T1')
1504      let var{T72_throw('var4')} var{T72_addpath('T2')} | call T72_addpath('T3')
1505      call T72_addpath('T4')
1506    catch /^var4$/
1507      call T72_addpath('T5')
1508    endtry
1509
1510    try
1511      call T72_addpath('T6')
1512      unlet var{T72_throw('var5')} var{T72_addpath('T7')}
1513            \ | call T72_addpath('T8')
1514      call T72_addpath('T9')
1515    catch /^var5$/
1516      call T72_addpath('T10')
1517    endtry
1518
1519    call assert_equal('T1T5T6T10', g:T72_addpath)
1520    call assert_equal(11, g:throwcount)
1521  catch /.*/
1522    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1523  endtry
1524
1525  call assert_equal('acdfhikmoprsuvx', g:Xpath)
1526endfunc
1527
1528
1529"-------------------------------------------------------------------------------
1530" Test 73:  :throw across :function, :delfunction			    {{{1
1531"
1532"	    The :function and :delfunction commands may cause an expression
1533"	    specified in braces to be evaluated.  During evaluation, an
1534"	    exception might be thrown.  The exception can be caught by the
1535"	    script.
1536"-------------------------------------------------------------------------------
1537
1538let T73_taken = ''
1539
1540func T73_throw(x, n)
1541  let g:T73_taken = g:T73_taken . 'T' . a:n
1542  throw a:x
1543endfunc
1544
1545func T73_expr(x, n)
1546  let g:T73_taken = g:T73_taken . 'E' . a:n
1547  if a:n % 2 == 0
1548    call T73_throw(a:x, a:n)
1549  endif
1550  return 2 - a:n % 2
1551endfunc
1552
1553func Test_throw_func()
1554  XpathINIT
1555
1556  try
1557    try
1558      " Define function.
1559      Xpath 'a'
1560      function! F0()
1561      endfunction
1562      Xpath 'b'
1563      function! F{T73_expr('function-def-ok', 1)}()
1564      endfunction
1565      Xpath 'c'
1566      function! F{T73_expr('function-def', 2)}()
1567      endfunction
1568      Xpath 'd'
1569    catch /^function-def-ok$/
1570      Xpath 'e'
1571    catch /^function-def$/
1572      Xpath 'f'
1573    catch /.*/
1574      call assert_report('def: ' . v:exception . ' in ' . v:throwpoint)
1575    endtry
1576
1577    try
1578      " List function.
1579      Xpath 'g'
1580      function F0
1581      Xpath 'h'
1582      function F{T73_expr('function-lst-ok', 3)}
1583      Xpath 'i'
1584      function F{T73_expr('function-lst', 4)}
1585      Xpath 'j'
1586    catch /^function-lst-ok$/
1587      Xpath 'k'
1588    catch /^function-lst$/
1589      Xpath 'l'
1590    catch /.*/
1591      call assert_report('lst: ' . v:exception . ' in ' . v:throwpoint)
1592    endtry
1593
1594    try
1595      " Delete function
1596      Xpath 'm'
1597      delfunction F0
1598      Xpath 'n'
1599      delfunction F{T73_expr('function-del-ok', 5)}
1600      Xpath 'o'
1601      delfunction F{T73_expr('function-del', 6)}
1602      Xpath 'p'
1603    catch /^function-del-ok$/
1604      Xpath 'q'
1605    catch /^function-del$/
1606      Xpath 'r'
1607    catch /.*/
1608      call assert_report('del: ' . v:exception . ' in ' . v:throwpoint)
1609    endtry
1610    call assert_equal('E1E2T2E3E4T4E5E6T6', g:T73_taken)
1611  catch /.*/
1612    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1613  endtry
1614
1615  call assert_equal('abcfghilmnor', g:Xpath)
1616endfunc
1617
1618
1619"-------------------------------------------------------------------------------
1620" Test 74:  :throw across builtin functions and commands		    {{{1
1621"
1622"	    Some functions like exists(), searchpair() take expression
1623"	    arguments, other functions or commands like substitute() or
1624"	    :substitute cause an expression (specified in the regular
1625"	    expression) to be evaluated.  During evaluation an exception
1626"	    might be thrown.  The exception can be caught by the script.
1627"-------------------------------------------------------------------------------
1628
1629let T74_taken = ""
1630
1631func T74_throw(x, n)
1632  let g:T74_taken = g:T74_taken . "T" . a:n
1633  throw a:x
1634endfunc
1635
1636func T74_expr(x, n)
1637  let g:T74_taken = g:T74_taken . "E" . a:n
1638  call T74_throw(a:x . a:n, a:n)
1639  return "EXPR"
1640endfunc
1641
1642func T74_skip(x, n)
1643  let g:T74_taken = g:T74_taken . "S" . a:n . "(" . line(".")
1644  let theline = getline(".")
1645  if theline =~ "skip"
1646    let g:T74_taken = g:T74_taken . "s)"
1647    return 1
1648  elseif theline =~ "throw"
1649    let g:T74_taken = g:T74_taken . "t)"
1650    call T74_throw(a:x . a:n, a:n)
1651  else
1652    let g:T74_taken = g:T74_taken . ")"
1653    return 0
1654  endif
1655endfunc
1656
1657func T74_subst(x, n)
1658  let g:T74_taken = g:T74_taken . "U" . a:n . "(" . line(".")
1659  let theline = getline(".")
1660  if theline =~ "not"       " T74_subst() should not be called for this line
1661    let g:T74_taken = g:T74_taken . "n)"
1662    call T74_throw(a:x . a:n, a:n)
1663  elseif theline =~ "throw"
1664    let g:T74_taken = g:T74_taken . "t)"
1665    call T74_throw(a:x . a:n, a:n)
1666  else
1667    let g:T74_taken = g:T74_taken . ")"
1668    return "replaced"
1669  endif
1670endfunc
1671
1672func Test_throw_builtin_func()
1673  XpathINIT
1674
1675  try
1676    try
1677      Xpath 'a'
1678      let result = exists('*{T74_expr("exists", 1)}')
1679      Xpath 'b'
1680    catch /^exists1$/
1681      Xpath 'c'
1682      try
1683        let result = exists('{T74_expr("exists", 2)}')
1684        Xpath 'd'
1685      catch /^exists2$/
1686        Xpath 'e'
1687      catch /.*/
1688        call assert_report('exists2: ' . v:exception . ' in ' . v:throwpoint)
1689      endtry
1690    catch /.*/
1691      call assert_report('exists1: ' . v:exception . ' in ' . v:throwpoint)
1692    endtry
1693
1694    try
1695      let file = tempname()
1696      exec "edit" file
1697      call append(0, [
1698            \ 'begin',
1699            \ 'xx',
1700            \ 'middle 3',
1701            \ 'xx',
1702            \ 'middle 5 skip',
1703            \ 'xx',
1704            \ 'middle 7 throw',
1705            \ 'xx',
1706            \ 'end'])
1707      normal! gg
1708      Xpath 'f'
1709      let result = searchpair("begin", "middle", "end", '',
1710            \ 'T74_skip("searchpair", 3)')
1711      Xpath 'g'
1712      let result = searchpair("begin", "middle", "end", '',
1713            \ 'T74_skip("searchpair", 4)')
1714      Xpath 'h'
1715      let result = searchpair("begin", "middle", "end", '',
1716            \ 'T74_skip("searchpair", 5)')
1717      Xpath 'i'
1718    catch /^searchpair[35]$/
1719      Xpath 'j'
1720    catch /^searchpair4$/
1721      Xpath 'k'
1722    catch /.*/
1723      call assert_report('searchpair: ' . v:exception . ' in ' . v:throwpoint)
1724    finally
1725      bwipeout!
1726      call delete(file)
1727    endtry
1728
1729    try
1730      let file = tempname()
1731      exec "edit" file
1732      call append(0, [
1733            \ 'subst 1',
1734            \ 'subst 2',
1735            \ 'not',
1736            \ 'subst 4',
1737            \ 'subst throw',
1738            \ 'subst 6'])
1739      normal! gg
1740      Xpath 'l'
1741      1,2substitute/subst/\=T74_subst("substitute", 6)/
1742      try
1743        Xpath 'm'
1744        try
1745          let v:errmsg = ""
1746          3substitute/subst/\=T74_subst("substitute", 7)/
1747        finally
1748          if v:errmsg != ""
1749            " If exceptions are not thrown on errors, fake the error
1750            " exception in order to get the same execution path.
1751            throw "faked Vim(substitute)"
1752          endif
1753        endtry
1754      catch /Vim(substitute)/	    " Pattern not found ('e' flag missing)
1755        Xpath 'n'
1756        3substitute/subst/\=T74_subst("substitute", 8)/e
1757        Xpath 'o'
1758      endtry
1759      Xpath 'p'
1760      4,6substitute/subst/\=T74_subst("substitute", 9)/
1761      Xpath 'q'
1762    catch /^substitute[678]/
1763      Xpath 'r'
1764    catch /^substitute9/
1765      Xpath 's'
1766    finally
1767      bwipeout!
1768      call delete(file)
1769    endtry
1770
1771    try
1772      Xpath 't'
1773      let var = substitute("sub", "sub", '\=T74_throw("substitute()y", 10)', '')
1774      Xpath 'u'
1775    catch /substitute()y/
1776      Xpath 'v'
1777    catch /.*/
1778      call assert_report('substitute()y: ' . v:exception . ' in '
1779            \ . v:throwpoint)
1780    endtry
1781
1782    try
1783      Xpath 'w'
1784      let var = substitute("not", "sub", '\=T74_throw("substitute()n", 11)', '')
1785      Xpath 'x'
1786    catch /substitute()n/
1787      Xpath 'y'
1788    catch /.*/
1789      call assert_report('substitute()n: ' . v:exception . ' in '
1790            \ . v:throwpoint)
1791    endtry
1792
1793    call assert_equal('E1T1E2T2S3(3)S4(5s)S4(7t)T4U6(1)U6(2)U9(4)U9(5t)T9T10',
1794          \ g:T74_taken)
1795
1796  catch /.*/
1797    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1798  endtry
1799
1800  call assert_equal('acefgklmnopstvwx', g:Xpath)
1801endfunc
1802
1803
1804"-------------------------------------------------------------------------------
1805" Test 75:  Errors in builtin functions.				    {{{1
1806"
1807"	    On an error in a builtin function called inside a :try/:endtry
1808"	    region, the evaluation of the expression calling that function and
1809"	    the command containing that expression are abandoned.  The error can
1810"	    be caught as an exception.
1811"
1812"	    A simple :call of the builtin function is a trivial case.  If the
1813"	    builtin function is called in the argument list of another function,
1814"	    no further arguments are evaluated, and the other function is not
1815"	    executed.  If the builtin function is called from the argument of
1816"	    a :return command, the :return command is not executed.  If the
1817"	    builtin function is called from the argument of a :throw command,
1818"	    the :throw command is not executed.  The evaluation of the
1819"	    expression calling the builtin function is abandoned.
1820"-------------------------------------------------------------------------------
1821
1822func T75_F1(arg1)
1823  Xpath 'a'
1824endfunc
1825
1826func T75_F2(arg1, arg2)
1827  Xpath 'b'
1828endfunc
1829
1830func T75_G()
1831  Xpath 'c'
1832endfunc
1833
1834func T75_H()
1835  Xpath 'd'
1836endfunc
1837
1838func T75_R()
1839  while 1
1840    try
1841      let caught = 0
1842      let v:errmsg = ""
1843      Xpath 'e'
1844      return append(1, "s")
1845    catch /E21/
1846      let caught = 1
1847    catch /.*/
1848      Xpath 'f'
1849    finally
1850      Xpath 'g'
1851      if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1852        Xpath 'h'
1853      endif
1854      break		" discard error for $VIMNOERRTHROW
1855    endtry
1856  endwhile
1857  Xpath 'i'
1858endfunc
1859
1860func Test_builtin_func_error()
1861  XpathINIT
1862
1863  try
1864    set noma	" let append() fail with "E21"
1865
1866    while 1
1867      try
1868        let caught = 0
1869        let v:errmsg = ""
1870        Xpath 'j'
1871        call append(1, "s")
1872      catch /E21/
1873        let caught = 1
1874      catch /.*/
1875        Xpath 'k'
1876      finally
1877        Xpath 'l'
1878        if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1879          Xpath 'm'
1880        endif
1881        break		" discard error for $VIMNOERRTHROW
1882      endtry
1883    endwhile
1884
1885    while 1
1886      try
1887        let caught = 0
1888        let v:errmsg = ""
1889        Xpath 'n'
1890        call T75_F1('x' . append(1, "s"))
1891      catch /E21/
1892        let caught = 1
1893      catch /.*/
1894        Xpath 'o'
1895      finally
1896        Xpath 'p'
1897        if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1898          Xpath 'q'
1899        endif
1900        break		" discard error for $VIMNOERRTHROW
1901      endtry
1902    endwhile
1903
1904    while 1
1905      try
1906        let caught = 0
1907        let v:errmsg = ""
1908        Xpath 'r'
1909        call T75_F2('x' . append(1, "s"), T75_G())
1910      catch /E21/
1911        let caught = 1
1912      catch /.*/
1913        Xpath 's'
1914      finally
1915        Xpath 't'
1916        if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1917          Xpath 'u'
1918        endif
1919        break		" discard error for $VIMNOERRTHROW
1920      endtry
1921    endwhile
1922
1923    call T75_R()
1924
1925    while 1
1926      try
1927        let caught = 0
1928        let v:errmsg = ""
1929        Xpath 'v'
1930        throw "T" . append(1, "s")
1931      catch /E21/
1932        let caught = 1
1933      catch /^T.*/
1934        Xpath 'w'
1935      catch /.*/
1936        Xpath 'x'
1937      finally
1938        Xpath 'y'
1939        if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1940          Xpath 'z'
1941        endif
1942        break		" discard error for $VIMNOERRTHROW
1943      endtry
1944    endwhile
1945
1946    while 1
1947      try
1948        let caught = 0
1949        let v:errmsg = ""
1950        Xpath 'A'
1951        let x = "a"
1952        let x = x . "b" . append(1, "s") . T75_H()
1953      catch /E21/
1954        let caught = 1
1955      catch /.*/
1956        Xpath 'B'
1957      finally
1958        Xpath 'C'
1959        if caught || $VIMNOERRTHROW && v:errmsg =~ 'E21'
1960          Xpath 'D'
1961        endif
1962        call assert_equal('a', x)
1963        break		" discard error for $VIMNOERRTHROW
1964      endtry
1965    endwhile
1966  catch /.*/
1967    call assert_report('Caught ' . v:exception . ' in ' . v:throwpoint)
1968  finally
1969    set ma&
1970  endtry
1971
1972  call assert_equal('jlmnpqrtueghivyzACD', g:Xpath)
1973endfunc
1974
1975" Modelines								    {{{1
1976" vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker
1977"-------------------------------------------------------------------------------
1978