When writing C macro, there is a trick called "sequence iteration". It looks like as follow:
#define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define FUNCTION(name) void name();
#define FUNCTION_TABLE(seq) CAT(FUNCTION_TABLE_1 seq, _END)
#define FUNCTION_TABLE_1(x) FUNCTION(x) FUNCTION_TABLE_2
#define FUNCTION_TABLE_2(x) FUNCTION(x) FUNCTION_TABLE_1
#define FUNCTION_TABLE_1_END
#define FUNCTION_TABLE_2_END
FUNCTION_TABLE((x) (y) (z) (e))
The sequence, i.e. the argument of FUCTION_TABLE, will be processed one by one. However, as far as I know, a token will not be expanded twice in the same scope. Because it is "painted blue". When FUNCTION_TABLE_2 is expanded, the macro FUNCTION_TABLE_1 has already been painted yet. Why is it still expanded?
Function-like macro replacement is a recursive process:
#
and ##
#
or ##
is expanded#
and ##
(if any) are applied to the resulting operands(this is somewhat more complicated to describe than implement!). So for your code:
FUNCTION_TABLE((x) (y) (z) (e))
expands to CAT(FUNCTION_TABLE_1 (x) (y) (z) (e), _END)
CAT(X, _END)
expands to PRIMITIVE_CAT(expand(X), _END)
. Working out expand(X)
now:
FUNCTION_TABLE_1 (x) (y) (z) (e)
expands to FUNCTION(x) FUNCTION_TABLE_2 (y) (z) (e)
:
FUNCTION(x)
expands to void x();
FUNCTION_TABLE_2 (y) (z) (e)
expands to FUNCTION(y) FUNCTION_TABLE_1 (z) (e)
FUNCTION(y)
expands to void y();
FUNCTION_TABLE_1 (z) (e)
expands to FUNCTION(z) FUNCTION_TABLE_2(e)
FUNCTION(z)
expands to void z();
FUNCTION_TABLE_2(e)
expands to FUNCTION(e) FUNCTION_TABLE_1
FUNCTION(e)
expands to void e();
void e(); FUNCTION_TABLE_1
void z(); void e(); FUNCTION_TABLE_1
void y(); void z(); void e(); FUNCTION_TABLE_1
void x(); void y(); void z(); void e(); FUNCTION_TABLE_1
X
, let's recap where we are: PRIMITIVE_CAT(void x(); void y(); void z(); void e(); FUNCTION_TABLE_1, _END)
void x(); void y(); void z(); void e(); FUNCTION_TABLE_1_END
void x(); void y(); void z(); void e();
The idea is that inside a macro expansion all the expansion of parameters will start with the same BLUE-SET.
inside FUNCTION_TABLE(seq)
the expansion of ALL parameters inside FUNCTION_TABLE_1 seq
will start all the time with BLUE-SET={seq}. So after entering inside the FUNCTION_TABLE_1 the BLUE-SET is added the x
, but when this finishes it comes back to the scope of FUNCTION_TABLE
where the expansion starts again with the BLUE-SET={seq}
.
So, the first time it is expanded FUNCTION_TABLE_1(x)
and INSIDE this expansion the BLUE-SET={seq,x}
but when the expansion of FUNCTION_TABLE_1
finishes, it comes back to FUNCTION_TABLE
and it will expand next FROM this scope the FUNCTION_TABLE_2(y)
and INSIDE FUNCTION_TABLE_2
the BLUE-SET={seq, x} again, etc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With