1// Author: Ali ��ehreli
2// See https://forum.dlang.org/post/o2n7f8$2p1t$1@digitalmars.com
3
4import core.stdc.stdio;
5
6class TestException : Exception
7{
8    this(string msg)
9    {
10        super(typeof(this).stringof~": "~msg);
11    }
12}
13
14class TestError : Error
15{
16    this(string msg)
17    {
18        super(typeof(this).stringof~": "~msg);
19    }
20}
21
22// Causes an exception chain where the node at index errorIndex is an
23// Error (others are all Exceptions).
24void causeExceptionChain(size_t chainLength, size_t errorIndex)
25{
26    void throws(size_t n)
27    {
28        scope (exit)
29        {
30            string msg = [ cast(char)('a'+n) ].idup;
31            if (n == errorIndex)
32            {
33                throw new TestError(msg);
34            }
35            else
36            {
37                throw new TestException(msg);
38            }
39        }
40
41        if (n != 0)
42        {
43            // Redundant 'return' keyword due to
44            // https://issues.dlang.org/show_bug.cgi?id=16960
45            return throws(n - 1);
46        }
47    }
48
49    throws(chainLength - 1);
50}
51
52void main()
53{
54    try
55    {
56        // -1 would mean "no Error in the chain". Change this to a
57        // number between 0 and 4 (inclusive) then you will realize
58        // that the Exception below will not be caught.
59        size_t errorIndex = 3;
60        causeExceptionChain(5, errorIndex);
61    }
62    catch (Error original)
63    {
64        printf("Caught\n");
65        string prefix = "";
66        for ({ size_t i; Throwable ex = original; } ex; ex = ex.next, ++i)
67        {
68            printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr);
69            prefix = prefix~" ";
70        }
71        printf("Bypassed chain was:\n");
72        prefix = "";
73        for ({ size_t i; Throwable ex = original.bypassedException; } ex; ex = ex.next, ++i)
74        {
75            printf("%.*s%.*s\n", cast(int)prefix.length, prefix.ptr, cast(int)ex.msg.length, ex.msg.ptr);
76            prefix = prefix~" ";
77        }
78    }
79}
80