Subversion Repositories QNX 8.QNX8 IFS tool

Rev

Rev 23 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
16 pmbaty 1
#ifndef UTILITY_H
2
#define UTILITY_H
3
 
4
 
5
#ifdef __cplusplus
6
extern "C" {
7
#endif
8
 
9
 
10
// standard C includes
11
#include <stdint.h>
12
#include <time.h>
13
 
14
 
15
// bring TLS support to antique compilers
16
#ifndef thread_local
17
#ifdef _MSC_VER
18
#define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23
19
#else // a saner compiler
20
#define thread_local _Thread_local // the thread_local keyword wasn't defined before C++11 and C23
21
#endif // _MSC_VER
22
#endif // !thread_local
23
 
24
 
25
// Microsoft-specific shims
26
#ifdef _MSC_VER
19 pmbaty 27
#include <stdarg.h>
28
#include <io.h>
29
#include <direct.h>
16 pmbaty 30
#if defined(_M_AMD64)
31
#define __x86_64__ 1
32
#elif defined(_M_ARM64) || defined(_M_ARM64EC)
33
#define __aarch64__ 1
34
#endif // native platform identification
35
static inline char *sane_strerror (int errnum) { thread_local static char errorstr[256]; strerror_s (errorstr, sizeof (errorstr), errnum); return (errorstr); } // non-complaining strerror() implementation for MSVC. Note that strerror() is unsafe IF AND ONLY IF the locale is changed during program execution AND a string pointer returned by strerror is saved and reused by the program. Guess the odds it will happen here...
36
#define strerror(n) sane_strerror ((n)) // STFU Microsoft
37
static inline char *sane_getenv (const char *varname) { extern char **environ; size_t i, len = strlen (varname); for (i = 0; environ[i] != NULL; i++) if ((strncmp (environ[i], varname, len) == 0) && ((environ[i])[len] == '=')) return (&(environ[i])[len + 1]); return (NULL); } // non-complaining getenv() implementation for MSVC. Note that getenv_s() access _environ too as per Microsoft docs, so this is perfectly legit. Nuff said.
38
#define getenv(v) sane_getenv ((v)) // STFU Microsoft
39
static struct tm *sane_localtime (const time_t *clock) { thread_local static struct tm localtime_tm; if (localtime_s (&localtime_tm, clock) != 0) return (NULL); return (&localtime_tm); } // non-complaining localtime() implementation for MSVC. Uses TLS.
40
#define localtime(t) sane_localtime ((t)) // STFU Microsoft
41
static inline char *sane_asctime (const struct tm *tm_time) { thread_local static char asctimestr[64]; if (asctime_s (asctimestr, sizeof (asctimestr), tm_time) != 0) return (NULL); return (asctimestr); } // non-complaining asctime() implementation for MSVC. Uses TLS.
42
#define asctime(t) sane_asctime ((t)) // STFU Microsoft
19 pmbaty 43
static inline int vasprintf (char **out_string, const char *fmt, va_list va_args) { int retval; va_list ap; va_copy (ap, va_args); retval = _vsnprintf_s (NULL, 0, 0, fmt, ap); va_end (ap); if (retval == -1) return (-1); *out_string = malloc ((size_t) retval + 1); if (*out_string == NULL) return (-1); va_copy (ap, va_args); retval = _vsnprintf_s (*out_string, (size_t) retval + 1, (size_t) retval + 1, fmt, va_args); va_end (ap); return (retval); } // vasprintf() implementation for Windows
44
static inline int asprintf (char **out_string, const char *fmt, ...) { int r; va_list ap; va_start (ap, fmt); r = vasprintf (out_string, fmt, ap); va_end (ap); return (r); } // asprintf() implementation for Windows
45
#define strcasecmp(s1,s2) _stricmp ((s1), (s2))
46
#define __builtin_bswap16(x) _byteswap_ushort ((unsigned short) (x))
47
#define __builtin_bswap32(x) _byteswap_ulong ((unsigned long) (x))
48
#define __ORDER_LITTLE_ENDIAN__ 1234
49
#define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ // all Windows machines are little-endian
16 pmbaty 50
#define S_IFIFO 0x1000
51
#define S_IFLNK 0xa000
18 pmbaty 52
#define S_ISDIR(m)  (((m) & S_IFMT) == S_IFDIR)
53
#define S_ISREG(m)  (((m) & S_IFMT) == S_IFREG)
54
#define S_ISLNK(m)  (((m) & S_IFMT) == S_IFLNK)
55
#define S_ISFIFO(m) (((m) & S_IFMT) == S_IFIFO)
19 pmbaty 56
#define major(rdev) ((int) (((rdev) >> 10) & 0x3f)) // on Windows assume a QNX-compatible makedev(). Node is zero (local host).
57
#define minor(rdev) ((int) (((rdev) >> 0) & 0x3ff)) // on Windows assume a QNX-compatible makedev(). Node is zero (local host).
58
#define makedev(maj,min) ((dev_t) (((maj) << 10) | (min))) // on Windows assume a QNX-compatible makedev(). Node is zero (local host).
16 pmbaty 59
#define strdup(s) _strdup ((s))
60
#define strcasecmp(s1,s2) _stricmp ((s1), (s2))
61
#define strtok_r(s,delim,ctx) strtok_s ((s), (delim), (ctx))
19 pmbaty 62
#define mkdir(pathname,mode) _mkdir ((pathname))
16 pmbaty 63
#define utimbuf __utimbuf32
64
#define utime(p,t) _utime32 ((p), (t))
19 pmbaty 65
#define access(pathname,accmode) _access ((pathname), (accmode))
66
#define unlink(pathname) _unlink ((pathname))
67
#define ftello(fp) _ftelli64 ((fp))
68
#define fileno(fp) _fileno ((fp))
69
#define ftruncate(fd,size) _chsize_s ((fd), (size))
70
#define readlink(pathname,buf,maxsize) ((*_errno () = 129 /*ENOTSUP*/), -1) // readlink() not supported on Windows
71
#define stat _stat64
72
#define getcwd(buf,maxsize) _getcwd ((buf), (maxsize))
73
#define chdir(pathname) _chdir ((pathname))
74
#define putenv(v) _putenv ((v))
16 pmbaty 75
#define MAXPATHLEN 1024
23 pmbaty 76
static const char *__static_progname = NULL;
77
static const char *__getprogname (void) { if (__static_progname == NULL) { const char *sep; __static_progname = __argv[0]; if ((sep = strrchr (__static_progname, '\\')) != NULL) __static_progname = sep + 1; if ((sep = strrchr (__static_progname, '/')) != NULL) __static_progname = sep + 1; } return (__static_progname); }
78
#define __progname (__getprogname ())
19 pmbaty 79
struct dirent { unsigned char d_namlen; char *d_name; }; // bring struct dirent/opendir() support to Windows
80
typedef struct DIR { intptr_t handle; struct __finddata64_t info; struct dirent result; char *pathname; char *search_pattern; } DIR;
81
static inline DIR *opendir (const char *name) // UNIX-like opendir() implementation for Windows
82
{
83
   DIR *dir; size_t base_length, all_length; const char *suffix;
84
   dir = (DIR *) malloc (sizeof (DIR)); if (dir == NULL) { /*errno already set*/ return (NULL); }
85
   dir->pathname = _fullpath (NULL, name, 0); // system will mallocate, caller frees
86
   if (dir->pathname == NULL) { free (dir); *_errno () = 12 /*ENOMEM*/; return (NULL); }
87
   base_length = strlen (name);
88
   suffix = ((name[base_length - 1] == '\\') || (name[base_length - 1] == '/') ? "*" : "/*"); // search pattern must end with suitable wildcard
89
   all_length = base_length + strlen (suffix) + 1;
90
   dir->search_pattern = (char *) malloc (all_length); if (dir->search_pattern == NULL) { free (dir->pathname); free (dir); *_errno () = 12 /*ENOMEM*/; return (NULL); }
91
   strcpy_s (dir->search_pattern, all_length, name); strcat_s (dir->search_pattern, all_length, suffix);
92
   dir->handle = _findfirst64 (dir->search_pattern, &dir->info); if (dir->handle == -1) { free (dir->search_pattern); free (dir->pathname); free (dir); return (NULL); }
93
   dir->result.d_namlen = 0; dir->result.d_name = NULL; // first-time initialization
94
   return (dir);
95
}
96
static inline int closedir (DIR *dir) // UNIX-like closedir() implementation for Windows
97
{
98
   int result = -1;
99
   if (dir == NULL) { *_errno () = 9 /*EBADF*/; return (-1); }
100
   if (dir->handle != -1) result = _findclose (dir->handle);
101
   if (dir->search_pattern != NULL) free (dir->search_pattern);
102
   if (dir->pathname != NULL) free (dir->pathname);
103
   free (dir);
104
   if (result == -1) *_errno () = 9 /*EBADF*/; // map all errors to EBADF
105
   return (result);
106
}
107
static inline struct dirent *readdir (DIR *dir) // UNIX-like readdir() implementation for Windows
108
{
109
   struct dirent *result = NULL;
110
   if ((dir == NULL) || (dir->handle == -1)) { *_errno () = 9 /*EBADF*/; return (NULL); }
111
   if ((dir->result.d_name == NULL) || (_findnext64 (dir->handle, &dir->info) != -1)) {
112
      result = &dir->result;
113
      result->d_name = dir->info.name;
114
      result->d_namlen = (unsigned char) strlen (dir->info.name);
115
   }
116
   return (result);
117
}
118
static inline void rewinddir (DIR *dir) // UNIX-like rewinddir() implementation for Windows
119
{
120
   if ((dir == NULL) || (dir->handle == -1)) { *_errno () = 9 /*EBADF*/; return; }
121
   _findclose (dir->handle);
122
   dir->handle = (long) _findfirst64 (dir->search_pattern, &dir->info);
123
   dir->result.d_namlen = 0; dir->result.d_name = NULL; // first-time initialization
124
}
16 pmbaty 125
#else // !_MSC_VER
126
#define strcpy_s(s1,s1size,s2) strcpy ((s1), (s2))
34 pmbaty 127
#define strncpy_s(s1,s1size,s2,len) strncpy ((s1), (s2), (len))
16 pmbaty 128
#define strcat_s(s1,s1size,s2) strcat ((s1), (s2))
34 pmbaty 129
#define strncat_s(s1,s1size,s2,len) strncat ((s1), (s2), (len))
16 pmbaty 130
#define sprintf_s(s1,s1size,...) sprintf ((s1), __VA_ARGS__)
131
#define fopen_s(fp,pathname,mode) *(fp) = fopen ((pathname), (mode))
23 pmbaty 132
extern const char *__progname; // exported by libc
16 pmbaty 133
#endif // _MSC_VER
134
 
135
 
136
// handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD);
137
#ifndef VERSION_ARG_YYYYMMDD
138
#define BUILDDATE_YEAR  (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021"
139
#define BUILDDATE_MONTH ( \
140
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jan ") ? "01" : \
141
   *((uint32_t *) __DATE__) == *((uint32_t *) "Feb ") ? "02" : \
142
   *((uint32_t *) __DATE__) == *((uint32_t *) "Mar ") ? "03" : \
143
   *((uint32_t *) __DATE__) == *((uint32_t *) "Apr ") ? "04" : \
144
   *((uint32_t *) __DATE__) == *((uint32_t *) "May ") ? "05" : \
145
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jun ") ? "06" : \
146
   *((uint32_t *) __DATE__) == *((uint32_t *) "Jul ") ? "07" : \
147
   *((uint32_t *) __DATE__) == *((uint32_t *) "Aug ") ? "08" : \
148
   *((uint32_t *) __DATE__) == *((uint32_t *) "Sep ") ? "09" : \
149
   *((uint32_t *) __DATE__) == *((uint32_t *) "Oct ") ? "10" : \
150
   *((uint32_t *) __DATE__) == *((uint32_t *) "Nov ") ? "11" : \
151
   *((uint32_t *) __DATE__) == *((uint32_t *) "Dec ") ? "12" : \
152
   "XX" \
153
) // compiler will optimize this into a const string, e.g. "11"
154
#define BUILDDATE_DAY ( \
155
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  1 ") ? "01" : \
156
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  2 ") ? "02" : \
157
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  3 ") ? "03" : \
158
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  4 ") ? "04" : \
159
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  5 ") ? "05" : \
160
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  6 ") ? "06" : \
161
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  7 ") ? "07" : \
162
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  8 ") ? "08" : \
163
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) "  9 ") ? "09" : \
164
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 10 ") ? "10" : \
165
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 11 ") ? "11" : \
166
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 12 ") ? "12" : \
167
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 13 ") ? "13" : \
168
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 14 ") ? "14" : \
169
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 15 ") ? "15" : \
170
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 16 ") ? "16" : \
171
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 17 ") ? "17" : \
172
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 18 ") ? "18" : \
173
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 19 ") ? "19" : \
174
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 20 ") ? "20" : \
175
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 21 ") ? "21" : \
176
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 22 ") ? "22" : \
177
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 23 ") ? "23" : \
178
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 24 ") ? "24" : \
179
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 25 ") ? "25" : \
180
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 26 ") ? "26" : \
181
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 27 ") ? "27" : \
182
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 28 ") ? "28" : \
183
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 29 ") ? "29" : \
184
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \
185
   *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : \
