-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathOSFixes.hpp
More file actions
251 lines (223 loc) · 8.7 KB
/
OSFixes.hpp
File metadata and controls
251 lines (223 loc) · 8.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
#ifndef __OSFIXES__H
#define __OSFIXES__H
#include <string>
#include <string.h>
/* =============================================================================
* =============================================================================
* OS/compiler-specific oddities to make code as portable as possible.
*
*
* =============================================================================
* ===========================================================================*/
/* =============================================================================
* Avoid format warnings on MINGW from it trying to use old MSVc printf
* ===========================================================================*/
#if defined(__MINGW64__) || defined(__MINGW32__)
#define __USE_MINGW_ANSI_STDIO 1
#endif
/* =============================================================================
* Headers for fixed-width ints (i.e. uint64_t) depend on c++ version.
* These are needed for addresses.
* ===========================================================================*/
#if __cplusplus >= 201103
#include <cstdint>
#include <cinttypes>
#else
#include <stdint.h>
#ifndef __BORLANDC__ // Borland doesn't know about inttypes.h,
#include <inttypes.h> // despite knowing about stdint.h...
#endif
#include <sstream>
#endif
/* =============================================================================
* Pointer/Address formatting depends on C++ & Compiler version.
*
* C++98 doesn't necessarily know about long-long and long is not 64-bits on all
* compiler/platform combinations. To complicate matters, uint64_t (inittpypes.h
* /cinittypes) is not consistently typed across platforms. e.g. it is long on
* Ubuntu 16.04 GCC but long long on MinGW 64-bit.
* Relies on inttypes.h/cinittypes.
*
* Example Usage:
* fprintf(fp, "Pointer: %" PTR_FMT "\n", static_cast<uint64_t>(&Var);
* ===========================================================================*/
#define PTR_FMT "#018" PRIx64
#define SYMA_FMT "#018" PRIx64
#define HWA_FMT "#010" PRIx32
#define SWA_FMT "#010" PRIx32
/* =============================================================================
* Handle NULL<>nullptr for C++98 and C++11+ compatibility.
*
* C++11 complains about using NULL as it compares a pointer to 0, which is NOT
* portable according to the standard. C++98 does not have nullptr.
*
* Usage is anywhere that you would use NULL or nullptr
* ===========================================================================*/
#if __cplusplus >= 201103 // C++11+ land
#define PNULL nullptr
#else
#define PNULL NULL
#endif
/* =============================================================================
* Offer a to_string method for C++98
* ===========================================================================*/
#if __cplusplus >= 201103 // C++11+ land
#define TO_STRING std::to_string
#else // C++98 land
#define TO_STRING OSFixes::to_string
namespace OSFixes
{
template<typename T>
std::string to_string(const T& value)
{
std::ostringstream oss;
oss << value;
return oss.str();
}
}
#endif
/* =============================================================================
* Quick and dirty cross-platform method to get error string from error code.
*
* When called with "errno", this will return an std::string containing the
* relevant error text for the last failed system call.
*
* The "default" option (using sterror) is NOT thread safe, but is portable.
* Other options (using sterror_s and friends) need adding for Windows/Borland.
*
* Example Usage:
* std::cout << OSFixes::getSysErrorString(errno) << std::endl;
* ===========================================================================*/
namespace OSFixes
{
inline std::string getSysErrorString(int errNum)
{
#if (_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && _GNU_SOURCE
char errMsg[1000];
return std::string(strerror_r(errNum, errMsg, 1000));
#elif _POSIX_C_SOURCE >= 200112L
char errMsg[1000];
if(strerror_r(errNum, errMsg, 1000)) return std::string("");
else return std::string(errMsg);
#else
return std::string(strerror(errNum));
#endif
}
}
/* =============================================================================
* Macros for indicating that variables may be unused by design.
*
* Example use cases include common code (e.g. softswitch) where user-provided
* code is inserted into pre-defined methods.
*
* OS_ATTRIBUTE_UNUSED Placed immedidiately after potentially unused var.
* OS_PRAGMA_UNUSED(x) Placed on a line after a potentially unused var.
*
* Example Usage:
* unsigned foo OS_ATTRIBUTE_UNUSED = 0;
* OS_PRAGMA_UNUSED(foo) // N.B. note the lack of ";"
* ===========================================================================*/
#ifdef __GNUC__ /* GCC Specific definitions. */
#define OS_ATTRIBUTE_UNUSED __attribute__((unused))
#define OS_PRAGMA_UNUSED(x)
#elif __BORLANDC__ /* Borland specific definitions. */
#define OS_ATTRIBUTE_UNUSED
#define OS_PRAGMA_UNUSED(x) (void) x ;
#elif __clang__ /* Clang Specific definitions. */
#define OS_ATTRIBUTE_UNUSED
#define OS_PRAGMA_UNUSED(x) #pragma unused(x);
#elif _MSC_VER /* MS Specific definitions. */
#define OS_ATTRIBUTE_UNUSED
#define OS_PRAGMA_UNUSED(x) x;
#else /* Other compilers. */
#warning "Building without Compiler-specific unused variable handling."
#define OS_ATTRIBUTE_UNUSED
#define OS_PRAGMA_UNUSED(x)
#endif
/* =============================================================================
* Hostname retrieval, as a string.
* ===========================================================================*/
#ifdef _WIN32
#else /* Unix-like way */
#include <unistd.h>
#define HOSTNAME_LENGTH 128
#endif
namespace OSFixes
{
inline std::string get_hostname()
{
#ifdef _WIN32
printf("[OSFixes::get_hostname] MLV should edit this to use "
"GetComputerNameExA!\n"); // <!>
return "";
#else
char buffer[HOSTNAME_LENGTH];
gethostname(buffer, HOSTNAME_LENGTH);
return buffer;
#endif
}
}
/* =============================================================================
* Filesystem manipulation - not under RISCV though.
* ===========================================================================*/
#ifndef __riscv
#ifdef _WIN32
#include <stdlib.h>
#include <windows.h>
#define MAXIMUM_PATH_LENGTH MAX_PATH /* Actually, MAX_PATH isn't. See
https://stackoverflow.com/questions/833291/is-there-an-equivalent-to-winapis
-max-path-under-linux-unix */
#else /* Unix-like way */
#include <libgen.h>
#include <linux/limits.h>
#include <unistd.h>
#define MAXIMUM_PATH_LENGTH PATH_MAX /* Actually, PATH_MAX isn't. See
http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html */
#endif
namespace OSFixes
{
/* Returns the directory component of 'fullPath'. Don't pass in a path to a
* directory unless you know what you're doing. */
inline std::string dirname(std::string fullPath)
{
#ifdef _WIN32
printf("[OSFixes::dirname] MLV should edit this to use "
"Generics/filename!\n"); // <!>
return "";
#else
/* FYI: The function '::dirname' refers to dirname in the global
* namespace. Another pitfall: The const_cast is implicitly trusting
* ::dirname not to modify the path passed in. */
return ::dirname(const_cast<char*>(fullPath.c_str()));
#endif
}
/* Gets the path to the executable calling this function. Note that this
* will not get the object. Returns a string containing the path if
* successful, and returns an empty string otherwise. */
inline std::string get_executable_path()
{
char path[MAXIMUM_PATH_LENGTH] = {}; /* Empty initialiser to placate
* Valgrind. */
/* Determining the predicate by OS. Value resolution is independent. */
#ifdef _WIN32
HMODULE hModule = GetModuleHandle(PNULL);
if (hModule != PNULL)
{
GetModuleFileName(hModule, path, sizeof(path));
#else /* Unix-like way. If you want to harden this further, look at the
* man page for readlink, at:
* http://man7.org/linux/man-pages/man2/readlink.2.html#EXAMPLE */
if (readlink("/proc/self/exe", path, MAXIMUM_PATH_LENGTH))
{
#endif
return path;
}
else
{
return "";
}
}
}
#endif /* _riscv */
/* ===========================================================================*/
#endif /* __OSFIXES__H */