I am attempting to port C code from one platform to another and remove dependencies.
There is a debug function called dbg_out
which prints out like printf()
.
The prototype is void dbg_out(int dbgMask, const char *pFormat, ...);
Here is an example call : dbg_out((5, "SerialDriver : (x-lx) \n", id, sn));
I would like to map this function to a normal printf()
call but having some issues.
I have attempted this so far
void dbg_out (int dbgMask, const char *pFormat, ...)
__attribute__((format(printf, 2, 3)))
;
I need to ignore the first parameter dbgMask and just take into consideration the other parameters.
I would prefer to use the preprocessor to define a wrapper. I'd appreciate some help with this.
CodePudding user response:
You need use vprintf
instead, to be able to use unknown arguments
inline void dbg_out (int dbgMask, const char *pFormat, ...) {
va_list ptr;
va_start(ptr, pFormat);
vprintf(pFormat, ptr);
va_end(ptr);
}
CodePudding user response:
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.