186
   "XX" \
187
) // compiler will optimize this into a const string, e.g. "14"
188
#define VERSION_FMT_YYYYMMDD "%s%s%s"
189
#define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY
190
#endif // !VERSION_ARG_YYYYMMDD
191
 
192
 
193
// macro to bring __FILE_NAME__ support to moronic compilers
194
#ifndef __FILE_NAME__ // Clang 9+ has the macro, GCC 12+ added it too in 2021, MSVC obviously won't do it. Heh.
195
#define __FILE_NAME__ ( \
196
   (sizeof (__FILE__) >  2) && ((__FILE__[sizeof (__FILE__) -  2] == '/') || (__FILE__[sizeof (__FILE__) -  2] == '\\')) ? &__FILE__[sizeof (__FILE__) -  1] : \
197
   (sizeof (__FILE__) >  3) && ((__FILE__[sizeof (__FILE__) -  3] == '/') || (__FILE__[sizeof (__FILE__) -  3] == '\\')) ? &__FILE__[sizeof (__FILE__) -  2] : \
198
   (sizeof (__FILE__) >  4) && ((__FILE__[sizeof (__FILE__) -  4] == '/') || (__FILE__[sizeof (__FILE__) -  4] == '\\')) ? &__FILE__[sizeof (__FILE__) -  3] : \
