| // REQUIRED_ARGS: -g |
| // REQUIRED_ARGS(linux freebsd dragonflybsd): -L-export-dynamic |
| // PERMUTE_ARGS: |
| // DISABLED: osx |
| |
| import core.stdc.stdio; |
| |
| void main() |
| { |
| fun(1); |
| fun(2); |
| fun(3); |
| #line 30 |
| fun(4); |
| |
| foo(1, 10); |
| foo(2, 10); |
| foo(3, 10); |
| #line 40 |
| foo(4, 10); |
| } |
| |
| void fun(int n, int defParam = 10) |
| { |
| try |
| { |
| if (n == 4) |
| throw new Exception("fun"); |
| } |
| catch(Exception e) |
| { |
| string s = e.toString(); |
| printf("%.*s\n", cast(int)s.length, s.ptr); |
| int line = lineInMain(e.toString()); |
| assert(line >= 30 && line <= 32); // return address might be next statement |
| } |
| } |
| |
| void foo(int n, int m) |
| { |
| try |
| { |
| if (n == 4) |
| throw new Exception("foo"); |
| } |
| catch(Exception e) |
| { |
| string s = e.toString(); |
| printf("%.*s\n", cast(int)s.length, s.ptr); |
| int line = lineInMain(e.toString()); |
| assert(line >= 40 && line <= 41); // return address might be next statement |
| } |
| } |
| |
| int lineInMain(string msg) |
| { |
| // find line number of _Dmain in stack trace |
| // on linux: file.d:line _Dmain [addr] |
| // on windows: addr in _Dmain at file.d(line) |
| int line = 0; |
| bool mainFound = false; |
| for (size_t pos = 0; pos + 6 < msg.length; pos++) |
| { |
| if (msg[pos] == '\n') |
| { |
| line = 0; |
| mainFound = false; |
| } |
| else if ((msg[pos] == ':' || msg[pos] == '(') && line == 0) |
| { |
| for (pos++; pos < msg.length && msg[pos] >= '0' && msg[pos] <= '9'; pos++) |
| line = line * 10 + msg[pos] - '0'; |
| if (line > 0 && mainFound) |
| return line; |
| } |
| else if (msg[pos .. pos + 6] == "_Dmain" || msg[pos .. pos + 6] == "D main") |
| { |
| mainFound = true; |
| if (line > 0 && mainFound) |
| return line; |
| } |
| } |
| return 0; |
| } |