Using a macro
If you want to use a macro that changes the call to dbg_out to a direct call to printf, you can use a variadic macro:
#define dbg_out(mask, ...) printf(__VA_ARGS__)
int main() {
dbg_out(1, "%d", 12);
}
if they get called like in your question with double parentheses (e.g. dbg_out((5, "%d", 12));
), then you need to unwrap it first:
#define EXPAND(mask, ...) (__VA_ARGS__)
#define dbg_out(...) printf EXPAND __VA_ARGS__
int main() {
dbg_out((1, "%d", 12));
}
Additionally if you know that the format is always a string literal, you could additionally add the mask to the printf output, e.g.:
#define dbg_out(mask, format, ...) printf("[Mask:%d]" format, mask, ##__VA_ARGS__)
int main() {
dbg_out(1, "%d", 12);
}
with double parenthesis calls:
#define EXPAND(mask, format, ...) ("[Mask:%d]" format, mask, ##__VA_ARGS__)
#define dbg_out(...) printf EXPAND __VA_ARGS__
int main() {
dbg_out((1, "%d", 12));
}
Redirect to another function with a macro
In case you can't change the implementation of dbg_out, you can use a macro to redirect the call to another function that does the work:
#include <stdarg.h>
#define dbg_out(...) dbg_out_new(__VA_ARGS__)
void dbg_out_new(int mask, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
void dbg_out_new(int mask, const char* fmt, ...) {
va_list va;
va_start(va, fmt);
vprintf(fmt, va);
va_end(va);
}
int main() {
dbg_out(1, "%d", 12);
}
If it's called with double parenthesis, you need to change the macro to:
#define dbg_out(...) dbg_out_new __VA_ARGS__
/* ... */
int main() {
dbg_out((1, "%d", 12));
}
With the __attribute__(format()) you also get the benefit of compile-time type checking of the arguments, like in the "Using a macro" example.
Change the function
In case you can edit the dbg_out function implementation, you could replace it with the above dbg_out_new implementation.
However this will not work if it gets called with double parenthesis like you wrote in your question.