Page 1 of 1

VA_LIST

Posted: Wed Nov 23, 2005 6:32 am
by zack
Hi everybody.
i tried yesterday to make a function with a va_list.

this is the function prototype:

Code: Select all

void       DrawBitmap      (GUIBitmap *, int32_t, int32_t, uint8_t, ...);
if the last uint8_t is DRAW_TRANSPARENT (0x2), then the function request one parameter more. i tried to get it with this peace of code here:

Code: Select all

#typedef unsigned long uint32_t;
void    DrawBitmap(GUIBitmap *_bmp, int32_t _x, int32_t _y, uint8_t _mode, ...)
{
   va_list args;
   va_start(args, _mode);

   uint32_t transp = va_arg(args, uint32_t); //needed only if _mode == DRAW_TRANSPARENT

   va_end(args);
};
but however this one didn't work. :(
what made i wrong?
could you help me? thx

thx for help.

Code: Select all

#ifndef STDARG_H
#define STDARG_H

typedef unsigned char *va_list;

#define STACKITEM int

#define va_start(AP,LASTARG)                                  \
  ( AP = (( va_list ) & ( LASTARG ) + VA_SIZE( LASTARG )))

#define va_arg(AP,TYPE)                                       \
  (AP+=__va_rounded_size(TYPE),*((TYPE *)(AP-__va_rounded_size(TYPE))))

#define __va_rounded_size(TYPE)                               \
  (((sizeof(TYPE)+sizeof(int)-1)/sizeof(int))*sizeof(int))

#define VA_SIZE(TYPE)                                         \
  ((sizeof(TYPE)+sizeof(STACKITEM)-1)&~(sizeof(STACKITEM)-1))

#define va_end(AP) \
   ( AP = (void *)(0) )
  
#endif

Re:VA_LIST

Posted: Wed Nov 23, 2005 5:06 pm
by Cjmovie
Well, I'm really no expert on define macros....(Yeah, I've no clue ^_^)

So, the obvious problem I can point out is that anything you send to a function, no matter what size it is, will ALWAYS be 32-bits on an x86 machine, meaning your VA_SIZE shouldn't return the size of something to add to the end of the stack, as it will vary from the 32 bits....instead, always add 4 bytes.

Of course, I could be totally wrong.

Re:VA_LIST

Posted: Wed Nov 23, 2005 5:15 pm
by zack
well, i'd "copied" (rewritten) this part of a tutorial. and i've seen other code snippets which does the same. but i'll try it.
thx

Re:VA_LIST

Posted: Wed Nov 23, 2005 5:59 pm
by AR
What exactly do you mean by "doesn't work"? It's not very helpful with programming problems when people just say "doesn't work"... Do you mean it doesn't compile? Outputs rubbish? Page faults?

In the former case, you have a 'pound' sign ("#") in front of your typedef, typedef is a C directive not a preprocessor directive. In the second case, I don't like those sorts of complex macros so I prefer the easy way out using the GCC builtin directives:

Code: Select all

#define va_start(v, f) __builtin_va_start(v, f);
#define va_end(v)       __builtin_va_end(v);
#define va_arg(v, a)   __builtin_va_arg(v, a);
You can also just "#include <stdarg.h>".

Re:VA_LIST

Posted: Thu Nov 24, 2005 12:55 am
by zack
the output is rubbish.... a.expl. if i give to it a parameter 0x00 (32bit) the the content of the va_arg(_mode, int) is something like 0xXXXX00. but the code shouldn't be wrong...

thats the output of your code:

Code: Select all

gui/uiBitmap.c: In function `DrawBitmap':
gui/uiBitmap.c:38: error: incompatible type for argument 1 of `__builtin_va_start'
gui/uiBitmap.c:56: error: incompatible type for argument 1 of `__builtin_va_end'
gui/uiBitmap.c:43: error: first argument to `va_arg' not of type `va_list'
make.exe: *** [c] Error 1
Error open kernelc.bin
argh.. :)
thx!

Re:VA_LIST

Posted: Thu Nov 24, 2005 1:08 am
by AR
Sorry, you will also need:

Code: Select all

#define va_list     __builtin_va_list

Re:VA_LIST

Posted: Thu Nov 24, 2005 1:20 am
by zack
yeah, this one works now... but what was the different?
works this gcc builtin on all versions? (djgpp, cygwin, linux, windows...)

thx

Re:VA_LIST

Posted: Thu Nov 24, 2005 1:45 am
by AR
It should work on all GCC 3.x/4.x. If you want to support multiple compilers then I recommend using "#include <stdarg.h>" instead of defining your own macros.

Re:VA_LIST

Posted: Thu Nov 24, 2005 1:56 am
by Anon00000100
As far as I can see, <stdarg.h> was what he was trying to implement in the first place...

Re:VA_LIST

Posted: Thu Nov 24, 2005 2:04 am
by AR
Anon00000100 wrote: As far as I can see, <stdarg.h> was what he was trying to implement in the first place...
I am suggesting to not implement a stdarg.h, just to use the one that came with the compiler (stdarg.h is part of the freestanding GCC environment [ie. it's a system header] and should be in other compilers as well).