Using verify_int_stack()
as described previously has some serious drawbacks.
assert()
inside the verify_
fails, it reports the
line number of the verify_
routine, not the line number of the
function calling the verify_
, which is the line number that we
are really interested in.
verify_
can be fairly expensive. One may wish to enable/disable them
independent of assert()
- in particular, they need an enabling
mechanism independent of NDEBUG
.
verify_
function; its just wasted work.
To correct the first two problems, we will modify define a macro like
assert()
, but one that uses an external file and line number.
/* this belongs in some project-wide common header */
#if( NVERIFY )
#define verify(_file, _line, _e) ((void)0)
#else
#define verify(_file, _line, _e) \
((_e)? (void)0: \
( fprintf(stderr, "%s %d: verify failure: %s", \
_file, _line, #_e), \
abort()))
#endif
Note that one can disable verification by defining NVERIFY
to 1; this is different from disabling assert()
. In that case defining NDEBUG
to anything will cause assert()
to be disabled.
We also have to modify the verify_
routine to accept the callers file and line numbers:
void
verify_int_stack(
FILE * file,
int line,
const int_stack stack
)
{
verify( file, line, len_int_stack(stack) >= 0 );
verify( file, line, len_int_stack(stack) <= max_int_stack(stack) );
verify( file, line, max_int_stack(stack) >= 16 );
verify( file, line, ((max_int_stack(stack) - 16)%16) == 0 );
}
Finally, we have to control the actual calling of the verify_
function. To do this we define the following macros:
#if( NVERIFY )
#define VERIFY_INT_STACK(_stack) ((void)0)
#else
#define VERIFY_INT_STACK(_stack) \
verify_int_stack(__FILE__, __LINE__, _stack)
#endif
Using this macro, the code for push_int_stack()
will look like:
void
push_int_stack(
int_stack stack,
int val
)
{
/* definitions ... */
VERIFY_INT_STACK(stack);
/* body ... */
VERIFY_INT_STACK(stack);
}