This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
A better (more portable) way of printing variable argument lists
- To: egcs at cygnus dot com
- Subject: A better (more portable) way of printing variable argument lists
- From: "Kaveh R. Ghazi" <ghazi at caip dot rutgers dot edu>
- Date: Tue, 24 Feb 1998 21:31:40 -0500 (EST)
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.