-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcommon.h
112 lines (94 loc) · 3.33 KB
/
common.h
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
/**
* Copyright © 2019 Andrey Nevolin, https://github.com/AndreyNevolin
* Twitter: @Andrey_Nevolin
* LinkedIn: https://www.linkedin.com/in/andrey-nevolin-76387328
*
* Common tools that can be used by all modules:
* - assertions
* - debugging
* - logging
*/
#ifndef _PEF_COMMON_H_
#define _PEF_COMMON_H_
#ifdef PEF_DEBUG
#include <execinfo.h>
#include <cstdio>
#include <cstdlib>
#endif
#include "errno.h"
#include "string.h"
/**
* Maximum size of error messages generated by PEF. This value is used when declaring
* (or allocating memory for) a buffer intended for storing an error message
*/
#define PEF_ERR_MSG_SIZE 500
/*
* Macro that evaluates to 1 if PEF should use non-negative return values. In the
* opposite case the macro evaluates to -1.
* PEF takes care of its return values' sign to avoid interference with reserved error
* codes. Only one such 'reserved code' is relevant for now. Namely, PTHREAD_CANCELED
*/
#define PEF_RET_SIGN ((long)PTHREAD_CANCELED < 0 ? 1 : -1)
/* Return value that indicates generic error */
#define PEF_RET_GENERIC_ERR (PEF_RET_SIGN * 1)
#ifdef PEF_DEBUG
/**
* Print stack dump
*/
static inline void pef_PrintStack()
{
void *frames[100];
size_t stack_depth;
char **calls;
fprintf( stderr, "Stack trace: \n");
stack_depth = backtrace( frames, 100);
calls = backtrace_symbols( frames, stack_depth);
for ( size_t i = 0; i < stack_depth; i++ )
{
printf ("\t[%2lu] %s\n", stack_depth - i - 1, calls[i]);
}
free( calls);
}
#define PEF_ABORT \
fprintf( stderr, "\n"), \
fprintf( stderr, "Internal error: file \"%s\", line %u\n", __FILE__, __LINE__), \
fprintf( stderr, "\n"), \
fflush( NULL), \
pef_PrintStack(), \
abort()
#endif /* PEF_DEBUG */
#ifdef PEF_DEBUG
# define PEF_ASSERT( condition_) ((condition_) || (PEF_ABORT, 0))
#else
# define PEF_ASSERT( condition_)
#endif
#define PEF_OUT( format_, ...) \
fprintf( stdout, format_, ##__VA_ARGS__), \
fprintf( stdout, "\n")
#define PEF_EMIT_ERR_MSG( format_, ...) \
fprintf( stderr, format_, ##__VA_ARGS__), \
fprintf( stderr, "\n") \
#define PEF_ERROR( ...) \
PEF_EMIT_ERR_MSG( __VA_ARGS__), \
exit( EXIT_FAILURE)
/**
* Print formatted error message to the specified buffer
* Just a shortcut to make error-processing code more compact
*/
#define PEF_BUFF_MSG( buff_, buff_size_, format_, ...) \
if ( buff_ ) \
{ \
snprintf( buff_, buff_size_, format_, ##__VA_ARGS__); \
/* Precaution in case the string doesn't fit the buffer */ \
buff_[buff_size_ - 1] = '\0'; \
}
/**
* Wrapper around "strerror_r()" aimed at making calls to
* "strerror_r()" more compact and manageable
*/
static inline char *PEF_STRERROR_R( char *buff, size_t size)
{
PEF_ASSERT( buff);
return strerror_r( errno, buff, size);
}
#endif /* _PEF_COMMON_H_ */