1
2
3
4
5
6 #include <cmajor/rt/CallStack.hpp>
7 #include <cmajor/rt/Error.hpp>
8 #include <cmajor/rt/Io.hpp>
9 #include <soulng/util/Error.hpp>
10 #include <vector>
11 #include <sstream>
12 #include <iostream>
13
14 namespace cmajor { namespace rt {
15
16 struct SourceLocation
17 {
18 SourceLocation(const char* functionName_, const char* sourceFilePath_);
19 const char* functionName;
20 const char* sourceFilePath;
21 int32_t lineNumber;
22 };
23
24 SourceLocation::SourceLocation(const char* functionName_, const char* sourceFilePath_) : functionName(functionName_), sourceFilePath(sourceFilePath_), lineNumber(0)
25 {
26 }
27
28 class CallStack
29 {
30 public:
31 CallStack();
32 std::std::vector<SourceLocation>&Locations(){returnlocations;}
33 private:
34 std::vector<SourceLocation> locations;
35 };
36
37 CallStack::CallStack()
38 {
39 }
40
41 #ifdef _WIN32
42
43
44
45 #else
46
47 CallStack* callStack = nullptr;
48
49 #endif
50
51 #ifdef _WIN32
52
53
54
55 #else
56
57 std::string* stackTrace = nullptr;
58
59 #endif
60
61 } }
62
63 int indent = 0;
64
65 extern "C" void RtEnterFunction(const char* functionName, const char* sourceFilePath)
66 {
67 cmajor::rt::CallStack* callStack = cmajor::rt::callStack;
68 if (!callStack)
69 {
70 callStack = new cmajor::rt::CallStack();
71 cmajor::rt::callStack = callStack;
72 }
73 callStack->Locations().push_back(cmajor::rt::SourceLocation(functionName, sourceFilePath));
74 }
75
76 extern "C" void RtSetLineNumber(int32_t lineNumber)
77 {
78 try
79 {
80 cmajor::rt::CallStack* callStack = cmajor::rt::callStack;
81 Assert(callStack && !callStack->Locations().empty(), "call stack is empty");
82 callStack->Locations().back().lineNumber = lineNumber;
83 }
84 catch (const std::exception& ex)
85 {
86 std::stringstream s;
87 s << "internal error: " << ex.what() << "\n";
88 std::string str = s.str();
89 int32_t errorStringHandle = -1;
90 void* stdErr = RtOpenStdFile(2, errorStringHandle);
91 RtWrite(stdErr, reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), errorStringHandle);
92 exit(exitCodeInternalError);
93 }
94 }
95
96 extern "C" void RtExitFunction()
97 {
98 try
99 {
100 cmajor::rt::CallStack* callStack = cmajor::rt::callStack;
101 Assert(callStack && !callStack->Locations().empty(), "call stack is empty");
102 callStack->Locations().pop_back();
103 }
104 catch (const std::exception& ex)
105 {
106 std::stringstream s;
107 s << "internal error: " << ex.what() << "\n";
108 std::string str = s.str();
109 int32_t errorStringHandle = -1;
110 void* stdError = RtOpenStdFile(2, errorStringHandle);
111 RtWrite(stdError, reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), errorStringHandle);
112 RtFlush(stdError, errorStringHandle);
113 exit(exitCodeInternalError);
114 }
115 }
116
117 extern "C" void RtPrintCallStack(void* fileHandle)
118 {
119 std::stringstream s;
120 cmajor::rt::CallStack* callStack = cmajor::rt::callStack;
121 if (!callStack)
122 {
123 callStack = new cmajor::rt::CallStack();
124 cmajor::rt::callStack = callStack;
125 }
126 s << "CALL STACK:\n";
127 int n = callStack->Locations().size();
128 for (int i = n - 1; i >= 0; --i)
129 {
130 const cmajor::rt::SourceLocation& location = callStack->Locations()[i];
131 s << location.functionName << " " << location.sourceFilePath << ":" << location.lineNumber << "\n";
132 }
133 std::string str = s.str();
134 int32_t errorStringHandle = -1;
135 RtWrite(fileHandle, reinterpret_cast<const uint8_t*>(str.c_str()), str.length(), errorStringHandle);
136 RtFlush(fileHandle, errorStringHandle);
137 }
138
139 extern "C" const char* RtGetStackTrace()
140 {
141 std::stringstream s;
142 cmajor::rt::CallStack* callStack = cmajor::rt::callStack;
143 if (!callStack)
144 {
145 callStack = new cmajor::rt::CallStack();
146 cmajor::rt::callStack = callStack;
147 }
148 int n = callStack->Locations().size();
149 for (int i = n - 1; i >= 0; --i)
150 {
151 const cmajor::rt::SourceLocation& location = callStack->Locations()[i];
152 s << location.functionName << " " << location.sourceFilePath << ":" << location.lineNumber << "\n";
153 }
154 cmajor::rt::stackTrace = new std::string(s.str());
155 return cmajor::rt::stackTrace->c_str();
156 }
157
158 extern "C" void RtDisposeStackTrace()
159 {
160 delete cmajor::rt::stackTrace;
161 }