Reuse variable in macro with modification - c

I'm trying to make a linked list for error handling in C. Functions would return the head element of the error list, or NULL.
I need macros to add file name, line numbers, ...
#define MAKE_ERR(MSG) \
_err_malloc(__FILE__, __LINE__, __PRETTY_FUNCTION__, MSG, NULL)
#define PUSH_ERR(NEXT, MSG) \
_err_malloc(__FILE__, __LINE__, __PRETTY_FUNCTION__, MSG, NEXT)
and I would like to make it easy to add the current frame as messages go up the stack:
#define FORWARD_ERR(NEXT) \
(NEXT ? PUSH_ERR(NEXT, NULL) : NULL)
err_t* foo();
err_t* bar() {
return FORWARD_ERR(foo());
}
The problem is that FORWARD_ERR uses NEXT twice.
I would like to use FORWARD_ERR as an expression. I can easily make it a block:
#define FORWARD_ERR(NEXT) \
{ err_t* N = (NEXT); return (N ? PUSH_ERR(N, NULL) : NULL) }
but I don't think that's a good solution.
I was trying to get it working with the Elvis operator a ?: b, but couldn't get it to work.

Clang and GCC both support statement expressions, which would let you do something like this:
#define FORWARD_ERR(NEXT) \
({ err_t* N = (NEXT); N ? PUSH_ERR(N, NULL) : NULL; })
Which lets you use it as an expression the way you want to but doesn't force you to embed the return statement inside your macro.

Related

Evaluate/print function return that is used as input to macro

