I would like to do something like the following:
F_BEGIN
F(f1) {some code}
F(f2) {some code}
...
F(fn) {some code}
F_END
and have it gene
There's this thing called X Macro which is used as:
a technique for reliable maintenance of parallel lists, of code or data, whose corresponding items must appear in the same order
This is how it works:
#include <stdio.h>
//you create macro that contains your values and place them in (yet) not defined macro
#define COLORS\
X(red, 91)\
X(green, 92)\
X(blue, 94)\
//you can name that macro however you like but conventional way is just an "X"
//and then you will be able to define a format for your values in that macro
#define X(name, value) name = value,
typedef enum { COLORS } Color;
#undef X //just another convention (so you don't use it accidentally, I think)
int main(void)
{
#define X(name, value) printf("%d, ", name);
COLORS
#undef X
return 0;
}
Solution for your problem would be:
#define FUNCTIONS \
F(f1, code1)\
F(f2, code2)\
F(f3, code3)
#define F(name, code) int name(void){code}
FUNCTIONS
#undef F
#define F(name, code) &name,
int (*function_table[])(void) = { FUNCTIONS };
#undef F
If you have a C99 complying compiler, the preprocessor has variable length argument lists. P99 has a preprocessor P99_FOR
that can do "code unrolling" like the one you want to achieve. To stay close to your example
#define MYFUNC(DUMMY, FN, I) int FN(void) { return I; }
#define GENFUNCS(...) \
P99_FOR(, P99_NARG(__VA_ARGS__), P00_IGN, MYFUNC, __VA_ARGS__) \
int (*function_table)(void)[] = { __VA_ARGS__ }
GENFUNCS(toto, hui, gogo);
would expand to the following (untested)
int toto(void) { return 0; }
int hui(void) { return 1; }
int gogo(void) { return 2; }
int (*function_table)(void)[] = { toto, hui, gogo };
The normal way of doing this with the preprocessor is to define all the functions in a macro that takes another macro as an argument, and then use other macros to extract what you want. For your example:
#define FUNCTION_TABLE(F) \
F(f1, { some code }) \
F(f2, { some code }) \
F(f3, { some code }) \
:
F(f99, { some code }) \
F(f100, { some code })
#define DEFINE_FUNCTIONS(NAME, CODE) int NAME() CODE
#define FUNCTION_NAME_LIST(NAME, CODE) NAME,
FUNCTION_TABLE(DEFINE_FUNCTIONS)
int (*function_table)(void)[] = { FUNCTION_TABLE(FUNCTION_NAME_LIST) };
This is sort of abuse of CPP but a common type of abuse. I handle situations like this by defining dummy macros
#define FUNCTIONS \
foo(a,b,c,d) \
foo(a,b,c,d) \
foo(a,b,c,d)
now,
#define foo(a,b,c,d) \
a+b ;
FUNCTIONS
#undef foo
later, when you want something different done with the same list
#define foo(a,b,c,d) \
a: c+d ;
FUNCTIONS
#undef foo
It's a bit ugly and cumbersome, but it works.
Boost is a C++ library, but it's Preprocessor module should still be good for use in C. It offers some surprisingly advanced data types and functionality for use in the preprocessor. You could check it out.