Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
Stilgar

psnprntf.c compile error [SVN, Linux]

Recommended Posts

Can't compile SVN on XUbuntu (64-bit version, if that might be related). Gives the following error:

psnprntf.c: In function ‘pvsnprintf’:
psnprntf.c:188: error: incompatible types when assigning to type ‘va_list’ from type ‘struct __va_list_tag *’
psnprntf.c: In function ‘pvsnfmt_int’:
psnprntf.c:476: warning: cast from pointer to integer of different size
psnprntf.c:495: warning: cast from pointer to integer of different size
psnprntf.c:514: warning: cast from pointer to integer of different size
make[2]: *** [psnprntf.o] Error 1
make[2]: Leaving directory `/home/gw/eternity/trunk/source'
make[1]: *** [all-recursive] Error 1
make[1]: Leaving directory `/home/gw/eternity/trunk/source'
make: *** [all-recursive] Error 1

Share this post


Link to post

I don't have a clue what the compiler is on about here. The variable and the argument being assigned to it should be of the exact same type - va_list.

This is not the first time GCC has thrown fits about this very same code. It earlier started having a conniption because it used va_list *, which apparently GCC also thinks is an invalid type. I don't understand what is wrong here, but I think they need to get their act together on making va_list work like an ordinary C type again...

Share this post


Link to post

va_list is special, it is part of the machinery of stepping through arguments, and I'd bet whatever GCC does is allowed by the various C standards.

More likely that psnprntf.c code is erroneous (assuming some things about how varargs are implemented that it should not assume).

Share this post


Link to post

It passes the va_list down to various functions that it calls - there is simply no other means of parsing out the information. The original code passed the va_list by reference using a va_list *. GCC 4 started complaining about this at random on Linux so I changed the va_list to be passed inside of a structure instead. Now it is suddenly complaining about that too, after accepting it for months.

I don't understand what else I am supposed to do. You can't implement snprintf in a single function, it would be over 5000 lines long! Also the idea that you cannot pass down a va_list isn't possible, or vsprintf wouldn't exist.

Share this post


Link to post

I think you should, for example, remove 'va_list*' argument from pvsnfmt_double() and instead pass the value, doing the 'value = va_arg(ap, double)' just before you call it in the CHECK_TYPE macro.

Share this post


Link to post

Thanks, that is in fact what I decided to do last night while working on this though ;)

The problem came in with the pvsnfmt_int function, however, which used different va_arg() calls depending on the formatting character in use. To replace that business I have had to introduce a union type that is used to pass in the parameter. It's pretty hackish if you ask me.

I found that the problem, which you were right about, stems all the way back to the C89 standard. Since it declines to define va_list even to the extent that you know you can pass it to more than one function reliably, compiler writers are free to do it in whatever way they see fit. C99 didn't fix this, but in fact made it worse by introducing a ridiculous va_copy mechanism which only works if you want to pass the list to each function from the beginning.

Because of this standards loophole, and what must be some really icky internal design, GCC 64-bit has va_list implemented as an array type, which is what was causing the type matching error. Evidently, instead of using a different, sane calling convention for varargs functions like Microsoft does, GCC uses the normal AMD64 calling convention for them, and copies the first 6 arguments passed in registers into this array. That really sounds like the paragon of efficiency...

Varargs functions ought to be implemented with a stdc calling convention on any machine that supports a stack, if you ask me.

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×