I am trying to create a simple unit test library for my projects. I can get most things working, but now I am trying to add some functionality: printing the expressions/input.
It works if I pass arguments by actual value (1, 2.456, false), but if I pass a function argument I get the function string printed.
Here is my code explaining the problem
I am not 100% sure what the STR(x) macro is doing, copied it from somewhere online...
The code actually works (the evaluation of LHS and RHS) just the printing does not, shown below.
#include <stdio.h>
#define STR(x) #x
#define TEST_COMPARE_EQ(TestName, LHS, RHS) \
do { \
if ((LHS) != (RHS)) { \
printf("[Test: %s] --- Failed at line %d in file %s\n", TestName, __LINE__, __FILE__); \
printf("\Got value %s\n", STR(LHS)); \
printf("\Expected value %s\n", STR(RHS)); \
} \
else { \
printf("[Test: %s] --- Passed\n", TestName); \
}\
} while (0)
// Calling code example
// This works, prints:
// Got value 123
// Expected value 124
TEST_COMPARE_EQ("PrintingWorks", 123, 124);
// This however does not work.
// It prints
// Got value my_fn_that_returns_false
// Expected value true
// How can I get it to print the return value of my_fn_that_returns_false, and not
// the actual function name?
TEST_COMPARE_EQ("PrintingDoesNotWork", my_fn_that_returns_false(), true);
what the STR(x) macro is doing,
It takes the code as it is and adds " in front and back. STR(anything) is "anything", just like that.
How can I get it to print the return value
You have to print it.
printf("Got value %d\n", LHS);
No, there are no templates in C. It is hard to write type generic functions in C. You have to handle each possible type separately - like TEST_COMPARE_EQ_INT TEST_COMPARE_EQ_FLOAT etc. For inspiration, take a look at Unity C unit testing library.
Writing that in a type-generic way sounds like a nice challenge in C. It would look basically like the following:
void test_eq_int(int a, const char *astr, int b, const char *btr) {
if (a != b) {
printf("%s = %s -> %d != %s\n", astr, bstr, a, b);
}
}
void test_eq_long(....) { .... }
void test_eq_some_other_type(...) { .... }
// etc. for each possible type
#define TEST_COMPARE_EQ(msg, a, b) \
_Generic(a, \
int: test_eq_int, \
long: test_eq_long, \
/* etc. for each type */ \
)(msg, a, #a, b, #b);

getting the variable values in #define definition

Here is what I am trying to do.
step1) I want to call a macro with a conditional statement(simple are compounded) like
for eg:
MACRO1(a==1)
MACRO1((i!=NULL) && (j>10))
step2) Here is how i am defining this macro
#define MACRO1(condition) \
if(!(condition)) ??????????????????????????
Here in the definition of the macro, if the condition statement fails. I want to print the variable values so that I will be useful to know the exact reason.
I used #condition in the definition, but it just printing the condition, instead of the values of the variables used in the condition. Please help.
You could do something along these lines:
#define MACRO1(condition, msg) \
if(!(condition)) { printf msg; }
and use it as follows:
MACRO1(a==1, ("a: %d\n", a))
MACRO1((i != NULL) && (j>10), ("i: %p, j: %d\n", i, j));
The C preprocessor is just a simple substitution engine, without the capability of analyzing the contents of expressions.
You shouldn't define macros that look like a function, but behave differently, in particular in your case may change control flow: an else that follows a macro that contains an if can apply to something different than the programmer (yourself after a week) thinks. Protect the if such that a dangling else will not apply to it
#define MACRO1(COND, ...) \
do { \
if (!(COND)) printf(stderr, "condition " #COND ": " __VA_ARGS_); \
} while (0)
This macro should always be called with a format string as second argument and the names of the variables that you want to see
MACRO1((toto != 78.0), "toto=%9\n", toto);
this should print you something like
condition (toto != 78.0): toto=3.14
There is no way that I know of to separate the variables from the condition.
However, you can pass them in as extra parameters:
#define MACRO(condition, printsyntax, ...) \
if(!(condition)) {\
printf("condition %s not met! (" printsyntax ")\n", #condition, __VA_ARGS__); \
};
You would use it as:
MACRO((i!=NULL) && (j>10), "i=%p, j=%d", i, j)
with an example result being:
condition (i!=NULL) && (j>10) not met! (i=(nil), j=11)
The compiler will splice together the constant strings into one string for the printf,
the condition will automatically be printed and the rest of the arguments are your job to get right.
Edit
After Jens' remark about the else I modified the code a bit to not allow for such structures without using do{}while();.

Creating function-like macros

gcc 4.4.2 c89
I have this code snippet that I have to repeat in a lot of my code. I am just wondering is there a way to make it short by using a macro function?
There is the code I would like to change.
ERR_INFO error_info; /* create error object */
ErrorInfo(&error_info); /* pass the address for it to be filled with error info */
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); /* display the error msg */
And my attempt to create a macro function to use it.
#define DISPLAY_ERR(error_info) ErrorInfo(&error_info) error_info.msg
fprintf(stderr, "And the error is? [ %s ]\n", DISPLAY_ERR); /* display the error
Any suggestions would be most helpful,
If you really want a macro:
#define DISPLAY_ERR(error_info) \
do \
{ \
ErrorInfo(&(error_info)); \
fprintf(stderr, "And the error is? [ %s ]\n", (error_info).msg); \
} while(0)
You need the do... while(0) because of a good reason.
Then, you call your macro when you want to print the error:
if (error) {
DISPLAY_ERR(error_info);
/* more statements if needed */
}
I am assuming that error_info has been defined somewhere. If not, or if you don't want to, then you can change your macro definition and use:
#define DISPLAY_ERR() \
do \
{ \
ERR_INFO error_info;
ErrorInfo(&error_info); \
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); \
} while(0)
if (error) {
DISPLAY_ERR();
/* more statements if needed */
}
There's a couple of ways you could do this. You could use the comma operator:
#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info)),(error_info).msg)
...or you could change the ErrorInfo() function so that it's return value is the pointer you pass it:
#define DISPLAY_ERR(error_info) (ErrorInfo(&(error_info))->msg)
(and a few more options besides).
Are you trying to create a macro which "returns" a value? In C++ you can use the comma operator , to evaluate the left expression and then return the right expression. You can do the same in C, too.
(foo(var), var.field) // foo(...)is evaluated first,
// then second expression is returned
also
DISPLAY(message) // Pass an argument to macro
You need to make it work like a function call, so it can be used anywhere a function call can, except with no value returned. You also need to mark the ends of intermediate lines with a backslash. And the 'do { ... } while (0) idiom is useful in this context:
#define DISPLAY_ERR() do { ERR_INFO error_info; ErrorInfo(&error_info); \
fprintf(stderr, "And the error is? [ %s ]\n", error_info.msg); } while (0)
The error_info variable is local to the block, so you don't have to remember to declare it in the functions where you use the macro (or have it as a file static or, perish the thought, global variable).
Note that this code does not return a value, but it can be used anywhere in a function that a void expression could be used:
if (somefunc() != 0)
DISPLAY_ERR();
else if (anotherfunc() != 0)
DISPLAY_ERR();
else
do_something_useful_after_all();
Etc.
I would still want to make sure I measured the overhead of using a regular function versus having the function-like macro. Used often enough, you might be still be better off with a real function.

