In the previous section, while printing out the error message, we had to use fprintf()
. There is a simpler, though not as straight forward way to do this. It takes advantage of the C
pre-processor. (Note: this will not work with the older, non ANSI C
pre-processors - the so called K&R or Reiser pre-processors)
/* usually goes in some project wide file, such as common.h */
#include <stdio.h>
#if( __STDC__ )
#define STR(x) #x
#define STR2(x) STR(x)
#define PANIC(x) \
do { \
fputs(__FILE__ STR2(__LINE__) x, stderr); \
abort(); \
} while(0)
#else
#error "works only with standard C"
#endif
int_stack
make_int_stack(void)
{
int_stack stack = xalloc(struct int_stack);
if( stack == 0 ) {
PANIC("out of memory");
}
/* other stuff */
}
This takes advantages of several features of ANSI C:
"xy" "zw"
is identical to "xyzw"
.
STR(x)
,
#x
causes the parameter to be stringified; thus
STR(17)
will be expand to "17"
.
__LINE__
, we have to go through an additional
level of indirection. STR(__LINE__)
would result in
"__LINE__"
. STR2(__LINE__)
causes the actual
line number to be expanded, and then that is stringified.
do {...} while(0)
is used instead of
{...}
. This causes a compile-time error if the
';
' is omitted at the end of the invocation of
PANIC()
.
Also, a stylistic note: macros such as is_empty_int_stack()
that can be either functions or macros are written in lower case. However, macros that cannot be rewritten as functions are usually written in all upper case. This includes, for instance STR()
. Generally:
Unfortunately, the code above contains two exceptions to the usual rule. Clearly, xalloc()
can never be written as a function, but it is still in lower case. Generally macros that contain blocks ({...}
), such as PANIC()
, will be written as all upper-case. However, PANIC()
can easily be rewritten as a function.