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]

Re: egcs-980315, gen*.c system.h and fatal() using stdarg/varargs


 > From: Richard Henderson <rth@dot.cygnus.com>
 > 
 > On Thu, Mar 26, 1998 at 01:59:03PM -0500, Kaveh R. Ghazi wrote:
 > > 	I've come up with a workable approach/framework, why do you
 > > feel it is nonsense?  Please explain your technical objections.
 > 
 > 	HOST_WIDE_INT a0 = va_arg(args, HOST_WIDE_INT); \
 > 	HOST_WIDE_INT a1 = va_arg(args, HOST_WIDE_INT); \
 > 
 > sizeof(HOST_WIDE_INT) is not necessarily equal to sizeof(int)
 > or sizeof(char *) or ...  Thus the 
 > 
 > 	fprintf(file, format, a0, a1, a2, ...)
 > 
 > may not necessarily get the arguments in the right place for
 > any given format string.  The only way to do it portably is to
 > parse the format string and pick the arguments off by type.
 > 
 > True, these days probably most of the hosts that such size 
 > mismatches matter for have ANSI/ISO compliant libraries and
 > headers, but it doesn't make your solution any more Correct.
 > r~

	I know its not an argument for strict correctness, however the
solution I propose is already in use in gcc.  I'm just trying to
gather them all together and do it in a consistent manner.  Eg, the
following appears in cccp.c/cexp.c when vfprintf is not available:

 > # define vfprintf(file, msg, args) \
 >     { \
 >       char *a0 = va_arg(args, char *); \
 >       char *a1 = va_arg(args, char *); \
 >       char *a2 = va_arg(args, char *); \
 >       char *a3 = va_arg(args, char *); \
 >       fprintf (file, msg, a0, a1, a2, a3); \
 >     }

	The following is cut from toplev.c:

 > #ifdef HAVE_VPRINTF
 >   vfprintf (stderr, s, ap);
 > #else
 >   {
 >     HOST_WIDE_INT v1 = va_arg(ap, HOST_WIDE_INT);
 >     HOST_WIDE_INT v2 = va_arg(ap, HOST_WIDE_INT);
 >     HOST_WIDE_INT v3 = va_arg(ap, HOST_WIDE_INT);
 >     HOST_WIDE_INT v4 = va_arg(ap, HOST_WIDE_INT);
 >     fprintf (stderr, s, v1, v2, v3, v4);
 >   }
 > #endif

	I found this in gcc.c/mips-tfile.c:

 > static void
 > error (msg, arg1, arg2)
 >      char *msg, *arg1, *arg2;
 > {
 >   fprintf (stderr, "%s: ", programname);
 >   fprintf (stderr, msg, arg1, arg2);
 >   fprintf (stderr, "\n");
 > }
 > #endif /* not HAVE_VPRINTF */

And the gen*.c files use the unnamed integer arguments instead of char*
like the above. 

	All of these individual hacks play tricks with type mismatches
on arguments passed to fprintf.  None of them accounts for the actual
size of the argument passed.  Yet somehow we haven't had a bug report
against this.  Is it possible that no one is running platforms without
vfprintf?  Or maybe this hack happens to work on all these systems. 

	This might not prove anything, but I ran some tests on solaris2,
faking the fact that vfprintf and _doprnt were absent and it still
worked.  So I have to ask whether your objection is perhaps only
theoretical?

	My understanding of va_arg(va_list, type) is that it simply
copies sizeof(type) bytes out of `va_list' and increments `va_list' by
that many bytes.  If true, my implementation of the VFPRINTF() macro
simply copies 10*sizeof(HOST_WIDE_INT) bytes out of `va_list' and
passes them to fprintf after the format string.  The fact that the
bytes were copied sizeof(HOST_WIDE_INT) at a time doesn't matter if
all that happens is that they are concatenated together and passed to
another function.  Then fprintf pulls them off the va_list in the
right type size amounts.

	The only cases I can see where my hack fails is if there are
more parameters than I account for.  But given that the _existing_
hacks only account for 3 or 4 args, the fact that I listed 10 should
be enough.

		--Kaveh
--
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]