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.