8051

How to use __VA_ARGS__ variadic in 8051


I'm trying to build a project 8051 in Keil IDE. I have a definition to print information for purposes debug program as following:

#define LOGI(fmt, ...)      printf("[I] %s:%u: "fmt, __FILE__, __LINE__, ##__VA_ARGS__)

But there are errors:

log.h(18): error C301: identifier expected
log.h(18): error C301: identifier expected
log.h(18): error C304: bad macro parameter list

Please help me fix this code, thank you.


Solution

  • According to the documentation, Keil C51 is based on C90. So it does not support __VA_ARGS__ that is a C99 addition.

    However, you can work around this for example by this trick. Use a parenthesized argument.

    #define LOGI(args) \
        do { \
            printf("[I] %s:%u: ", __FILE__, __LINE__); \
            printf args; \
        } while (0)
    
    void f(void) {
        LOGI(("address of f() = %p\n", f));
    }
    

    Another possible solution is to provide an own function with a variable number of arguments, see the example in the documentation. This is a cleaner way because you can use this function without a "hick-up" when reading the source code because of the double parentheses. But be aware that these arguments are not placed in registers, and more memory on stack and in code is used.

    #include <stdio.h>
    #include <stdarg.h>
    
    void logi(const char* filename, int line, char *fmt, ...) {
        va_list arg_ptr;
        va_start(arg_ptr, fmt);
        printf("[I] %s:%u: ", filename, line);
        vprintf(fmt, arg_ptr);
        va_end(arg_ptr);
    }
    
    void f(void) {
        logi(__FILE__, __LINE__, "Hello %u %u", 1 , 2);
    }
    

    Note: You might want to switch to another compiler, which supports some newer standard than a 30 years old one.