1*58b9f456SAndroid Build Coastguard Worker #ifndef SUPPORT_ASSERT_CHECKPOINT_H
2*58b9f456SAndroid Build Coastguard Worker #define SUPPORT_ASSERT_CHECKPOINT_H
3*58b9f456SAndroid Build Coastguard Worker
4*58b9f456SAndroid Build Coastguard Worker #include <csignal>
5*58b9f456SAndroid Build Coastguard Worker #include <iostream>
6*58b9f456SAndroid Build Coastguard Worker #include <cstdlib>
7*58b9f456SAndroid Build Coastguard Worker
8*58b9f456SAndroid Build Coastguard Worker struct Checkpoint {
9*58b9f456SAndroid Build Coastguard Worker const char* file;
10*58b9f456SAndroid Build Coastguard Worker const char* func;
11*58b9f456SAndroid Build Coastguard Worker int line;
12*58b9f456SAndroid Build Coastguard Worker const char* msg;
13*58b9f456SAndroid Build Coastguard Worker
CheckpointCheckpoint14*58b9f456SAndroid Build Coastguard Worker Checkpoint() : file(nullptr), func(nullptr), line(-1), msg(nullptr) {}
CheckpointCheckpoint15*58b9f456SAndroid Build Coastguard Worker Checkpoint(const char* xfile, const char* xfunc, int xline, const char* xmsg)
16*58b9f456SAndroid Build Coastguard Worker : file(xfile), func(xfunc), line(xline), msg(xmsg)
17*58b9f456SAndroid Build Coastguard Worker {}
18*58b9f456SAndroid Build Coastguard Worker
19*58b9f456SAndroid Build Coastguard Worker template <class Stream>
printCheckpoint20*58b9f456SAndroid Build Coastguard Worker void print(Stream& s) const {
21*58b9f456SAndroid Build Coastguard Worker if (!file) {
22*58b9f456SAndroid Build Coastguard Worker s << "NO CHECKPOINT\n";
23*58b9f456SAndroid Build Coastguard Worker return;
24*58b9f456SAndroid Build Coastguard Worker }
25*58b9f456SAndroid Build Coastguard Worker s << file << ":" << line << " " << func << ": Checkpoint";
26*58b9f456SAndroid Build Coastguard Worker if (msg)
27*58b9f456SAndroid Build Coastguard Worker s << " '" << msg << "'";
28*58b9f456SAndroid Build Coastguard Worker s << std::endl;
29*58b9f456SAndroid Build Coastguard Worker }
30*58b9f456SAndroid Build Coastguard Worker };
31*58b9f456SAndroid Build Coastguard Worker
globalCheckpoint()32*58b9f456SAndroid Build Coastguard Worker inline Checkpoint& globalCheckpoint() {
33*58b9f456SAndroid Build Coastguard Worker static Checkpoint C;
34*58b9f456SAndroid Build Coastguard Worker return C;
35*58b9f456SAndroid Build Coastguard Worker }
36*58b9f456SAndroid Build Coastguard Worker
clearCheckpoint()37*58b9f456SAndroid Build Coastguard Worker inline void clearCheckpoint() {
38*58b9f456SAndroid Build Coastguard Worker globalCheckpoint() = Checkpoint();
39*58b9f456SAndroid Build Coastguard Worker }
40*58b9f456SAndroid Build Coastguard Worker
41*58b9f456SAndroid Build Coastguard Worker #if defined(__GNUC__)
42*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT_FUNCTION_NAME __PRETTY_FUNCTION__
43*58b9f456SAndroid Build Coastguard Worker #else
44*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT_FUNCTION_NAME __func__
45*58b9f456SAndroid Build Coastguard Worker #endif
46*58b9f456SAndroid Build Coastguard Worker
47*58b9f456SAndroid Build Coastguard Worker #define CHECKPOINT(msg) globalCheckpoint() = Checkpoint(__FILE__, CHECKPOINT_FUNCTION_NAME, __LINE__, msg);
48*58b9f456SAndroid Build Coastguard Worker
checkpointSignalHandler(int signal)49*58b9f456SAndroid Build Coastguard Worker inline void checkpointSignalHandler(int signal) {
50*58b9f456SAndroid Build Coastguard Worker if (signal == SIGABRT) {
51*58b9f456SAndroid Build Coastguard Worker globalCheckpoint().print(std::cerr);
52*58b9f456SAndroid Build Coastguard Worker } else {
53*58b9f456SAndroid Build Coastguard Worker std::cerr << "Unexpected signal " << signal << " received\n";
54*58b9f456SAndroid Build Coastguard Worker }
55*58b9f456SAndroid Build Coastguard Worker std::_Exit(EXIT_FAILURE);
56*58b9f456SAndroid Build Coastguard Worker }
57*58b9f456SAndroid Build Coastguard Worker
initCheckpointHandler()58*58b9f456SAndroid Build Coastguard Worker inline bool initCheckpointHandler() {
59*58b9f456SAndroid Build Coastguard Worker typedef void(*HandlerT)(int);
60*58b9f456SAndroid Build Coastguard Worker static bool isInit = false;
61*58b9f456SAndroid Build Coastguard Worker if (isInit) return true;
62*58b9f456SAndroid Build Coastguard Worker HandlerT prev_h = std::signal(SIGABRT, checkpointSignalHandler);
63*58b9f456SAndroid Build Coastguard Worker if (prev_h == SIG_ERR) {
64*58b9f456SAndroid Build Coastguard Worker std::cerr << "Setup failed.\n";
65*58b9f456SAndroid Build Coastguard Worker std::_Exit(EXIT_FAILURE);
66*58b9f456SAndroid Build Coastguard Worker }
67*58b9f456SAndroid Build Coastguard Worker isInit = true;
68*58b9f456SAndroid Build Coastguard Worker return false;
69*58b9f456SAndroid Build Coastguard Worker }
70*58b9f456SAndroid Build Coastguard Worker
71*58b9f456SAndroid Build Coastguard Worker static bool initDummy = initCheckpointHandler();
72*58b9f456SAndroid Build Coastguard Worker
73*58b9f456SAndroid Build Coastguard Worker #endif
74