199
   (sizeof (__FILE__) >  5) && ((__FILE__[sizeof (__FILE__) -  5] == '/') || (__FILE__[sizeof (__FILE__) -  5] == '\\')) ? &__FILE__[sizeof (__FILE__) -  4] : \
200
   (sizeof (__FILE__) >  6) && ((__FILE__[sizeof (__FILE__) -  6] == '/') || (__FILE__[sizeof (__FILE__) -  6] == '\\')) ? &__FILE__[sizeof (__FILE__) -  5] : \
201
   (sizeof (__FILE__) >  7) && ((__FILE__[sizeof (__FILE__) -  7] == '/') || (__FILE__[sizeof (__FILE__) -  7] == '\\')) ? &__FILE__[sizeof (__FILE__) -  6] : \
202
   (sizeof (__FILE__) >  8) && ((__FILE__[sizeof (__FILE__) -  8] == '/') || (__FILE__[sizeof (__FILE__) -  8] == '\\')) ? &__FILE__[sizeof (__FILE__) -  7] : \
203
   (sizeof (__FILE__) >  9) && ((__FILE__[sizeof (__FILE__) -  9] == '/') || (__FILE__[sizeof (__FILE__) -  9] == '\\')) ? &__FILE__[sizeof (__FILE__) -  8] : \
