Our C codebase is littered with pattern-like code that performs the same iteration, NULL
handling, etc. for any "list append" operation on structs which have a .next
pointer of the same type as themselves:
struct foo {
int bar;
char *baz;
struct foo *next;
}
Example pattern-code:
struct foo *foo_list;
int func(struct foo *f) {
struct foo *it;
...
if (!foo_list) {
foo_list = f;
} else {
for (it = foo_list; it->next; it = it->next)
{}
it->next = f;
}
...
}
I'm trying to come up with a macro that would simplify the append process for any struct with such a .next
member. Keep in mind that addition may also be done to a NULL
list, so the macro must also return the new list head:
#define add_last(what, where) \
({ \
if (!(where)) { \
(what); \
} else { \
typeof(where) __wit = (where); \
while (__wit->next) \
__wit = __wit->next; \
__wit->next = (what); \
(where); \
}})
However, when using it like this:
return add_last(filter, filters);
, gcc
isn't too happy, and spews:
cachedb/../db/../ut.h:104:4: warning: statement with no effect [-Wunused-value]
(what); \
^
cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’
return add_last(new, existing);
^
cachedb/../db/../ut.h:110:4: warning: statement with no effect [-Wunused-value]
(where); \
^
cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’
return add_last(new, existing);
^
cachedb/../db/../ut.h:103:2: error: void value not ignored as it ought to be
({ if (!(where)) { \
^
cachedb/cachedb.c:797:9: note: in expansion of macro ‘add_last’
return add_last(new, existing);
^
I've tried with a do while (0)
block, no luck either. Is what I'm trying even possible? Thank you!