Va_*

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
elaverick

Va_*

Post by elaverick »

I'm having a bit of difficulty with va_ commands in my k_printf

My va functions are defined as follows (borrowed from another Barebones)

Code: Select all

#define __va_rounded_size( TYPE )   ( ( (sizeof(TYPE) + sizeof(int) - 1) / sizeof(int) ) * sizeof(int) )
#define va_start( AP, LASTARG )      ( AP = ((char *) &(LASTARG) + __va_rounded_size(LASTARG)) )
#define va_arg( AP, TYPE )         ( AP += __va_rounded_size(TYPE), *((TYPE *) (AP - __va_rounded_size(TYPE))) )
And I'm using them like this

Code: Select all

void SCR_Printf(const char *fmt, ...)
{
    va_list pt;
    int args = 0;
    char cur, pos = 0;
    
   while((cur = fmt[pos++]))
       if(cur == '%')
           args++;
    if(args)
        va_start(pt, args);

    while((cur = *fmt++))
        if(cur == '%')
        {
            cur = *fmt++;
            switch(cur)
            {
                case 'd':
                case 'i':
                    putint((int)va_arg(pt, int));
                    break;
                case 'c':
                    putchar((char)va_arg(pt, char));
                    break;
                case 's':
                    puts(va_arg(pt, char *));
                    break;
            }
        }
        else
            putchar(cur);
}
All the put* functions are working fine as I've unit tested each of those, but when I try to parse any va statements all I get printed is a solid right facing arrow head.

Any ideas?
wacco

Re:Va_*

Post by wacco »

The second parameter of va_start should be the last parameter your function explicitly defined. In your case;

Code: Select all

va_start(pt, fmt);

// And don't forget at the end of your function!
va_end(pt);
Furthermore I'm not entirely happy with your if(args), if I recall correctly you *have* to do the va_start / va_end combination if you declared your function that way, otherwise your compiler could make nasty mistakes. Then again, you might just get away with it ;)

For a proper example you might want to have a look on this website.
elaverick

Re:Va_*

Post by elaverick »

That's great thanks. I had come across that website but I'd misunder stood how the va_start was being called for some reason. It's all working nicely now tho thank you :)
CopperMan

Re:Va_*

Post by CopperMan »

Hi .

If You use a GCC to compile your code you can use builtin functions :

#define va_start(v,l)   __builtin_va_start(v,l)
#define va_end(v)   __builtin_va_end(v)
#define va_arg(v,l)   __builtin_va_arg(v,l)

typedef __builtin_va_list va_list;

Works fine for me !
Post Reply