204
   (sizeof (__FILE__) > 10) && ((__FILE__[sizeof (__FILE__) - 10] == '/') || (__FILE__[sizeof (__FILE__) - 10] == '\\')) ? &__FILE__[sizeof (__FILE__) -  9] : \
205
   (sizeof (__FILE__) > 11) && ((__FILE__[sizeof (__FILE__) - 11] == '/') || (__FILE__[sizeof (__FILE__) - 11] == '\\')) ? &__FILE__[sizeof (__FILE__) - 10] : \
206
   (sizeof (__FILE__) > 12) && ((__FILE__[sizeof (__FILE__) - 12] == '/') || (__FILE__[sizeof (__FILE__) - 12] == '\\')) ? &__FILE__[sizeof (__FILE__) - 11] : \
207
   (sizeof (__FILE__) > 13) && ((__FILE__[sizeof (__FILE__) - 13] == '/') || (__FILE__[sizeof (__FILE__) - 13] == '\\')) ? &__FILE__[sizeof (__FILE__) - 12] : \
208
   (sizeof (__FILE__) > 14) && ((__FILE__[sizeof (__FILE__) - 14] == '/') || (__FILE__[sizeof (__FILE__) - 14] == '\\')) ? &__FILE__[sizeof (__FILE__) - 13] : \
