At 1:17 PM +0530 2001/06/08, Shoeb wrote:
>but this is the declaration, how to implement it & how to access all the
>unknown parameters passed.

Essentially you treat the parameters of the function (which have been pushed on the 
stack in right-to-left order as defined by the C language) as one big array of 
(potentially variable-sized) elements. Note that there is no way to know how many 
parameters are being passed to a function; the mechanism requires some other method of 
indicating this information, such as a format string in the case of StrPrintF.

There are standard C library functions (macros actually) to help you set up and 
manipulate this array, defined in cstdarg.h in the CodeWarrior SDK (or in stdarg.h in 
most other SDKs). These functions are called va_start, va_end, and va_arg. Because 
these functions must implicitly know the packing and alignment rules of the processor 
on which they're being used, their implementations vary slightly to account for these 
platform-specific differences. You have to be careful when dealing with platforms that 
pass parameters in registers by telling the compiler not to do that for your 
multi-parameter function. Fortunately (?) you don't need to worry about that with the 
68k CPU used in all current Palm devices.

Here's an example implementation of the va_ routines:

  typedef char *va_list;
  #define va_start(ap, parmN) ap = (va_list)((char*)&parmN + (((sizeof(parmN)+1)/2)*2))
  #define va_end(ap) /* do nothing */
  #define va_arg(ap, type) ((type *)(ap += sizeof (type)))[-1]

You begin by assigning the start of the parameter list to ap. This allows you to have 
labeled parameters prior to the variable parameters. You then iterate over the 
argument list in left-to-right order, calling var_arg to retrieve each parameter, 
specifying the parameter type each time (so the routine can compute the pointer to the 
next argument on the stack). When you're done, call va_end to balance va_start (this 
would be necessary if, for example, va_start allocated a temporary memory buffer... it 
doesn't, obviously, but it's just good form to do so, as it also indicates to the 
programmer that the routine is finished walking the stack, and in the case of using 
the stdarg library routines, you can never be certain exactly how they're implemented).

Of course, if your function has multiple fixed-sized parameters all of the same type, 
you could just get a pointer to the first of these parameters, cast its address as an 
array of that type, then iterate over the array just as you would any other array. No 
need for funky va_ routines. Though the stdarg approach does make the code easier to 
understand by other engineers.

For more information check out a book on the C language, specifically one with 
information on stdarg, and/or write a wee bit of test code, walking through it under 
the debugger to understand how this mechanism works.

Best of luck,

Jim Schram
Palm Incorporated
Partner Engineering


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