[vox-tech] macro arguments in C

Mark K. Kim vox-tech@lists.lugod.org
Thu, 17 Oct 2002 15:03:08 -0700 (PDT)


It's a hack but it works:

   #define die if(\
      (die_filename = __FILE__) && \
      (die_function = __FUNCTION__) && \
      (die_line = __LINE__) \
   ) die_for_reals


   char* die_filename;
   char* die_function;
   int die_line;


   void die_for_reals(int err, const char *fmt, ...)
   {
      va_list args;

      va_start(args, fmt);
      fprintf(stderr, "\n\nFatal Error:\n");
      fprintf(stderr,  "   file: %s, function: %s, line: %d\n", die_filename, die_function, die_line);
      fprintf(stderr,  "   strerror reports: %s\n", strerror(err));
      fprintf(stderr,  "   ");
      vfprintf(stderr, fmt, args);
      fprintf(stderr,  "\n");
      exit(0);
   }

Usage:

   if(condition) die(errno, "Blah %d", 5);

Note the following:

   - "if" is used in the "die" macro to join the macro value store
     stage and the "die_for_reals" function call stage.  It should
     always evaluate all three conditionals within the if statement,
     and they should always evaluate to true, so "die_for_reals"
     should always be called.

     This "if" trick is necessary.  Otherwise you'd have to have
     {} die, like this:

        if(condition) { die(errno, "Blah %d", 5); }

     which isn't desirable.

   - Your die() function had a problem.  The line

         vfprintf(stderr, "   %s\n", args);

     was changed to:

         fprintf(stderr,  "   ");
         vfprintf(stderr, fmt, args);
         fprintf(stderr,  "\n");

     besides the modifications that were necessary to accomodate
     the die macro trick.

I used a similar trick for my database class.  I didn't have to deal with
variable arguments, though.

-Mark

On Thu, 17 Oct 2002, Peter Jay Salzman wrote:

> i wrote a generalized "die" function:
>
> void
> die(int err, const char *file, const char *func, int line, const char *fmt, ...)
> {
>    va_list args;
>
>    va_start(args, fmt);
>    fprintf(stderr, "\n\nFatal Error:\n");
>    fprintf(stderr,  "   file: %s, function: %s, line: %d\n", file, func, line);
>    fprintf(stderr,  "   strerror reports: %s\n", strerror(err));
>    vfprintf(stderr, "   %s\n", args);
>    exit(0);
> }
>
>
> normally, i call this function as (for example):
>
>    die(errno, __FILE__, __FUNCTION__, __LINE__,
>       "you made boo-boo number %d.", boo-boo);
>
> that's quite a mouthful.  if possible, i'd like to use a macro to
> shorten this to:
>
>    die("you made boo-boo number %d.", boo-boo);
>
> the problem is the "..." in the die() declaration.  i'm pretty sure that
> macros can't take an arbitrary number of arguments.  potentially, i'd
> like to be able to call die as:
>
>    die("%c%c%c%c%c" 'o', 'o', 'p', 's', '!');
>
> is there a way to shorten the call to die() and still transmit the
> errno, file, function and line informatin?
>
> pete
>
> --
> Fingerprint: B9F1 6CF3 47C4 7CD8 D33E 70A9 A3B9 1945 67EA 951D
> _______________________________________________
> vox-tech mailing list
> vox-tech@lists.lugod.org
> http://lists.lugod.org/mailman/listinfo/vox-tech
>

--
Mark K. Kim
http://www.cbreak.org/
PGP key available upon request.