209
   (sizeof (__FILE__) > 15) && ((__FILE__[sizeof (__FILE__) - 15] == '/') || (__FILE__[sizeof (__FILE__) - 15] == '\\')) ? &__FILE__[sizeof (__FILE__) - 14] : \
210
   (sizeof (__FILE__) > 16) && ((__FILE__[sizeof (__FILE__) - 16] == '/') || (__FILE__[sizeof (__FILE__) - 16] == '\\')) ? &__FILE__[sizeof (__FILE__) - 15] : \
211
   (sizeof (__FILE__) > 17) && ((__FILE__[sizeof (__FILE__) - 17] == '/') || (__FILE__[sizeof (__FILE__) - 17] == '\\')) ? &__FILE__[sizeof (__FILE__) - 16] : \
212
   (sizeof (__FILE__) > 18) && ((__FILE__[sizeof (__FILE__) - 18] == '/') || (__FILE__[sizeof (__FILE__) - 18] == '\\')) ? &__FILE__[sizeof (__FILE__) - 17] : \
213
   (sizeof (__FILE__) > 19) && ((__FILE__[sizeof (__FILE__) - 19] == '/') || (__FILE__[sizeof (__FILE__) - 19] == '\\')) ? &__FILE__[sizeof (__FILE__) - 18] : \
214
   (sizeof (__FILE__) > 20) && ((__FILE__[sizeof (__FILE__) - 20] == '/') || (__FILE__[sizeof (__FILE__) - 20] == '\\')) ? &__FILE__[sizeof (__FILE__) - 19] : \
215
   (sizeof (__FILE__) > 21) && ((__FILE__[sizeof (__FILE__) - 21] == '/') || (__FILE__[sizeof (__FILE__) - 21] == '\\')) ? &__FILE__[sizeof (__FILE__) - 20] : \
216
   (sizeof (__FILE__) > 22) && ((__FILE__[sizeof (__FILE__) - 22] == '/') || (__FILE__[sizeof (__FILE__) - 22] == '\\')) ? &__FILE__[sizeof (__FILE__) - 21] : \
217
   (sizeof (__FILE__) > 23) && ((__FILE__[sizeof (__FILE__) - 23] == '/') || (__FILE__[sizeof (__FILE__) - 23] == '\\')) ? &__FILE__[sizeof (__FILE__) - 22] : \
218
   (sizeof (__FILE__) > 24) && ((__FILE__[sizeof (__FILE__) - 24] == '/') || (__FILE__[sizeof (__FILE__) - 24] == '\\')) ? &__FILE__[sizeof (__FILE__) - 23] : \
219
   (sizeof (__FILE__) > 25) && ((__FILE__[sizeof (__FILE__) - 25] == '/') || (__FILE__[sizeof (__FILE__) - 25] == '\\')) ? &__FILE__[sizeof (__FILE__) - 24] : \
