This is the mail archive of the gcc@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

A better (more portable) way of printing variable argument lists


	One of the messy issues in gcc source code has been the
various ways of handling stdargs/varargs and vfprintf.  There are many
different implementations of the `fatal' functions.  Each one is a
little different, not all are done equally well.  Ditto for the
various warning/error/etc functions.

	Markku Rossi implemented a neat way (IMHO) to bypass all of
this as of enscript-1.5.4 by using macros implemented in terms of
fprintf.  (Below is some code from enscript-1.5.4/src/gsint.h, take a
look.)  You call the macros by adding a second parenthesis around the
body of the variable arguments.  Eg:

FATAL ((stderr, "%s, %d, %f", arg1, arg2, arg3));
MESSAGE (verbose, (stderr, "%s, %d, %f", arg1, arg2, arg3));

It gets expanded to "do {blah; blah; fprintf (...); blah; } while(0);"

	The advantages are that we don't have to worry if stdarg or
varargs is available, we also don't care about vfprintf.  Everything
is handled by stdio.h and fprintf.  And we don't have to set the
__printf__ format attribute on all our special functions to get format
specifier checks, we get that on fprintf for free.  Note, only some,
not all, of gcc's variable argument functions currently set this
attribute on themselves.

	If y'all think this is a good idea, I can add some similar
macros to a common header file and start converting gcc source to use
them.  Suggestions on how those macros would be specifically defined
to suit gcc are welcome.

		--Kaveh

---example from enscript-1.5.4/src/gsint.h----	
/* Print message if <verbose> is >= <verbose_level>. */
#define MESSAGE(verbose_level, body)		\
  do {						\
    if (!quiet && verbose >= (verbose_level))	\
      fprintf body;				\
  } while (0)

/* Report continuable error. */
#define ERROR(body)			\
  do {					\
    fprintf (stderr, "%s: ", program);	\
    fprintf body;			\
    fprintf (stderr, "\n");		\
    fflush (stderr);			\
  } while (0)

/* Report fatal error and exit with status 1.  Function never returns. */
#define FATAL(body)			\
  do {					\
    fprintf (stderr, "%s: ", program);	\
    fprintf body;			\
    fprintf (stderr, "\n");		\
    fflush (stderr);			\
    exit (1);				\
  } while (0)


--
Kaveh R. Ghazi			Project Manager / Custom Development
ghazi@caip.rutgers.edu		ICon CMT Corp.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]