Ben Combee (Tue, 19 Jun 2001 07:24:16) wrote:
-------------------
The problem is that va_arg(argp, unsigned char) is never meaningful.
Arguments pushed onto the stack for variable argument list functions are
always at least sizeof(int) bytes. If you have a parameter you want to treat
as unsigned char, you can read it off as unsigned int, then downcast. The
compiler won't push just one byte -- it will have converted any expressions
to at least int before pushing. 
--------

Ben,

Thank you for the clarification.  It enabled me to come up with the
following replacement for va_arg and explanation, which I include in hope of
assisting other Palm developers.  Please let us know if you see a problem
with it.  I find I need to support code that expects va_arg(argp, unsigned
short) to work. 

I couldn't find any restrictions mentioned on the type argument for va_arg
in the Palm SDK, companion docs, the Ansi standard or the docs that came
with CW7 from Metrowerks.  Tech support also seemed unaware of this.  I say
all this in appreciation of how quickly you set me straight relative to my
other sources.  

Again I thank you,

-- Chuck


/*
#define va_arg(ptr, type)  (sizeof(type) >= sizeof(int) \
   ? ( (((type*)ptr)++ ), (type)(*(((type*)ptr)-1)) ) \
   : ( (((int*)ptr)++ ),  (type)(*(((int*)ptr)-1)) ) )
*/

/* for Ansi-strict, you need to spell out that first part */
#define va_arg(ptr, type)  (sizeof(type) >= sizeof(int) \
   ? ( (ptr = ((char*) (((unsigned long)ptr) + sizeof(type)))),
(type)(*(((type*)ptr)-1)) ) \
   : ( (ptr = ((char*) (((unsigned long)ptr) + sizeof(int )))),
(type)(*(((int*)ptr)-1)) ) )

/* va_arg(ptr, type)
Returns the value at ptr and advances ptr past that value.

Note for those new to va_arg:
This is effectively 
  1) cast ptr to type*
  2) dereference ptr to get value
  3) increment ptr
  4) return value.
It looks strange because the dereference and post-increment operators
don't work together for this case.
  *(((type*)ptr)++)  [1,3,2] derefrences a value too far.
  (*((type*)ptr))++  [1,2,3] increments the dereferenced value, not ptr.
So we wind up with 1,3,1,decrement-to-undo-step-3,2,4 instead,
which looks like the lobster quadrille ;-)

Note for those using Codewarrior for PalmOS:
Arguments put on the va stack by the ... prototype are at least sizeof(int).
So, short (when ints are 4 bytes) and byte arguments are promoted to int. 
This version of va_arg handles always advances ptr by at least sizeof(int).
*/

-- 
For information on using the Palm Developer Forums, or to unsubscribe, please see 
http://www.palmos.com/dev/tech/support/forums/

Reply via email to