With the uintptr_t data parameter, it is actually quite nice to have
VERB(do_impl, "name-a", …)
VERB(do_impl, "name-b", …)
int do_impl(…) { … }
To make this work, the do_impl_data struct needs to have a unique name and
we also need to suppress the warning about the forward declaration for
do_impl being repeated. I think it's fine to suppress the warning, it's
not needed for anything. If somebody declares the function with the same
name by mistake, the implementations are going to conflict too.
#define XCONCATENATE(x, y) x ## y
#define CONCATENATE(x, y) XCONCATENATE(x, y)
+#define CONCATENATE3(x, y, z) CONCATENATE(x, CONCATENATE(y, z))
#define assert_cc(expr) _Static_assert(expr, #expr)
} Verb;
#define VERB_FULL(d, v, a, amin, amax, f, dat, h) \
+ DISABLE_WARNING_REDUNDANT_DECLS \
static int d(int, char**, uintptr_t, void*); \
+ REENABLE_WARNING \
_section_("SYSTEMD_VERBS") \
_alignptr_ \
_used_ \
_retain_ \
_variable_no_sanitize_address_ \
- static const Verb CONCATENATE(d, _data) = { \
+ static const Verb CONCATENATE3(d, _data_, __COUNTER__) = { \
.verb = v, \
.min_args = amin, \
.max_args = amax, \