FW: a nifty feature for c preprocessor

R A ren_zokuken01@hotmail.com
Wed Dec 28 06:48:00 GMT 2011


i'm an amateur programmer that just started learning C. i like most of the features, specially the c preprocessor that it comes packed with. it's an extremely portable way of implementing metaprogramming in C.

though i've always thought it lacked a single feature -- an "evaluation" feature.

say i have these definitions:
#define MACRO_1           (x/y)*y
#define MACRO_2           sqrt(a)
#define MACRO_3           calc13()
....
#define MACRO_15         (a + b)/c


now, all throughout the codebase, whenever and whichever of MACRO_1, or MACRO_2 (or so forth) needs to be called, they are conveniently "indexed" by another macro expansion:

#define CONCAT(a, b)                  a##b
#define CONCAT_VAR(a, b)           CONCAT(a, b)

#define MASTER_MACRO(N)         CONCAT_VAR(MACRO_, N)

now, if we use MASTER_MACRO with a "direct" value:

MASTER_MACRO(10)
or
#define N              10
MASTER_MACRO(10)
both will work.


but substitute this with:

#define N                                    ((5*a)/c + (10*b)/c + ((5*a) % c + (10*b) % c)/c)

and MASTER_MACRO expands to:
MACRO_((5*a)/c + (10*b)/c + ((5*a) % c + (10*b) % c)/c)

which, of course is wrong.
there are other workarounds or many times this scheme can be avoided altogether.
but it can be made to work (elegantly) by adding an "eval" preprocessor operation:

so we redefine MASTER_MACRO this way:
#define MASTER_MACRO(N)         CONCAT_VAR(MACRO_, eval(N))
which evaluates correctly.

this nifty trick (though a bit extended than what i elaborated above) can also be used to *finally* have increments and decrements (among others).
since "eval" forces the evaluation of an *arithmetic* expression (for now), it will force the evaluation of an expression, then define it to itself.
this will of course trigger a redefinition flag from our beloved preprocessor, but the defined effect would be:

#define X             (((14*x)/y)/z)    /* say this evaluates to simply 3 */

incrementing X, will simply be:
#define X             eval(eval(X) + 1)    /* 1) will be evaluated as 4 before any token substitution */
#define X             eval(eval(X) + 1)    /* 2) will be evaluated as 5 before any token substitution */

that easy.

to suppress the redef warnings, we can have another directive like force_redef (which can only work in conjunction with eval)
#force_redef  X             eval(eval(X) + 1)


i'm just confused :-S...
why hasn't this been suggested? i would love to have this incorporated (even just on test builds) to gcc.
it would make my code so, so much more manageable and virtually extensible to more platforms.

i would love to have a go at it and probably modify the gcc preprocessor, but i since i know nothing of it's implementation details, i don't know where to begin. i was hoping that this being a gnu implementation, it's been heavily modularized (the fact that gcc was heavily revised back then to use abstract syntax trees, gimple, etc, past version 2.95 -- ???). so i can easily "interrupt" the parsing operation (i wouldn't dare implement a pre-preprocessing operation, being big and redundant), then substitute the eval, then make the whole prasing go again.

any advice for a novice? thnx.
 		 	   		   		 	   		   		 	   		   		 	   		  



More information about the Gcc mailing list