In C, we often have to run such code
if (! somefun(x, y, z)) {
perror("somefun")
}
Is it possible to create a macro which, used as follows:
#define chkerr ...
chkerr(somefun(x, y, z));
would compile to the above?
I already know I can use __VA_ARGS__ macro, but this would require me to call it like
chkerr(somefun, x, y, z)
Short variant (you spotted already):
#define chkErr(FUNCTION, ...) \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
}
Be aware that this can impose big problems in nested if/else or similar constructs:
if(x)
chkErr(f, 10, 12) //;
//^ semicolon forgotten!
else
chkErr(f, 12, 10);
would compile to code equivalent to the following:
if(x)
{
if(!f(10, 12))
perror("f");
else if(!f, 12, 10))
perror("f");
}
Quite obviously not what was intended with the if/else written with the macros... So you really should prefer to let it look like a real function (requiring a semicolon):
#define chkErr(FUNCTION, ...) \
do \
{ \
if(!FUNCTION(__VA_ARGS__)) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
You would call it like this:
chkErr(someFunction, 10, 12);
In case of error, output would be:
someFunction: <error text>
However, this hides the fact that a function actually gets called, making it more difficult to understand for "outsiders". Same output, not hiding the function call, but requiring one additional comma in between function and arguments (compared to a normal function call):
#define chkErr(FUNCTION, ARGUMENTS) \
do \
{ \
if(!FUNCTION ARGUMENTS) \
{ \
perror(#FUNCTION); \
} \
} \
while(0)
chkErr(someFunction,(12, 10));
// ^ (!)
Another variant with the charm of retaining the function call would print out this entire function call:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_CALL); \
} \
} \
while(0)
chkErr(someFunction(10, 12));
In case of error, output would be:
someFunction(10, 12): <error text>
Addendum: If you really want exactly the output as shown in the question and still have the function call retained (without comma in between), you are a little in trouble. Actually, it is possible, but it requires some extra work:
Problem is how the preprocessor operates on macro arguments: Each argument is a token. It can easily combine tokens, but cannot split them.
Leaving out any commas results in the macro accepting one single token, just as in my second variant. Sure, you can stringify it, as I did, but you get the function arguments with. This is a string literal, and as the pre-processor cannot modify string literals, you have to operate on them at runtime.
Next problem then is, though, string literals are unmodifiable. So you need to modify a copy!
The following variant would do all this work for you:
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
char function_name[] = #FUNCTION_CALL; \
char* function_name_end = strchr(function_name, '('); \
if(function_name_end) \
*function_name_end = 0; \
perror(function_name); \
} \
} \
while(0)
Well, decide you if it is worth the effort...
By the way - whitespace between function name and opening parenthesis is not eliminated. If you want to be perfect:
unsigned char* end = (unsigned char*) function_name;
while(*end && *end != '(' && !isspace(*end))
++end;
*end = 0;
Or, much nicer (thanks chqrlie for the hint):
function_name[strcspn(function_name, "( \t")] = 0;
Anything else I can think of would require an additional pre-processing step:
#define CAT(X, Y) CAT_(X, Y)
#define CAT_(X, Y) X ## Y
#define chkErr(FUNCTION_CALL) \
do \
{ \
if(!FUNCTION_CALL) \
{ \
perror(CAT(CHK_ERR_TEXT_, __LINE__)); \
} \
} \
while 0
chkErr(function(10, 12));
Ah, huh, this would result in code like this:
if(!function(10, 12))
{
perror(CHK_ERR_TEXT_42);
}
And now, where to get these macros from? Well, the pre-processing, remember? Possibly a perl or python script, e. g. generating an additional header file you'd have to include. You would have to make sure this pre-processing is done every time before the compiler's pre-processor runs.
Well, all not impossible to solve, but I'll leave this to the masochists among us...
C11 6.4.2.2 Predefined identifiers
The identifier __func__ shall be implicitly declared by the translator as if, immediately following the opening brace of each function definition, the declaration
static const char __func__[] = "function-name";
appeared, where function-name is the name of the lexically-enclosing function.
You can used it this way:
#define chkErr(exp) do { if (!(exp)) perror(__func__); } while (0)
chkerr(somefun(x, y, z));
Unfortunately, this would produce an error message with the name of the calling function, not somefun. Here is a simple variant that should work and even produce more informative error messages:
#define chkErr(exp) do { if (!(exp)) perror(#exp); } while (0)
chkerr(somefun(x, y, z));
In case somefun(x, y, z) returns a non zero value, the error message will contain the string "somefun(x, y, z)".
You can combine both techniques to give both the offending call and the location:
#include <errno.h>
#include <stdio.h>
#include <string.h>
#define chkErr(exp) \
do { if (!(exp)) \
fprintf(stderr, "%s:%d: in function %s, %s failed: %s\n",\
__FILE__, __LINE__, __func__, #exp, strerror(errno)); \
} while (0)
chkerr(somefun(x, y, z));
This assumes somefun() returns 0 or NULL in case of error and set errno accordingly. Note however that most system calls return non zero in case of error.
You can use the original call format:
chkerr(somefun(x, y, z));
With a macro and a helper function:
#define chkerr(fcall) \
if (!fcall) { \
perror(extract_fname(#fcall)); \
}
const char *extract_fname(const char *fcall);
The extract_fname function would get text and return everything until the open parenthesis.
Yes it is possible with an ugly, unsafe variadic macro:
#define chkerr(func, ...) \
if(!func(__VA_ARGS__)) \
{ \
perror(#func); \
}
...
chkerr(somefunc, 1, 2, 3);
But it is a very bad idea.
Call for sanity:
If there was just the original code with the plain if statement, the reader would think "Here they call a function and do some basic error control. Okay, basic stuff. Moving on...". But after the changes, anyone who reads the code will instead freeze and think "WTF is this???".
You can never write a macro that is clearer than the if statement - which makes the if statement superior to the macro.
Some rules to follow:
Function-like macros are dangerous and unreadable. They should only be used as the very last resort.
Avoid inventing your own secret macro language with function-like macros. C programmers who read your code know C. They don't know your secret macro language.
"To avoid typing" is often a poor rationale for program design decisions. Avoiding code repetition is a good rationale, but taking it to the extremes will affect code readability. If you avoid code repetition and make the code more readable at the same time, it is a good thing. If you do it but the code turns less readable, it is hard to justify.
It's not possible to extract just the function name. The C processor sees the literals you pass as single tokens, which can't be manipulated. Your only options are to print the function with arguments like Aconcague suggests or pass the name as a separate parameter:
#define chkErr(FUNCTION_NAME, FUNCTION_CALL) \
if(!FUNCTION_CALL) \
{ \
perror(#FUNCTION_NAME); \
}
chkErr(someFunction, someFunction(10, 12));
For a debug purpose I defined the following macro
#define SECTION_TIME(out, s) GPIO_SetOut(out); \
s \
GPIO_ClrOut(out);
usage:
SECTION_TIME(GPIO_fooOut,
foo();
bar();
foo=bar^foo;....;....;
)
Goal: needed to mesure time of some code.
Sometimes this macro do not compile. Did I miss understand somthing?
PS: I also tried surrounding my code with {}
error: macro "SECTION_TIME" passed 6 arguments, but takes just 2
When code walks like a duck and talks like a duck, it better fully behave exactly like a duck. What I mean by that is that SECTION_TIME(GPIO_fooOut, ...) (sort of) looks like one statement while in reality it maps to 3 or more statements. This is bad, and you should strive to truely make it one statement.
This is actually not difficult, and the common idiom used for this is to wrap the macro content in do { ... } while (0) without a trailing semicolon (so that the trailing semicolon is supplied to the end of the macro invocation).
So you should at least change your macro to something like
#define SECTION_TIME(out, s) \
do { \
GPIO_SetOut(out); \
s; \
GPIO_ClrOut(out); \
} while (0)
Also notice here that you should put the terminating semicolon for s in the macro and not the argument. So the macro should be invoked like
SECTION_TIME(GPIO_fooOut,
foo();
bar();
foo=bar^foo;....;....
);
Depending on use cases, the suggestion to use SETION_TIME_BEGIN and SECTION_TIME_END might be a better solution.
Solved using variadic macro
#define BOARD_SECTION_TIME(out, ...) do { \
GPIO_SetOut(out); \
__VA_ARGS__ \
GPIO_ClrOut(out); \
} while(0)
I also use the way of __VA_ARGS__ but I also make some curry-like syntax by defining a second macro, which name is in the first:
#define SECTION_TIME(out) \
do { \
/* remember to save the value, so that the same output is always cleared and can be used in the second one */ \
decltype(out) _o = out; \
GPIO_SetOut(_o); \
SECTION_TIME_BLOCK1
#define SECTION_TIME_BLOCK1(...) \
{__VA_ARGS__}; \
GPIO_ClrOut(_o); \
} while(0);
And it can be used like this:
SECTION_TIME(GPIO_fooOut) (
foo();
bar();
foo=bar^foo;
//....;....;
);
You see that the out input-parameter is a separate tuple and that the syntax is similar to the syntax of if for example, only the brackets are different. And if you want to define only one macro, you say that the code-parameter(s) should be in a tuple:
// this macro is only a help to remove the brackets and can be used in multiple definitions
#define PP_REMOVE_BRACKETS(...) __VA_ARGS__
/**
* \param code a tuple containing the code you want to run
**/
#define SECTION_TIME(out, code) \
do { \
/* remember to save the value, so that the same output is always cleared */ \
decltype(out) _o = out; \
GPIO_SetOut(_o); \
{PP_REMOVE_BRACKETS code}; \
GPIO_ClrOut(_o); \
} while(0);
This can be used like this:
SECTION_TIME(GPIO_fooOut, (
foo();
bar();
foo=bar^foo;
//....;....;
));
all
My codes like this:
#define TTP_ROUTE_TABLE_ENTRY_INC(table) \
static inline void \
ttp_route_##table_inc(void) \
{ \
cur_l3_##table_table_entries++; \
}
TTP_ROUTE_TABLE_ENTRY_INC(ipv4_host)
TTP_ROUTE_TABLE_ENTRY_INC(ipv4_route)
TTP_ROUTE_TABLE_ENTRY_INC(ipv6_host)
TTP_ROUTE_TABLE_ENTRY_INC(ipv6_route)
#undef TTP_ROUTE_TABLE_ENTRY_INC
but gcc warning:
lib/ttp-route-table.c:130:1: error: redefinition of 'ttp_route_table_inc'
So I think GCC preprocess ##table into table, actually I want
TTP_ROUTE_TABLE_ENTRY_INC(ipv4_host)
will be translate into this:
static inline void \
ttp_route_ipv4_host_inc(void) \
{ \
cur_l3_ipv4_host_table_entries++; \
}
So I don't know what's wrong with my codes. Thank you for your help.
You need another set of # after the argument table:
ttp_route_##table##_inc(void)
The same goes for other lines containing table.
I'm trying to make a custom printf that prints the file / line no , along with the error message , depending on the current print level set. I've defined a macro for the same. Given below is the code for the preprocessor:
#define DIE (s) \
printf(s); \
exit(0); \
#define my_print(level,s) \
if(level <= gPrintLevel) \
{ \
char *buffer = (char *)malloc(strlen(s)-1); \
if (NULL != buffer) \
{ \
sprintf(buffer,s); \
printf("[%s][%d]:%s\n",__FUNCTION__,__LINE__,buffer); \
if (level == fatal) \
{\
DIE(s);\
}\
} \
} \
I'm calling the above pre-processor like this from inside a function:
myPrint(2,"Unexpected error encountered\n");
But, I'm getting the below compile errors when I try to compile:
41: error: āsā was not declared in this scope
Please help, what am I doing wrong ? Also, its appreciated if someone can tell me if there's a more elegant way of having customized print statements as above. Thanks in advance.
Personally, I would simply assume or mandate that the user provide a literal format string. In that case, you can concatenate strings:
#define MYPRINT(fmt, ...) \
printf("Function: %s. Line: %d. " fmt "\n", \
__FUNCTION__, __LINE__, ## __VA_ARGS__);
Usage:
MYPRINT("The flargle %d has unexpected grobule %f", f->q, f->r);
This approach also lets you take advantage of the compiler's ability to analyze the format string statically and warn you about mismatching arguments.
(The code uses a GCC extension involving ## to elide the final comma in case the argument list is empty.)
OK thanks for all the help guys, the variadic macros solution works fine. This is the new defn of the macro now:
#define DIE(fmt) \
do { \
printf(fmt); \
exit(0); \
} while(0); \
#define my_print(x,fmt,...) \
if (x < gPrintLevel) \
{ \
printf("[%s][%u]:" fmt "\n",__FUNCTION__,__LINE__,##__VA_ARGS__); \
if (fatal == x) \
{\
DIE(fmt) \
}\
} \
I'm trying to instrument some code to catch and print error messages. Currently I'm using a macro somethng like this:
#define my_function(x) \
switch(function(x)) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
}
Normally, I never capture the function output and this works fine. But I've found a couple cases where I also need the return value of function(). I tried something like the following, but this produces a syntax error.
#define my_function(x) \
do { \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
} while(0)
I could declare a global variable to hold the return value of the function, but that looks ugly and my program is multithreaded, so that's likely to cause problems. I'm hoping there's a better solution out there.
GCC has a feature called statement expressions
So if define macro like
#define FOO(A) ({int retval; retval = do_something(A); retval;})
then you will be able to use it like
foo = FOO(bar);
This is relatively complicated code, there is not much reason to have it in a macro. Make it inline (C99) or static (C89) or both if you really want to place it in a header file. With any reasonable compiler this then should result in the same efficiency as a macro.
A very late reply. But none the less. I agree inline functions are better but MACROs do offer some pretty printing fun you can't get with inline functions. I agree with #qrdl that you can indeed use statement expressions had you restructured your statements a bit. Here is how it would work with a macro -
#define my_function(x, y) ({ \
int __err = 0; \
do { \
__err = function(x, y); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
} while(0); \
__err; \
})
Sorry, this is an edit...
I think you just need the curly braces. No need for the do..while keywords
Make sure that the backslashes are the last characters on each line (no space after).
If you need to get the err value out of the macro, you can just add a parameter
Like so:
#define my_function(x, out) \
{ \
int __err = function(x); \
switch(__err) { \
case ERROR: \
fprintf(stderr, "Error!\n"); \
break; \
} \
__err; \
(*(out)) = _err; \
}
To preserve the pass-by-reference C paradigm, you should call my_function this way:
int output_err;
my_function(num, &output_err);
This way, later, if you decide to make my_function a real function, you don't need to change the call references.
Btw, qrdl's "Statement Expressions" is also a good way to do it.
there is no need to declare variable if your function is returning something then you can directly get that value. For example:
#define FOO(A) do_something(A)
Here do_something returns some integer. Then you can easily use it like:
int a = FOO(a);