[comp.lang.c] Question about assertion macro

greg@suntan.viewlogic.com (Gregory Larkin) (05/29/91)

Hi there,

I would like to construct an assertion macro so that I
can print the exact condition that failed as a string.

Here is the way I call the macro:

ASSERT(foo != NULL, "Unexpected NULL pointer");

And here is how it is currently defined:

#define ASSERT(relation, msg) { if(!(relation)) { \
			      printf("ASSERTION FAILED: File %s Line %d %s\n",\
                                     __FILE__, __LINE__, msg); \
			      exit(FatalError); } }

I would like to expand the macro so that I can print the message as:

ASSERTION FAILED: foo != NULL, File xxxx Line yyyy Unexpected NULL pointer

How can I print the string "foo != NULL" without passing in the test as
a string.  Can I print the test directly as a string somehow?

Thanks for any help,
-- 
Greg Larkin (ASIC Engineer)|"This is a fragile ball we are living on; 
Viewlogic Systems, Inc.    |it's a miracle and we are destroying it.."
293 Boston Post Road West  |Peter Garrett, Midnight Oil               
Marlboro, MA 01752  (greg@Viewlogic.COM)

msh30@ruts.ccc.amdahl.com (Mark Hahn) (06/01/91)

>From: greg@suntan.viewlogic.com (Gregory Larkin)
>
>
>Hi there,
>
>I would like to construct an assertion macro so that I
>can print the exact condition that failed as a string.
>
>Here is the way I call the macro:
>
>ASSERT(foo != NULL, "Unexpected NULL pointer");
>
>And here is how it is currently defined:
>
>#define ASSERT(relation, msg) { if(!(relation)) { \
>			      printf("ASSERTION FAILED: File %s Line %d %s\n",\
>                                     __FILE__, __LINE__, msg); \
>			      exit(FatalError); } }
>
>I would like to expand the macro so that I can print the message as:
>
>ASSERTION FAILED: foo != NULL, File xxxx Line yyyy Unexpected NULL pointer
>
>How can I print the string "foo != NULL" without passing in the test as
>a string.  Can I print the test directly as a string somehow?
>
>Thanks for any help,
>-- 
>Greg Larkin (ASIC Engineer)|"This is a fragile ball we are living on; 
>Viewlogic Systems, Inc.    |it's a miracle and we are destroying it.."
>293 Boston Post Road West  |Peter Garrett, Midnight Oil               
>Marlboro, MA 01752  (greg@Viewlogic.COM)

#define ASSERT_ARG(relation, msg, action) \
if ( !(relation) ) { \
  printf("ASSERTION FAILED: File %s Line %d %s %s\n",\
  __FILE__, __LINE__, "relation", msg);\
  action; \
} /* if assertion failed */

should work in standard C; I'm not sure about ANSI C, though.
This version has the advantage of being able to specify a C
statement as an action to be taken rather than calling exit(),
which is useful if you need to clean up some things first.

Usage:
  ASSERT_ARG( foo != NULL, "Unexpected NULL pointer", 
              cleanup_routine(arg1, arg2, ..., argn) );

mccrady@torolab6.vnet.ibm.com ("Don McCrady") (06/03/91)

>>From: greg@suntan.viewlogic.com (Gregory Larkin)
>>I would like to construct an assertion macro so that I
>>can print the exact condition that failed as a string.
>>   ASSERT(foo != NULL, "Unexpected NULL pointer");
>>Greg Larkin (ASIC Engineer)

> #define ASSERT_ARG(relation, msg, action) \
> if ( !(relation) ) { \
>   printf("ASSERTION FAILED: File %s Line %d %s %s\n",\
>   __FILE__, __LINE__, "relation", msg);\
>   action; \
> } /* if assertion failed */
>
> should work in standard C; I'm not sure about ANSI C, though.
> From: msh30@ruts.ccc.amdahl.com (Mark Hahn)

No, this won't work in ANSI C... If you use an ANSI C preprocessor,
you can do this easily with the "stringize" operator, #... Try this:

  #define ASSERT_ARG(relation, msg, action) \
    if ( !(relation) ) { \
      printf("ASSERTION FAILED: " #relation "File %s Line %d %s\n",\
             __FILE__, __LINE__, msg); \
      action(); \
    }

Better yet, if you have an ANSI compiler, you should have a header
file called <assert.h>, which will do exactly what you want; that
is, print the failing assertion, the file and line number, and call
the abort() function to terminate the program.

Enjoy.

             ++Don;