220
   (sizeof (__FILE__) > 26) && ((__FILE__[sizeof (__FILE__) - 26] == '/') || (__FILE__[sizeof (__FILE__) - 26] == '\\')) ? &__FILE__[sizeof (__FILE__) - 25] : \
221
   (sizeof (__FILE__) > 27) && ((__FILE__[sizeof (__FILE__) - 27] == '/') || (__FILE__[sizeof (__FILE__) - 27] == '\\')) ? &__FILE__[sizeof (__FILE__) - 26] : \
222
   (sizeof (__FILE__) > 28) && ((__FILE__[sizeof (__FILE__) - 28] == '/') || (__FILE__[sizeof (__FILE__) - 28] == '\\')) ? &__FILE__[sizeof (__FILE__) - 27] : \
223
   (sizeof (__FILE__) > 29) && ((__FILE__[sizeof (__FILE__) - 29] == '/') || (__FILE__[sizeof (__FILE__) - 29] == '\\')) ? &__FILE__[sizeof (__FILE__) - 28] : \
224
   (sizeof (__FILE__) > 30) && ((__FILE__[sizeof (__FILE__) - 30] == '/') || (__FILE__[sizeof (__FILE__) - 30] == '\\')) ? &__FILE__[sizeof (__FILE__) - 29] : \
225
   (sizeof (__FILE__) > 31) && ((__FILE__[sizeof (__FILE__) - 31] == '/') || (__FILE__[sizeof (__FILE__) - 31] == '\\')) ? &__FILE__[sizeof (__FILE__) - 30] : \
226
   (sizeof (__FILE__) > 32) && ((__FILE__[sizeof (__FILE__) - 32] == '/') || (__FILE__[sizeof (__FILE__) - 32] == '\\')) ? &__FILE__[sizeof (__FILE__) - 31] : \
227
   (sizeof (__FILE__) > 33) && ((__FILE__[sizeof (__FILE__) - 33] == '/') || (__FILE__[sizeof (__FILE__) - 33] == '\\')) ? &__FILE__[sizeof (__FILE__) - 32] : \
228
   __FILE__) // this *COMPILE-TIME* macro complements the __FILE__ macro defined by the C standard by returning just the filename portion of the full path. Supports filenames up to 32 chars. Expand as necessary.
229
#endif // !__FILE_NAME__
230
 
231
 
232
// logging macros
23 pmbaty 233
#define LOG(type,lvl,...) do { if ((lvl) <= verbose_level) { fprintf (stderr, "%s: %s: ", __progname, (type)); if (verbose_level > 1) fprintf (stderr, "%s:%d:%s(): ", __FILE_NAME__, __LINE__, __func__); fprintf (stderr, __VA_ARGS__); fputc ('\n', stderr); } } while (0)
16 pmbaty 234
#define LOG_ERROR(...)   LOG ("error",   0, __VA_ARGS__)
235
#define LOG_WARNING(...) LOG ("warning", 1, __VA_ARGS__)
236
#define LOG_INFO(...)    LOG ("info",    2, __VA_ARGS__)
237
#define LOG_DEBUG(...)   LOG ("debug",   3, __VA_ARGS__)
238
 
239
// macro to gently exit with an error message
240
#define DIE_WITH_EXITCODE(exitcode,...) do { LOG_ERROR (__VA_ARGS__); exit ((exitcode)); } while (0)
241
 
242
// macro to exit less brutally than with abort() if something doesn't go the way we'd like to
23 pmbaty 243
#define ASSERT(is_it_true,...) do { if (!(is_it_true)) { LOG ("fatal error", 0, "consistency check failed:"); LOG ("failed check", 0, #is_it_true); LOG ("consequence", 0, __VA_ARGS__); exit (1); } } while (0)
16 pmbaty 244
#define ASSERT_WITH_ERRNO(is_it_true) ASSERT ((is_it_true), "%s", strerror (errno))
245
 
246
 
247
#ifdef __cplusplus
248
}
249
#endif
250
 
251
 
252
#endif // UTILITY_H