GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
Globals.h
Go to the documentation of this file.
1#ifndef GLOBALS_H
2#define GLOBALS_H
3
4// NOLINTBEGIN(cppcoreguidelines-macro-usage)
5#define RESET_COLOR "\033[m"
6#define BLUE "\033[1;34m"
7#define YELLOW "\033[1;33m"
8#define GREEN "\033[1;32m"
9#define RED "\033[1;31m"
10#define BLACK "\033[1;30m"
11#define MAGENTA "\033[1;35m"
12#define CYAN "\033[1;36m"
13#define WHITE "\033[1;37m"
14
15#define DBLUE "\033[0;34m"
16#define DYELLOW "\033[0;33m"
17#define DGREEN "\033[0;32m"
18#define DRED "\033[0;31m"
19#define DBLACK "\033[0;30m"
20#define DMAGENTA "\033[0;35m"
21#define DCYAN "\033[0;36m"
22#define DWHITE "\033[0;37m"
23
24#define BG_WHITE "\033[47m"
25#define BG_RED "\033[41m"
26#define BG_GREEN "\033[42m"
27#define BG_YELLOW "\033[43m"
28#define BG_BLUE "\033[44m"
29#define BG_MAGENTA "\033[45m"
30#define BG_CYAN "\033[46m"
31
32#define HIDE_CURSOR "\033[?25l"
33#define SHOW_CURSOR "\033[?25h"
34
35#define ALERTTEXT "\033[47m\033[0;31m"
36// NOLINTEND(cppcoreguidelines-macro-usage)
37
38#if __APPLE__
39#ifdef __CINT__
40#undef __GNUC__
41typedef char __signed;
42typedef char int8_t;
43#endif
44#endif
45
46#if __APPLE__
47//#include <_types/_uint8_t.h>
48#include <_types/_uint16_t.h>
49#include <_types/_uint32_t.h>
50#include <_types/_uint64_t.h>
51#include <sys/_types/_int16_t.h>
52#else
53#include <cstdint>
54#endif
55
56#include <iostream>
57#include <iomanip>
58#include <stdexcept>
59#include <string>
60#include <cstdio>
61#include <cstdlib>
62#include <execinfo.h>
63#include <cxxabi.h>
64#include <sstream>
65#include <array>
66#include <memory>
67#include <unistd.h>
68
69#include "TEnv.h"
70
71const std::string& ProgramName();
72
73namespace grsi {
74struct exit_exception : public std::exception {
75public:
76 explicit exit_exception(int c, const char* msg = "") : code(c), message(msg) {}
77 /* virtual const char* what() const throw {
78 // LOG(what); // write to log file
79 return what.c_str();
80 }*/
81
82 const int code;
83 const char* message;
84};
85
86void SetGRSIEnv();
87
88//-------------------- three function templates that print all arguments into a string
89// this template uses existing stream and appends the last argument to it
90template <typename T>
91void Append(std::ostringstream& stream, const T& tail)
92{
93 // append last argument
94 stream << tail;
95}
96
97// this template uses existing stream and appends to it
98template <typename T, typename... U>
99void Append(std::ostringstream& stream, const T& head, const U&... tail)
100{
101 // append first argument
102 stream << head;
103
104 // reversely call this template (or the one with the last argument)
105 Append(stream, tail...);
106}
107
108// this function typically gets called by user
109template <typename T, typename... U>
110std::string Stringify(const T& head, const U&... tail)
111{
112 // print first arguments to string
113 std::ostringstream stream;
114 stream << head;
115
116 // call the second template (or the third if tail is just one argument)
117 Append(stream, tail...);
118
119 // append a newline
120 stream << std::endl;
121
122 // return resulting string
123 return stream.str();
124}
125
126} // end of namespace grsi
127
128template <typename T>
129inline std::string hex(T val, int width = -1)
130{
131 std::ostringstream str;
132 str << "0x" << std::hex;
133 if(width > 0) {
134 str << std::setfill('0') << std::setw(width);
135 }
136 str << val;
137 if(width > 0) {
138 str << std::setfill(' ');
139 }
140 return str.str();
141}
142
143enum EVerbosity : int {
148 kAll = 4
150
151static inline std::string getexepath()
152{
153 std::array<char, 1024> result{};
154 ssize_t count = readlink("/proc/self/exe", result.data(), sizeof(result) - 1);
155 return {result.data(), static_cast<size_t>((count > 0) ? count : 0)};
156}
157
158static inline std::string sh(const std::string& cmd)
159{
160 std::array<char, 128> buffer{};
161 std::string result;
162 std::shared_ptr<FILE> pipe(popen(cmd.c_str(), "r"), pclose);
163 if(!pipe) { throw std::runtime_error("popen() failed!"); }
164 while(feof(pipe.get()) == 0) {
165 if(fgets(buffer.data(), 128, pipe.get()) != nullptr) {
166 result += buffer.data();
167 }
168 }
169 return result;
170}
171
172// print a demangled stack backtrace of the caller function (copied from https://panthema.net/2008/0901-stacktrace-demangled/)
173static inline void PrintStacktrace(std::ostream& out = std::cout, int maxFrames = 63)
174{
175 std::ostringstream output;
176 output << "stack trace:" << std::endl;
177
178 // storage array for stack trace address data
179 void** addrlist = new void*[maxFrames + 1];
180
181 // retrieve current stack addresses
182 int addrlen = backtrace(addrlist, maxFrames + 1);
183
184 if(addrlen == 0) {
185 output << " <empty, possibly corrupt>" << std::endl;
186 out << output.str();
187 return;
188 }
189
190 // resolve addresses into strings containing "filename(function+address)",
191 // this array must be free()-ed
192 char** symbollist = backtrace_symbols(addrlist, addrlen);
193
194 // allocate string which will be filled with the demangled function name
195 size_t funcnamesize = 256;
196 auto* funcname = new char[funcnamesize];
197
198 // iterate over the returned symbol lines. skip the first, it is the
199 // address of this function.
200 for(int i = 2; i < addrlen; i++) {
201 char* begin_name = nullptr;
202 char* begin_offset = nullptr;
203 char* end_offset = nullptr;
204
205 // find parentheses and +address offset surrounding the mangled name:
206 // ./module(function+0x15c) [0x8048a6d]
207 for(char* p = symbollist[i]; *p != 0; ++p) {
208 if(*p == '(') {
209 begin_name = p;
210 } else if(*p == '+') {
211 begin_offset = p;
212 } else if(*p == ')' && begin_offset != nullptr) {
213 end_offset = p;
214 break;
215 }
216 }
217
218 // try and decode file and line number (only if we have an absolute path)
219 // std::string line;
220 // if(symbollist[i][0] == '/') {
221 // std::ostringstream command;
222 // std::string filename = symbollist[i];
223 // command<<"addr2line "<<addrlist[i]<<" -e "<<filename.substr(0, filename.find_first_of('('));
224 // //std::cout<<symbollist[i]<<": executing command "<<command.str()<<std::endl;
225 // line = sh(command.str());
226 //}
227
228 if(begin_name != nullptr && begin_offset != nullptr && end_offset != nullptr && begin_name < begin_offset) {
229 *begin_name++ = '\0';
230 *begin_offset++ = '\0';
231 *end_offset = '\0';
232
233 // mangled name is now in [begin_name, begin_offset) and caller
234 // offset in [begin_offset, end_offset). now apply
235 // __cxa_demangle():
236
237 int status = 0;
238 char* ret = abi::__cxa_demangle(begin_name, funcname, &funcnamesize, &status);
239 if(status == 0) {
240 funcname = ret; // use possibly realloc()-ed string
241 output << " " << symbollist[i] << ": " << funcname << "+" << begin_offset << std::endl;
242 } else {
243 // demangling failed. Output function name as a C function with
244 // no arguments.
245 output << " " << symbollist[i] << ": " << begin_name << "()+" << begin_offset << std::endl;
246 }
247 } else {
248 // couldn't parse the line? print the whole line.
249 output << " " << symbollist[i] << std::endl;
250 }
251 // output << line;
252 }
253
254 delete[] funcname;
255 delete symbollist;
256 out << output.str();
257}
258
259#if !__APPLE__
260#include <sys/wait.h>
261#include <sys/prctl.h>
262static inline void PrintGdbStacktrace()
263{
264 std::array<char, 30> pid_buf{};
265 sprintf(pid_buf.data(), "%d", getpid());
266 std::array<char, 512> name_buf{};
267 name_buf[readlink("/proc/self/exe", name_buf.data(), 511)] = 0;
268 prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
269 int child_pid = fork();
270 if(child_pid == 0) {
271 dup2(2, 1); // redirect output to stderr - edit: unnecessary?
272 execl("/usr/bin/gdb", "gdb", "--batch", "-n", "-ex", "thread", "-ex", "bt", name_buf.data(), pid_buf.data(), nullptr);
273 abort(); /* If gdb failed to start */
274 } else {
275 waitpid(child_pid, nullptr, 0);
276 }
277}
278#endif
279
280#endif
static std::string getexepath()
Definition Globals.h:151
static std::string sh(const std::string &cmd)
Definition Globals.h:158
static void PrintGdbStacktrace()
Definition Globals.h:262
EVerbosity
Definition Globals.h:143
@ kQuiet
Definition Globals.h:144
@ kSubroutines
Definition Globals.h:146
@ kLoops
Definition Globals.h:147
@ kAll
Definition Globals.h:148
@ kBasicFlow
Definition Globals.h:145
static void PrintStacktrace(std::ostream &out=std::cout, int maxFrames=63)
Definition Globals.h:173
std::string hex(T val, int width=-1)
Definition Globals.h:129
const std::string & ProgramName()
Definition Globals.h:73
void Append(std::ostringstream &stream, const T &tail)
Definition Globals.h:91
std::string Stringify(const T &head, const U &... tail)
Definition Globals.h:110
void SetGRSIEnv()
Definition Globals.cxx:3
exit_exception(int c, const char *msg="")
Definition Globals.h:76
const char * message
Definition Globals.h:83