#ifdef inside a #define? - c
I'm initializing an array of structures with the help of a define like this:
#define FLAGCODE(name) { #name, MNT_ ## name }
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS),
FLAGCODE(ASYNC),
...
This works nicely, and now I'd like to add a check, whether each flag (such as MNT_ACLS) is defined without inserting an #ifdef and #endif for each symbol by hand?
That is, I want the macro FLAGCODE(name) to expand into (an equivalent of):
#ifdef MNT_ ##name
{ # name, MNT_ ##name },
#endif
Exempli gratia, if name is NOATIME, the code shall become:
#ifdef MNT_NOATIME
{ "NOATIME", MNT_NOATIME },
#endif
Yes, I realize, that this would mean double pass through preprocessor, and so is unlikely to be possible -- without a custom code-generator... But still...
There is a solution but highly not recommended! You could do funny things with C-preprocessor (cf. Macro to replace nested for loops and links in the question). But I repeat it: Don't do it. It is a cpp abuse.
In two words, you have to create your own #ifdef with macro. In the code below, ISDEF is an "operator" to check if the flag is defined and #if has been redefined: IIF (To understand, all explanations are here: https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms)
#define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__
#define COMMA ,
#define IIF(c) PRIMITIVE_CAT(IIF_, c)
#define IIF_0(t, ...) __VA_ARGS__
#define IIF_1(t, ...) t
#define CHECK_N(x, n, ...) n
#define CHECK(...) CHECK_N(__VA_ARGS__, 0,)
#define PROBE(x) x, 1,
#define ISDEF(x) CHECK(PRIMITIVE_CAT(ISDEF_, x))
#define ISDEF_ PROBE(~)
#define FLAGCODE(name) IIF(ISDEF(name))({ #name COMMA MNT_ ## name }COMMA)
#define ACLS
#define FLAGDEFINED
int main()
{
struct {
const char *name;
uint64_t flag;
} flagcodes[] = {
FLAGCODE(ACLS)
FLAGCODE(ASYNC)
FLAGCODE(FLAGDEFINED)
FLAGCODE(FLAGNOTDEFINED)
...
You could also do a list with your flags (cf. MAP part in http://jhnet.co.uk/articles/cpp_magic).
Enjoy but do not go overboard with preprocessor.
Following the very good comment of Chris Dodd,
1 : This tricks works if the flag is define as empty (#define FLAGDEFINED). It does not work with, for example, #define FLAGDEFINED 1 or #define FLAGDEFINED xxx.
2 : CPP_ prefix has been added and name is changed by CPP_FLAG
#define CPP_PRIMITIVE_CAT(CPP_a, ...) CPP_a ## __VA_ARGS__
#define CPP_COMMA ,
#define CPP_IIF(CPP_c) CPP_PRIMITIVE_CAT(CPP_IIF_, CPP_c)
#define CPP_IIF_0(CPP_t, ...) __VA_ARGS__
#define CPP_IIF_1(CPP_t, ...) CPP_t
#define CPP_CHECK_N(CPP_x, CPP_n, ...) CPP_n
#define CPP_CHECK(...) CPP_CHECK_N(__VA_ARGS__, 0,)
#define CPP_PROBE(CPP_x) CPP_x, 1,
#define CPP_ISDEF(CPP_x) CPP_CHECK(CPP_PRIMITIVE_CAT(CPP_ISDEF_, CPP_x))
#define CPP_ISDEF_ CPP_PROBE(~)
#define CPP_FLAGCODE(CPP_FLAG) CPP_IIF(CPP_ISDEF(CPP_FLAG))({ #CPP_FLAG CPP_COMMA MNT_ ## CPP_FLAG }CPP_COMMA)
#define ACLS
#define FLAGDEFINED
Related
Adding separators in iteration over __VA_ARGS__ in C/C++ macro
background I'm trying to make automatic generator of Lua-C interface using C macros. The biggest problem was to make it general for varying number of arguments, which I resolved by using __VA_ARGS__ with help of this answer: Is it possible to iterate over arguments in variadic macros? Simpler almost working solution this solution almost works, but it produce some redudant commas (nottice ,,,, in output) // helper macros for iteration over __VA_ARGS__ #define ARG1(WHAT,X,...) WHAT(X)ARG2(WHAT,__VA_ARGS__) #define ARG2(WHAT,X,...) WHAT(X)ARG3(WHAT,__VA_ARGS__) #define ARG3(WHAT,X,...) WHAT(X)ARG4(WHAT,__VA_ARGS__) #define ARG4(WHAT,X,...) WHAT(X)ARG5(WHAT,__VA_ARGS__) #define ARG5(WHAT,X,...) WHAT(X)ARG6(WHAT,__VA_ARGS__) #define ARG6(WHAT,X,...) WHAT(X)//ARG2(__VA_ARGS__) // macros dispatch propper type of Lua::get #define LUA_GET_int(i) Lua::getInt(L,i) #define LUA_GET_long(i) Lua::getInt(L,i) #define LUA_GET_float(i) (float)Lua::getDouble(L,i) #define LUA_GET_double(i) Lua::getDouble(L,i) #define LUA_GET_string(i) Lua::getString(L,i) #define LUA_PUSH_int(a) lua_pushnumber(L,a) #define LUA_PUSH_float(a) lua_pushnumber(L,a) #define LUA_PUSH_double(a) lua_pushnumber(L,a) #define LUA_PUSH_float(a) lua_pushstring(L,a) #define LUA_GET_(T) #define LUA_GET(T) ,LUA_GET_##T(i++) // commas come from here #define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; } // interface for function: // double add3(float, int, double ); MAKE_LUA_FUNC( double, add3, float, int, double ) // output: // 'int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3((float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++),,,, )); return 1; }' Working but less-nice solution I had to duplicate LUA_GET_ macros for case when it is first in argument list (without comma) and otherwise (with comma in front) // begin of argument list => no commas #define LUA_GET_int(i) Lua::getInt(L,i) #define LUA_GET_long(i) Lua::getInt(L,i) #define LUA_GET_float(i) (float)Lua::getDouble(L,i) #define LUA_GET_double(i) Lua::getDouble(L,i) #define LUA_GET_string(i) Lua::getString(L,i) // rest of argument list => with commas #define LUA_GET__int(i) ,Lua::getInt(L,i) #define LUA_GET__long(i) ,Lua::getInt(L,i) #define LUA_GET__float(i) ,(float)Lua::getDouble(L,i) #define LUA_GET__double(i) ,Lua::getDouble(L,i) #define LUA_GET__string(i) ,Lua::getString(L,i) #define LUA_PUSH_int(a) lua_pushnumber(L,a) #define LUA_PUSH_float(a) lua_pushnumber(L,a) #define LUA_PUSH_double(a) lua_pushnumber(L,a) #define LUA_PUSH_float(a) lua_pushstring(L,a) #define LUA_GET_(T) #define LUA_GET__(T) #define LUA_GET(T) LUA_GET__##T(i++) #define MAKE_LUA_FUNC(TR,fname,T1,...) int l_##fname(lua_State * L){ int i=0; LUA_PUSH_##TR( fname( LUA_GET_##T1(i++) ARG1(LUA_GET,__VA_ARGS__) ) ); return 1; } // MAKE_LUA_FUNC( double, add3, float, int, double ) // output: // int l_add3(lua_State * L){ int i=0; lua_pushnumber(L,add3( (float)Lua::getDouble(L,i++) ,Lua::getInt(L,i++),Lua::getDouble(L,i++) )); return 1; } Is it possible to make it simpler / nicer ? NOTE - for debugging I found very useful this Seeing expanded C macros in particular https://stackoverflow.com/a/31460434/1291544
You need to count the number of arguments you have, and then call the corresponding ARG# macro. #define ARGS_N(M,...) \ ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__) #define ARGS_N__(_1, _2, _3, _4, _5, _6, X, ...) ARGS_##X #define ARGS_1(M, X) M(X) #define ARGS_2(M, X, ...) M(X)ARGS_1(M, __VA_ARGS__) #define ARGS_3(M, X, ...) M(X)ARGS_2(M, __VA_ARGS__) #define ARGS_4(M, X, ...) M(X)ARGS_3(M, __VA_ARGS__) #define ARGS_5(M, X, ...) M(X)ARGS_4(M, __VA_ARGS__) #define ARGS_6(M, X, ...) M(X)ARGS_5(M, __VA_ARGS__) Now, change MAKE_LUA_FUNC to call ARGS_N instead of your ARG1. The way the counting technique works is that ARGS_N invokes the helper ARGS_N__ with the variable arguments, and then pads out the invocation with additional arguments. ARGS_N__ does the counting by always utilizing the 7th argument. So, if ARGS_N is provided 4 variable arguments after the first one, ARGS_N__ will produce ARGS_4, because in that case, in the padding provided by ARGS_N, 4 would be the 7th argument. ARGS_N__(__VA_ARGS__, 6, 5, 4, 3, 2, 1)(M, __VA_ARGS__) . . /|\ /|\ | | If this has 4 arguments | This would be the 7th argument This is the same technique that was shown in the answer you pointed to. However, that version was a bit more complicated than the version I am illustrating for you, so hopefully you will find this explanation helpful.
C Macros: How to map another macro to variadic arguments?
I'd like to know how to apply a unary function (or another macro) to variadic arguments of a macro, like int f(int a); #define apply(args...) <the magic> apply(a, b, c) which unrolls f(a) f(b) f(c) Note that the number of arguments is unknown.
The code below is working for what you've asked for with up to 1024 arguments and without using additional stuff like boost. It defines an EVAL(...) and also a MAP(m, first, ...) macro to do recursion and to use for each iteration the macro m with the next parameter first. With the use of that, your apply(...) looks like: #define apply(...) EVAL(MAP(apply_, __VA_ARGS__)). It is mostly copied from C Pre-Processor Magic. It is also great explained there. You can also download these helper macros like EVAL(...) at this git repository, there are also a lot of explanation in the actual code. It is variadic so it takes the number of arguments you want. But I changed the FIRST and the SECOND macro as it uses a Gnu extension like it is in the source I've copied it from. This is said in the comments below by #HWalters: Specifically, 6.10.3p4: "Otherwise [the identifier-list ends in a ...] there shall be more arguments in the invocation than there are parameters in the macro definition (excluding the ...)". Main function part: int main() { int a, b, c; apply(a, b, c) /* Expands to: f(a); f(b); f(c); */ return 0; } Macro definitions: #define FIRST_(a, ...) a #define SECOND_(a, b, ...) b #define FIRST(...) FIRST_(__VA_ARGS__,) #define SECOND(...) SECOND_(__VA_ARGS__,) #define EMPTY() #define EVAL(...) EVAL1024(__VA_ARGS__) #define EVAL1024(...) EVAL512(EVAL512(__VA_ARGS__)) #define EVAL512(...) EVAL256(EVAL256(__VA_ARGS__)) #define EVAL256(...) EVAL128(EVAL128(__VA_ARGS__)) #define EVAL128(...) EVAL64(EVAL64(__VA_ARGS__)) #define EVAL64(...) EVAL32(EVAL32(__VA_ARGS__)) #define EVAL32(...) EVAL16(EVAL16(__VA_ARGS__)) #define EVAL16(...) EVAL8(EVAL8(__VA_ARGS__)) #define EVAL8(...) EVAL4(EVAL4(__VA_ARGS__)) #define EVAL4(...) EVAL2(EVAL2(__VA_ARGS__)) #define EVAL2(...) EVAL1(EVAL1(__VA_ARGS__)) #define EVAL1(...) __VA_ARGS__ #define DEFER1(m) m EMPTY() #define DEFER2(m) m EMPTY EMPTY()() #define IS_PROBE(...) SECOND(__VA_ARGS__, 0) #define PROBE() ~, 1 #define CAT(a,b) a ## b #define NOT(x) IS_PROBE(CAT(_NOT_, x)) #define _NOT_0 PROBE() #define BOOL(x) NOT(NOT(x)) #define IF_ELSE(condition) _IF_ELSE(BOOL(condition)) #define _IF_ELSE(condition) CAT(_IF_, condition) #define _IF_1(...) __VA_ARGS__ _IF_1_ELSE #define _IF_0(...) _IF_0_ELSE #define _IF_1_ELSE(...) #define _IF_0_ELSE(...) __VA_ARGS__ #define HAS_ARGS(...) BOOL(FIRST(_END_OF_ARGUMENTS_ __VA_ARGS__)()) #define _END_OF_ARGUMENTS_() 0 #define MAP(m, first, ...) \ m(first) \ IF_ELSE(HAS_ARGS(__VA_ARGS__))( \ DEFER2(_MAP)()(m, __VA_ARGS__) \ )( \ /* Do nothing, just terminate */ \ ) #define _MAP() MAP #define apply_(x) f(x); #define apply(...) EVAL(MAP(apply_, __VA_ARGS__)) To test macro expansion it is useful to use gcc with the command line argument -E: $ gcc -E srcFile.c because your're getting concrete error messages and understand what's going on.
Everything is possible in C if you throw enough ugly macros at it. For example, you can have an ugly function-like macro: #include <stdio.h> int f (int a) { printf("%d\n", a); } #define SIZEOF(arr) (sizeof(arr) / sizeof(*arr)) #define apply(...) \ { \ int arr[] = {__VA_ARGS__}; \ for(size_t i=0; i<SIZEOF(arr); i++) \ { \ f(arr[i]); \ } \ } int main (void) { apply(1, 2, 3); } Notice that 1) This would be much better off as a variadic function, and 2) it would be even better if you get rid of the variadic nonsense entirely and simply make a function such as int f (size_t n, int array[n])
C Preprocessor generate macros by concatenation and stringification [duplicate]
This question already has answers here: What are the applications of the ## preprocessor operator and gotchas to consider? (13 answers) Closed 7 years ago. I have a set of target macros for which I want to generate aliases based on a choosing macro, like so: Choosing macro: #define I2C_MODULE 1 Alias macros (conceptual form): #define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE #define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE> Target macros (from an external file out of my control): #define INT_I2C0 24 #define INT_I2C1 53 ... #define I2C0_BASE 0x40020000 #define I2C1_BASE 0x40021000 ... I wanted to have the preprocessor generate the alias macros I2C_MODULE_BASE and I2C_MODULE_NVIC based on the choosing macro I2C_MODULE, but after much reading Q1, P1 and many other references I lost track of, I ended up hard-coding their values. Below I show my current working definitions, and then my last failed attempts at generating the macros: What works: #define I2C_MODULE 1 #define I2C_MODULE_BASE I2C1_BASE #define I2C_MODULE_NVIC INT_I2C1 what did not work: #define I2C_MODULE 1 #define STR_HELPER(x) #x #define STR(x) STR_HELPER(x) /* Attempt 1 */ #define I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE" #define I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE) /* Attempt 2 */ #define _I2C_MODULE_BASE "I2C" STR(I2C_MODULE) "_BASE" #define _I2C_MODULE_NVIC "INT_I2C" STR(I2C_MODULE) #define I2C_MODULE_BASE _I2C_MODULE_BASE #define I2C_MODULE_NVIC _I2C_MODULE_NVIC EDIT: I expanded upon the accepted answer to get to where I wanted, as follows: #define PASTE2(a, b) a ## b #define PASTE3(a, b, c) a ## b ## c #define _I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE) #define _I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x) #define I2C_MODULE_BASE _I2C_MODULE_BASE(I2C_MODULE) #define I2C_MODULE_NVIC _I2C_MODULE_NVIC(I2C_MODULE)
This seems to work: #define I2C_MODULE 1 //Alias macros (conceptual form): //#define I2C_MODULE_BASE I2C<Value of I2C_MODULE>_BASE //#define I2C_MODULE_NVIC INT_I2C<Value of I2C_MODULE> //Target macros (from an external file out of my control): #define INT_I2C0 24 #define INT_I2C1 53 #define I2C0_BASE 0x40020000 #define I2C1_BASE 0x40021000 #define PASTE2(a, b) a ## b #define PASTE3(a, b, c) a ## b ## c #define I2C_MODULE_BASE(x) PASTE3(I2C, x, _BASE) #define I2C_MODULE_NVIC(x) PASTE2(INT_I2C, x) extern int i2c_module_base = I2C_MODULE_BASE(I2C_MODULE); extern int i2c_module_nvic = I2C_MODULE_NVIC(I2C_MODULE); extern int i2c_module_base_0 = I2C_MODULE_BASE(0); extern int i2c_module_nvic_0 = I2C_MODULE_NVIC(0); extern int i2c_module_base_1 = I2C_MODULE_BASE(1); extern int i2c_module_nvic_1 = I2C_MODULE_NVIC(1); Sample output (from cpp): # 1 "xx.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "xx.c" # 21 "xx.c" extern int i2c_module_base = 0x40021000; extern int i2c_module_nvic = 53; extern int i2c_module_base_0 = 0x40020000; extern int i2c_module_nvic_0 = 24; extern int i2c_module_base_1 = 0x40021000; extern int i2c_module_nvic_1 = 53; It is closely based on my answer to C preprocessor and token concatenation. There are undoubtedly other ways that the I2C_MODULE_BASE and I2C_MODULE_NVIC macros could be written, but the key points are: Using the ## token pasting operator (not the # stringifying operator). Using two levels of macro (for example, I2C_MODULE_BASE and PASTE3).
I suspect that you are writing a I2C driver which can generically handle multiple I2C hardware peripherals in the same micro-controller without rewriting all the same code multiple times. In that case, what you are really looking for probably is something like this: #define I2C1 ((volatile uint8_t*)0x12345678) // address of first hw register for I2C1 #define I2C2 ((volatile uint8_t*)0x55555555) // address of first hw register for I2C2 /* map all registers used for I2C, they will have same register layout for every peripheral no matter which one: */ #define I2C_CONTROL(base) (*(base + 0)) #define I2C_DATA(base) (*(base + 1)) ... // create some dummy typedef to make your functions look nice: typedef volatile uint8_t* I2C_t; // define whatever functions you need in the driver: void i2c_init (IC2_t bus); void i2c_send (I2C_t bus, const uint8_t* data, size_t n); ... // implement functions in a bus-independent way: void i2c_init (IC2_t bus) { I2C_CONTROL(bus) = THIS | THAT; // setup registers } // caller code: i2c_init(I2C1); i2c_init(I2C2); ... i2c_send(I2C1, "hello", 5); i2c_send(I2C2, "world", 5);
Just use #if / #else / #endif #if (I2C_MODULE == 0) #define I2C_MODULE_BASE I2C0_BASE #define I2C_MODULE_NVIC INT_I2C0 #elif (I2C_MODULE == 1) #define I2C_MODULE_BASE I2C1_BASE #define I2C_MODULE_NVIC INT_I2C1 #else #error Unknown configuration #endif
Define array and symbolic indices at same time
I'm trying to think of a clever way (in C) to create an array of strings, along with symbolic names (enum or #define) for the array indices, in one construct for easy maintenance. Something like: const char *strings[] = { M(STR_YES, "yes"), M(STR_NO, "no"), M(STR_MAYBE, "maybe") }; where the result would be equivalent to: const char *strings[] = {"yes", "no", "maybe"}; enum indices {STR_YES, STR_NO, STR_MAYBE}; (or #define STR_YES 0, etc) but I'm drawing a blank for how to construct the M macro in this case. Any clever ideas?
A technique used in the clang compiler source is to create .def files that contains a list like this, which is designed like a C file and can easily be maintained without touching other code files that use it. For example: #ifndef KEYWORD #define KEYWORD(X) #endif #ifndef LAST_KEYWORD #define LAST_KEYWORD(X) KEYWORD(X) #endif KEYWORD(return) KEYWORD(switch) KEYWORD(while) .... LAST_KEYWORD(if) #undef KEYWORD #undef LAST_KEYWORD Now, what it does is including the file like this: /* some code */ #define KEYWORD(X) #X, #define LAST_KEYWORD(X) #X const char *strings[] = { #include "keywords.def" }; #define KEYWORD(X) kw_##X, #define LAST_KEYWORD(X) kw_##X enum { #include "keywords.def" }; In your case, you could do similar. If you can live with STR_yes, STR_no, ... as enumerator names you could use the same approach like above. Otherwise, just pass the macro two things. One lowercase name and one uppercase name. Then you could stringize the one you want like above.
This is a good place to use code generation. Use a language like perl, php or whatever to generate your .h file.
It is not required to put this into specific .def files; using only the preprocessor is perfectly possible. I usually define a list named ...LIST where each element is contained within ...LIST_ELEMENT. Depending on what I will use the list for I will either just separate with a comma for all but the last entry (simplest), or in the general case make it possible to select the separator individually on each usage. Example: #include <string.h> #define DIRECTION_LIST \ DIRECTION_LIST_ELEMENT( up, DIRECTION_LIST_SEPARATOR ) \ DIRECTION_LIST_ELEMENT( down, DIRECTION_LIST_SEPARATOR ) \ DIRECTION_LIST_ELEMENT( right, DIRECTION_LIST_SEPARATOR ) \ DIRECTION_LIST_ELEMENT( left, NO_COMMA ) #define COMMA , #define NO_COMMA /**/ #define DIRECTION_LIST_ELEMENT(elem, sep) elem sep #define DIRECTION_LIST_SEPARATOR COMMA typedef enum { DIRECTION_LIST } direction_t; #undef DIRECTION_LIST_ELEMENT #undef DIRECTION_LIST_SEPARATOR #define DIRECTION_LIST_ELEMENT(elem, sep) void (*move_ ## elem)(struct object_s * object); #define DIRECTION_LIST_SEPARATOR NO_COMMA typedef struct object_s { char *name; // ... DIRECTION_LIST } object_t; #undef DIRECTION_LIST_ELEMENT #undef DIRECTION_LIST_SEPARATOR static void move(object_t *object_p, const char * direction_string) { if (0) { } #define DIRECTION_LIST_SEPARATOR NO_COMMA #define DIRECTION_LIST_ELEMENT(elem, sep) \ else if (strcmp(direction_string, #elem) == 0) { \ object_p->move_ ## elem(object_p); \ } DIRECTION_LIST #undef DIRECTION_LIST_ELEMENT #undef DIRECTION_LIST_SEPARATOR }
How to write a while loop with the C preprocessor?
I am asking this question from an educational/hacking point of view, (I wouldn't really want to code like this). Is it possible to implement a while loop only using C preprocessor directives. I understand that macros cannot be expanded recursively, so how would this be accomplished?
If you want to implement a while loop, you will need to use recursion in the preprocessor. The easiest way to do recursion is to use a deferred expression. A deferred expression is an expression that requires more scans to fully expand: #define EMPTY() #define DEFER(id) id EMPTY() #define OBSTRUCT(id) id DEFER(EMPTY)() #define EXPAND(...) __VA_ARGS__ #define A() 123 A() // Expands to 123 DEFER(A)() // Expands to A () because it requires one more scan to fully expand EXPAND(DEFER(A)()) // Expands to 123, because the EXPAND macro forces another scan Why is this important? Well when a macro is scanned and expanding, it creates a disabling context. This disabling context will cause a token, that refers to the currently expanding macro, to be painted blue. Thus, once its painted blue, the macro will no longer expand. This is why macros don't expand recursively. However, a disabling context only exists during one scan, so by deferring an expansion we can prevent our macros from becoming painted blue. We will just need to apply more scans to the expression. We can do that using this EVAL macro: #define EVAL(...) EVAL1(EVAL1(EVAL1(__VA_ARGS__))) #define EVAL1(...) EVAL2(EVAL2(EVAL2(__VA_ARGS__))) #define EVAL2(...) EVAL3(EVAL3(EVAL3(__VA_ARGS__))) #define EVAL3(...) EVAL4(EVAL4(EVAL4(__VA_ARGS__))) #define EVAL4(...) EVAL5(EVAL5(EVAL5(__VA_ARGS__))) #define EVAL5(...) __VA_ARGS__ Next, we define some operators for doing some logic(such as if, etc): #define CAT(a, ...) PRIMITIVE_CAT(a, __VA_ARGS__) #define PRIMITIVE_CAT(a, ...) a ## __VA_ARGS__ #define CHECK_N(x, n, ...) n #define CHECK(...) CHECK_N(__VA_ARGS__, 0,) #define NOT(x) CHECK(PRIMITIVE_CAT(NOT_, x)) #define NOT_0 ~, 1, #define COMPL(b) PRIMITIVE_CAT(COMPL_, b) #define COMPL_0 1 #define COMPL_1 0 #define BOOL(x) COMPL(NOT(x)) #define IIF(c) PRIMITIVE_CAT(IIF_, c) #define IIF_0(t, ...) __VA_ARGS__ #define IIF_1(t, ...) t #define IF(c) IIF(BOOL(c)) Now with all these macros we can write a recursive WHILE macro. We use a WHILE_INDIRECT macro to refer back to itself recursively. This prevents the macro from being painted blue, since it will expand on a different scan(and using a different disabling context). The WHILE macro takes a predicate macro, an operator macro, and a state(which is the variadic arguments). It keeps applying this operator macro to the state until the predicate macro returns false(which is 0). #define WHILE(pred, op, ...) \ IF(pred(__VA_ARGS__)) \ ( \ OBSTRUCT(WHILE_INDIRECT) () \ ( \ pred, op, op(__VA_ARGS__) \ ), \ __VA_ARGS__ \ ) #define WHILE_INDIRECT() WHILE For demonstration purposes, we are just going to create a predicate that checks when number of arguments are 1: #define NARGS_SEQ(_1,_2,_3,_4,_5,_6,_7,_8,N,...) N #define NARGS(...) NARGS_SEQ(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1) #define IS_1(x) CHECK(PRIMITIVE_CAT(IS_1_, x)) #define IS_1_1 ~, 1, #define PRED(x, ...) COMPL(IS_1(NARGS(__VA_ARGS__))) Next we create an operator, which we will just concat two tokens. We also create a final operator(called M) that will process the final output: #define OP(x, y, ...) CAT(x, y), __VA_ARGS__ #define M(...) CAT(__VA_ARGS__) Then using the WHILE macro: M(EVAL(WHILE(PRED, OP, x, y, z))) //Expands to xyz Of course, any kind of predicate or operator can be passed to it.
Take a look at the Boost preprocessor library, which allows you to write loops in the preprocessor, and much more.
You use recursive include files. Unfortunately, you can't iterate the loop more than the maximum depth that the preprocessor allows. It turns out that C++ templates are Turing Complete and can be used in similar ways. Check out Generative Programming
I use meta-template programming for this purpose, its fun once you get a hang of it. And very useful at times when used with discretion. Because as mentioned its turing complete, to the point where you can even cause the compiler to get into an infinite loop, or stack-overflow! There is nothing like going to get some coffee just to find your compilation is using up 30+ gigabytes of memory and all the CPU to compile your infinite loop code!
well, not that it's a while loop, but a counter loop, nonetheless the loop is possible in clean CPP (no templates and no C++) #ifdef pad_always #define pad(p,f) p##0 #else #define pad0(p,not_used) p #define pad1(p,not_used) p##0 #define pad(p,f) pad##f(p,) #endif // f - padding flag // p - prefix so far // a,b,c - digits // x - action to invoke #define n0(p,x) #define n1(p,x) x(p##1) #define n2(p,x) n1(p,x) x(p##2) #define n3(p,x) n2(p,x) x(p##3) #define n4(p,x) n3(p,x) x(p##4) #define n5(p,x) n4(p,x) x(p##5) #define n6(p,x) n5(p,x) x(p##6) #define n7(p,x) n6(p,x) x(p##7) #define n8(p,x) n7(p,x) x(p##8) #define n9(p,x) n8(p,x) x(p##9) #define n00(f,p,a,x) n##a(pad(p,f),x) #define n10(f,p,a,x) n00(f,p,9,x) x(p##10) n##a(p##1,x) #define n20(f,p,a,x) n10(f,p,9,x) x(p##20) n##a(p##2,x) #define n30(f,p,a,x) n20(f,p,9,x) x(p##30) n##a(p##3,x) #define n40(f,p,a,x) n30(f,p,9,x) x(p##40) n##a(p##4,x) #define n50(f,p,a,x) n40(f,p,9,x) x(p##50) n##a(p##5,x) #define n60(f,p,a,x) n50(f,p,9,x) x(p##60) n##a(p##6,x) #define n70(f,p,a,x) n60(f,p,9,x) x(p##70) n##a(p##7,x) #define n80(f,p,a,x) n70(f,p,9,x) x(p##80) n##a(p##8,x) #define n90(f,p,a,x) n80(f,p,9,x) x(p##90) n##a(p##9,x) #define n000(f,p,a,b,x) n##a##0(f,pad(p,f),b,x) #define n100(f,p,a,b,x) n000(f,p,9,9,x) x(p##100) n##a##0(1,p##1,b,x) #define n200(f,p,a,b,x) n100(f,p,9,9,x) x(p##200) n##a##0(1,p##2,b,x) #define n300(f,p,a,b,x) n200(f,p,9,9,x) x(p##300) n##a##0(1,p##3,b,x) #define n400(f,p,a,b,x) n300(f,p,9,9,x) x(p##400) n##a##0(1,p##4,b,x) #define n500(f,p,a,b,x) n400(f,p,9,9,x) x(p##500) n##a##0(1,p##5,b,x) #define n600(f,p,a,b,x) n500(f,p,9,9,x) x(p##600) n##a##0(1,p##6,b,x) #define n700(f,p,a,b,x) n600(f,p,9,9,x) x(p##700) n##a##0(1,p##7,b,x) #define n800(f,p,a,b,x) n700(f,p,9,9,x) x(p##800) n##a##0(1,p##8,b,x) #define n900(f,p,a,b,x) n800(f,p,9,9,x) x(p##900) n##a##0(1,p##9,b,x) #define n0000(f,p,a,b,c,x) n##a##00(f,pad(p,f),b,c,x) #define n1000(f,p,a,b,c,x) n0000(f,p,9,9,9,x) x(p##1000) n##a##00(1,p##1,b,c,x) #define n2000(f,p,a,b,c,x) n1000(f,p,9,9,9,x) x(p##2000) n##a##00(1,p##2,b,c,x) #define n3000(f,p,a,b,c,x) n2000(f,p,9,9,9,x) x(p##3000) n##a##00(1,p##3,b,c,x) #define n4000(f,p,a,b,c,x) n3000(f,p,9,9,9,x) x(p##4000) n##a##00(1,p##4,b,c,x) #define n5000(f,p,a,b,c,x) n4000(f,p,9,9,9,x) x(p##5000) n##a##00(1,p##5,b,c,x) #define n6000(f,p,a,b,c,x) n5000(f,p,9,9,9,x) x(p##6000) n##a##00(1,p##6,b,c,x) #define n7000(f,p,a,b,c,x) n6000(f,p,9,9,9,x) x(p##7000) n##a##00(1,p##7,b,c,x) #define n8000(f,p,a,b,c,x) n7000(f,p,9,9,9,x) x(p##8000) n##a##00(1,p##8,b,c,x) #define n9000(f,p,a,b,c,x) n8000(f,p,9,9,9,x) x(p##9000) n##a##00(1,p##9,b,c,x) #define n00000(f,p,a,b,c,d,x) n##a##000(f,pad(p,f),b,c,d,x) #define n10000(f,p,a,b,c,d,x) n00000(f,p,9,9,9,9,x) x(p##10000) n##a##000(1,p##1,b,c,d,x) #define n20000(f,p,a,b,c,d,x) n10000(f,p,9,9,9,9,x) x(p##20000) n##a##000(1,p##2,b,c,d,x) #define n30000(f,p,a,b,c,d,x) n20000(f,p,9,9,9,9,x) x(p##30000) n##a##000(1,p##3,b,c,d,x) #define n40000(f,p,a,b,c,d,x) n30000(f,p,9,9,9,9,x) x(p##40000) n##a##000(1,p##4,b,c,d,x) #define n50000(f,p,a,b,c,d,x) n40000(f,p,9,9,9,9,x) x(p##50000) n##a##000(1,p##5,b,c,d,x) #define n60000(f,p,a,b,c,d,x) n50000(f,p,9,9,9,9,x) x(p##60000) n##a##000(1,p##6,b,c,d,x) #define n70000(f,p,a,b,c,d,x) n60000(f,p,9,9,9,9,x) x(p##70000) n##a##000(1,p##7,b,c,d,x) #define n80000(f,p,a,b,c,d,x) n70000(f,p,9,9,9,9,x) x(p##80000) n##a##000(1,p##8,b,c,d,x) #define n90000(f,p,a,b,c,d,x) n80000(f,p,9,9,9,9,x) x(p##90000) n##a##000(1,p##9,b,c,d,x) #define cycle5(c1,c2,c3,c4,c5,x) n##c1##0000(0,,c2,c3,c4,c5,x) #define cycle4(c1,c2,c3,c4,x) n##c1##000(0,,c2,c3,c4,x) #define cycle3(c1,c2,c3,x) n##c1##00(0,,c2,c3,x) #define cycle2(c1,c2,x) n##c1##0(0,,c2,x) #define cycle1(c1,x) n##c1(,x) #define concat(a,b,c) a##b##c #define ck(arg) a[concat(,arg,-1)]++; #define SIZEOF(x) (sizeof(x) / sizeof((x)[0])) void check5(void) { int i, a[32769]; for (i = 0; i < SIZEOF(a); i++) a[i]=0; cycle5(3,2,7,6,9,ck); for (i = 0; i < SIZEOF(a); i++) if (a[i] != 1) printf("5: [%d] = %d\n", i+1, a[i]); }
Here's an abuse of the rules that would get it done legally. Write your own C preprocessor. Make it interpret some #pragma directives the way you want.
I found this scheme useful when the compiler got cranky and wouldn't unroll certain loops for me #define REPEAT20(x) { x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;x;} REPEAT20( val = pleaseconverge(val) ); But IMHO, if you need something much more complicated than that, then you should write your own pre-preprocessor. Your pre-preprocessor could for instance generate an appropriate header file for you, and it is easy enough to include this step in a Makefile to have everything compile smoothly by a single command. I've done it.