How to define a function

I want to define a following function:
if(stmtToFinalize) {
NSLog(#"Finalizing statement stmtToFinalize");
if (sqlite3_finalize(stmtToFinalize) !=SQLITE_OK)
NSLog(#"An error occured while trying to finalize a statement stmtToFinalize: '%s'", sqlite3_errmsg(database));
stmtToFinalize = NULL;
}
But I am not familiar with the #define directive. I want instead of stmtToFinalize to have any statement of type sqlite3_stmt.
How can I implement it?
Thank you.
Syntax for #define is not Objective-C specific.
#define MY_FUNCTION(x) do { \
if( (x) ) { \
NSLog(#"Finalizing statement stmtToFinalize"); \
if (sqlite3_finalize( (x) ) !=SQLITE_OK) \
NSLog(#"An error occured while trying to finalize a statement stmtToFinalize: '%s'", sqlite3_errmsg(database)); \
(x) = NULL; \
} } while (0)
Text in NSLog() format string has not been changed.

do { ... } while (0) — what is it good for? [duplicate]

This question already has answers here:
Why use apparently meaningless do-while and if-else statements in macros?
(9 answers)
Closed 2 years ago.
I've been seeing that expression for over 10 years now. I've been trying to think what it's good for. Since I see it mostly in #defines, I assume it's good for inner scope variable declaration and for using breaks (instead of gotos.)
Is it good for anything else? Do you use it?
It's the only construct in C that you can use to #define a multistatement operation, put a semicolon after, and still use within an if statement. An example might help:
#define FOO(x) foo(x); bar(x)
if (condition)
FOO(x);
else // syntax error here
...;
Even using braces doesn't help:
#define FOO(x) { foo(x); bar(x); }
Using this in an if statement would require that you omit the semicolon, which is counterintuitive:
if (condition)
FOO(x)
else
...
If you define FOO like this:
#define FOO(x) do { foo(x); bar(x); } while (0)
then the following is syntactically correct:
if (condition)
FOO(x);
else
....
It is a way to simplify error checking and avoid deep nested if's. For example:
do {
// do something
if (error) {
break;
}
// do something else
if (error) {
break;
}
// etc..
} while (0);
It helps to group multiple statements into a single one so that a function-like macro can actually be used as a function. Suppose you have:
#define FOO(n) foo(n);bar(n)
and you do:
void foobar(int n) {
if (n)
FOO(n);
}
then this expands to:
void foobar(int n) {
if (n)
foo(n);bar(n);
}
Notice that the second call bar(n) is not part of the if statement anymore.
Wrap both into do { } while(0), and you can also use the macro in an if statement.
It is interesting to note the following situation where the do {} while (0) loop won't work for you:
If you want a function-like macro that returns a value, then you will need a statement expression: ({stmt; stmt;}) instead of do {} while(0):
#include <stdio.h>
#define log_to_string1(str, fmt, arg...) \
do { \
sprintf(str, "%s: " fmt, "myprog", ##arg); \
} while (0)
#define log_to_string2(str, fmt, arg...) \
({ \
sprintf(str, "%s: " fmt, "myprog", ##arg); \
})
int main() {
char buf[1000];
int n = 0;
log_to_string1(buf, "%s\n", "No assignment, OK");
n += log_to_string1(buf + n, "%s\n", "NOT OK: gcc: error: expected expression before 'do'");
n += log_to_string2(buf + n, "%s\n", "This fixes it");
n += log_to_string2(buf + n, "%s\n", "Assignment worked!");
printf("%s", buf);
return 0;
}
Generically, do/while is good for any sort of loop construct where one must execute the loop at least once. It is possible to emulate this sort of looping through either a straight while or even a for loop, but often the result is a little less elegant. I'll admit that specific applications of this pattern are fairly rare, but they do exist. One which springs to mind is a menu-based console application:
do {
char c = read_input();
process_input(c);
} while (c != 'Q');

Resources