2
This file contains development & diagnostic helpers
4
Copyright (C) 2005,2006 Rau'l Nu'n~ez de Arenas Coronado
5
Report bugs to DervishD <bugs@dervishd.net>
7
This program is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License
9
version 2 as published by the Free Software Foundation
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty
13
of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
See the GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
('GPL') along with this program; if not, write to:
19
Free Software Foundation, Inc.
20
59 Temple Place, Suite 330
21
Boston, MA 02111-1307 USA
26
#include <sys/types.h>
39
This macro is optional, but we assign here a default value so
40
the code of the rest of function and macros is a bit easier.
48
This macro should have been set to the module (object file) name.
49
I think that "(?)" is a sane default if it has not.
57
This macro should have been set by the developer to
58
the project's name. Otherwise we complain, the project
59
MUST have a name. It's the Tao.
62
#error "'PROJECT' is undefined, and 'mobs.h' needs it!"
67
This macro should have been set by the developer to
68
the project's version. Otherwise we complain, because the
69
project should have a version. This is also the Tao...
72
#error "'VERSION' is undefined, and 'mobs.h' needs it!"
77
This macro just stringifies its argument, no matter if it
78
is a literal or another macro. It's because of that it needs
79
the additional level of indirection. Only 'STRFY()' is meant
80
to be used. The other macro is just a helper.
83
#define STRFY(mobs_expression) __MOBS_H_STRFY(mobs_expression)
84
#ifndef __MOBS_H_STRFY
85
#define __MOBS_H_STRFY(mobs_expression) #mobs_expression
90
This macro does the same that 'BUG()', but with the semantics of
91
the C9x 'assert()' macro, and ignoring the value of 'errno'. The main
92
differences between 'assert()' and 'ASSERT()' may be the verbosity of
93
the latter and the format of the messages. Moreover, 'ASSERT()' cannot
94
be evaluated: take this into account when using it. A trace mark is
95
also printed for helping to locate this assertion.
97
Use this macro to make assertions. Quite easy, isn't it? ;)))
102
#define ASSERT(mobs_expr) do { if (!(mobs_expr)) {\
104
fprintf(stderr, "*** ASSERTION FAILED, process %d aborting...\n", getpid());\
105
fprintf(stderr, "*** Assertion \"(%s)\" failed at %s()@%s:%d\n", #mobs_expr, __func__, __FILE__, __LINE__);\
107
fputs("Report bug to "AUTHOR"\n", stderr);\
111
#define WASSERT(mobs_expr) do { if (!(mobs_expr)) {\
113
fwprintf(stderr, L"*** ASSERTION FAILED, process %d aborting...\n", getpid());\
114
fwprintf(stderr, L"*** Assertion \"(%s)\" failed at %s()@%s:%d\n", #mobs_expr, __func__, __FILE__, __LINE__);\
115
if (wcslen(L"" AUTHOR ""))\
116
fputws(L"Report bug to "AUTHOR"\n", stderr);\
121
#define ASSERT(mobs_expr) do {(void)(mobs_expr);} while(0)
122
#define WASSERT(mobs_expr) do {(void)(mobs_expr);} while(0)
127
/* This is a helper function to prettyprint the program name */
128
#ifndef __MOBS_progname
129
#define __MOBS_progname
130
static inline const char *progname (const char *);
131
static inline const char *progname (const char *mobs_string) {
132
char *mobs_where=NULL;
134
ASSERT(mobs_string != NULL);
136
mobs_where=strrchr(mobs_string, '/');
137
return mobs_where?mobs_where+1:mobs_string;
140
static inline const wchar_t *wprogname (const wchar_t *);
141
static inline const wchar_t *wprogname (const wchar_t *mobs_string) {
142
wchar_t *mobs_where=NULL;
144
WASSERT(mobs_string != NULL);
146
mobs_where=wcsrchr(mobs_string, L'/');
147
return mobs_where?mobs_where+1:mobs_string;
152
/* This one is pretty large ;))). The GPL disclaimer, just in case... */
153
#ifndef GPL_DISCLAIMER
154
#define GPL_DISCLAIMER() do {\
156
fputs("This program is part of '"PROJECT"-"VERSION"'\n", stdout);\
157
fputc('\n', stdout);\
158
fputs("This program is free software;\n", stdout);\
159
fputs("you can redistribute it and/or modify it under the terms of the\n", stdout);\
160
fputs("GNU General Public License as published by the Free Software Foundation;\n", stdout);\
161
fputs("either version 2 of the License, or (at your option) any later version.\n", stdout);\
162
fputc('\n', stdout);\
163
fputs("This program is distributed in the hope that it will be useful,\n", stdout);\
164
fputs("but WITHOUT ANY WARRANTY; without even the implied warranty\n", stdout);\
165
fputs("of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", stdout);\
166
fputs("See the GNU General Public License for more details.\n", stdout);\
167
fputc('\n', stdout);\
168
fputs("You should have received a copy of the GNU General Public License\n", stdout);\
169
fputs("('GPL') along with this program; if not, write to:\n", stdout);\
170
fputs("\tFree Software Foundation, Inc.\n", stdout);\
171
fputs("\t59 Temple Place, Suite 330\n", stdout);\
172
fputs("\tBoston, MA 02111-1307 USA\n", stdout);\
177
#ifndef WGPL_DISCLAIMER
178
#define WGPL_DISCLAIMER() do {\
180
fputws(L"This program is part of '"PROJECT"-"VERSION"'\n", stdout);\
181
fputwc(L'\n', stdout);\
182
fputws(L"This program is free software;\n", stdout);\
183
fputws(L"you can redistribute it and/or modify it under the terms of the\n", stdout);\
184
fputws(L"GNU General Public License as published by the Free Software Foundation;\n", stdout);\
185
fputws(L"either version 2 of the License, or (at your option) any later version.\n", stdout);\
186
fputwc(L'\n', stdout);\
187
fputws(L"This program is distributed in the hope that it will be useful,\n", stdout);\
188
fputws(L"but WITHOUT ANY WARRANTY; without even the implied warranty\n", stdout);\
189
fputws(L"of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", stdout);\
190
fputws(L"See the GNU General Public License for more details.\n", stdout);\
191
fputwc(L'\n', stdout);\
192
fputws(L"You should have received a copy of the GNU General Public License\n", stdout);\
193
fputws(L"('GPL') along with this program; if not, write to:\n", stdout);\
194
fputws(L"\tFree Software Foundation, Inc.\n", stdout);\
195
fputws(L"\t59 Temple Place, Suite 330\n", stdout);\
196
fputws(L"\tBoston, MA 02111-1307 USA\n", stdout);\
204
This function makes the program die nicely with 'EXIT_FAILURE',
205
outputting a formatted message to 'stderr', followed by '\n'.
207
By now there is no further information in the output message.
211
static inline void die (const char *, ...);
212
static inline void die (const char *mobs_format, ...) {
220
va_start(mobs_args, mobs_format);
221
vfprintf(stderr, mobs_format, mobs_args);
229
static inline void wdie (const wchar_t *, ...);
230
static inline void wdie (const wchar_t *mobs_format, ...) {
234
WASSERT(mobs_format);
238
va_start(mobs_args, mobs_format);
239
vfwprintf(stderr, mobs_format, mobs_args);
250
This macro logs an internal error and aborts.
252
Use this to report *impossible* error conditions, that is, failed
253
assertions (consider using 'ASSERT()' instead for a more classical
254
semantics). It's not intended to produce information useful to the user.
256
It prints the 'errno' value (only if nonzero), its associated message
257
and a trace mark, but the caller must take into account that this information
258
is not always meaningful, specially the trace mark.
260
Since BUG's occur in production releases, this is unconditionally defined
261
in order to help the users on sending bug reports with good information ;)
262
It outputs the project name and version for filling the bug report :)
266
int mobs_errno=errno;\
268
fputs("*** INTERNAL ERROR, please report so it can be fixed!\n",stderr);\
269
fprintf(stderr, "*** Process %d aborting...\n", getpid());\
270
fprintf(stderr, "*** errno <%d> (%s)\n", mobs_errno, strerror(mobs_errno));\
271
fputs("*** '"PROJECT"-"VERSION" (" OBJNAME ") ", stderr);\
272
fprintf(stderr, "%s()@%s:%d\n", __func__, __FILE__, __LINE__);\
274
fputs("*** Report bug to "AUTHOR"\n", stderr);\
282
int mobs_errno=errno;\
284
fputws(L"*** INTERNAL ERROR, please report so it can be fixed!\n",stderr);\
285
fwprintf(stderr, L"*** Process %d aborting...\n", getpid());\
286
fwprintf(stderr, L"*** errno <%d> (%s)\n", mobs_errno, strerror(mobs_errno));\
287
fputws(L"*** '"PROJECT"-"VERSION" (" OBJNAME ") ", stderr);\
288
fwprintf(stderr, L"%s()@%s:%d\n", __func__, __FILE__, __LINE__);\
289
if (wcslen(L"" AUTHOR ""))\
290
fputws(L"*** Report bug to "AUTHOR"\n", stderr);\
298
This function shows the message (the format string, you know...)
299
together with information about the current 'errno' value (strerror...)
300
Just for convenience... The actual format may change...
302
'errno' is not changed.
306
static inline void bang (const char *, ...);
307
static inline void bang (const char *mobs_format, ...) {
310
int mobs_errno=errno;
316
va_start(mobs_args, mobs_format);
317
vfprintf(stderr, mobs_format, mobs_args);
320
fprintf(stderr, "errno <%d> (%s)\n", mobs_errno, strerror(mobs_errno));
326
static inline void wbang (const wchar_t *, ...);
327
static inline void wbang (const wchar_t *mobs_format, ...) {
330
int mobs_errno=errno;
332
WASSERT(mobs_format);
336
va_start(mobs_args, mobs_format);
337
vfwprintf(stderr, mobs_format, mobs_args);
340
fwprintf(stderr, L"errno <%d> (%s)\n", mobs_errno, strerror(mobs_errno));
351
This function outputs a formatted string as specified by 'format', but
352
preceeded by the module name and PID, followed by a '\n'.
354
Please note that there is no way of testing whether the arguments are
355
correct or meaningful according with 'format'. Double check the format
356
string and the parameters, since 'SAY()' will silently fail and fuck up
357
your code if you don't use it correctly ;)))))
359
Use this function to watch variables and the like. If you just want to
360
trace code use the 'T' macro instead. This is useful too if you want to say
361
something before 'BUG()'.
363
Please note that if 'NDEBUG' is defined, the funcion does nothing, and
364
that the 'T' macro is really an alias to 'SAY()'.
366
'errno' is not changed.
371
#define SAY(mobs_format,...) do {\
372
int mobs_errno=errno;\
374
fprintf(stderr, OBJNAME" [%d] ", getpid());\
375
if (mobs_format) fprintf(stderr, mobs_format, ##__VA_ARGS__);\
376
fputc('\n', stderr);\
380
#define WSAY(mobs_format,...) do {\
381
int mobs_errno=errno;\
383
fwprintf(stderr, L""OBJNAME" [%d] ", getpid());\
384
if (mobs_format) fwprintf(stderr, mobs_format, ##__VA_ARGS__);\
385
fputwc('\n', stderr);\
390
#define SAY(mobs_format,...) do {} while(0)
391
#define WSAY(mobs_format,...) do {} while(0)
395
#define T() SAY("%s()@%s:%d", __func__, __FILE__, __LINE__)
396
#define WT() WSAY(L"%s()@%s:%d", __func__, __FILE__, __LINE__)