views:

46

answers:

1

I have a general macro:

#define mSwitch( Root, Case )  Root##_Case_##Case

#define mSpecialDisplay( what, Val )  mSwitch(mSpecialDisplay,what)(Val)
#define mSpecialDisplay_Case_Int(Val)    ...do stuff
#define mSpecialDisplay_Case_Float(Val)  ...do stuff
...more special cases

how do I guarantee that the variable Case is fully expanded before it gets pasted in mSwitch?

It works fine if mSwitch is passed a literal value, but if there are several layers of indirection, or intermediary operations, mSwitch ends up pasting one of those before they get fully expanded.

I'm using MSVC 2005.

Is there a simple way to make sure a parameter is fully expanded before pasting is done?

Thanks


well, it isn't that hard to give an example maybe:

  #define mMDebugInfo( ... ) mMDebugExp( mMDebugInfo_( 0, __VA_ARGS__ ) )

  #define mMDebugInfo_( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (C, __VA_ARGS__) )

  #define mMDebugInfoRep( C, ... ) mMXP##C( mMDebugInfo_ )mMXP##C((mMIInc(C),__VA_ARGS__)) //(mMExpDo(mMGlue( mM, C)##DebugInfo_(mMIInc(C),__VA_ARGS__))

  #define mMDebugInfo1( C, ... ) mMAritize( mMSwitch( mMDebugInfo, mMMetaTrait( Detect, __VA_ARGS__ ) ), (mMIInc(C), __VA_ARGS__) )

  #define mMDebugInfo_Case_Nil(...) [Nil]

  #define mMDebugInfo_Case_CntArgs(C,I,...) 
mMDebugInfoRep(C,I),mMDebugInfoRep(C,__VA_ARGS__)
  #define mMDebugInfo_Case_PrnNull(C,I) [()]

  #define mMDebugInfo_Case_Prn(C,I)   ( mMDebugInfoRep(C,mMDPrn(I)) )

  #define mMDebugInfo_Case_ActFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, I, mMTrait_Fn_mM##I) )

  #define mMDebugInfo_Case_PassFn(C,I) mMAritize( mMDebugInfo_Case_Fn, (C, mMTrait_Fn_mM##I) )

  #define mMDebugInfo_Case_Fn( C,Name, Reg, ArgCnt, PArgs ) [Name:ArgCnt]( mMAritize( mMSwitch( mMDebugInfo_Case_Fn, ArgCnt ), (C, mMDPrn( PArgs ) )) )

  #define mMDebugInfo_Case_Fn_Case_V(C, _1, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, __VA_ARGS__)

  #define mMDebugInfo_Case_Fn_Case_0(...) [Nil]

  #define mMDebugInfo_Case_Fn_Case_1(C, _1, ...) mMDebugInfoRep(C, _1)

  #define mMDebugInfo_Case_Fn_Case_2(C, _1, _2, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2)

  #define mMDebugInfo_Case_Fn_Case_3(C, _1, _2, _3, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3)  

  #define mMDebugInfo_Case_Fn_Case_4(C, _1, _2, _3, _4, ...) mMDebugInfoRep(C, _1), mMDebugInfoRep(C, _2), mMDebugInfoRep(C, _3), mMDebugInfoRep(C, _4)

  #define mMDebugInfo_Case_Int(C,I)   [Num:I]

  #define mMDebugInfo_Case_Digit(C,I) [Dig:I] 

  #define mMDebugInfo_Case_Bool(C,I)  [Bin:I]

  #define mMDebugInfo_Case_CCode(C,I) [CCd:I]

  #define mMDebugInfo_Case_UToken(C,I) [UT:I]

this is debug code that has no problems recursively parsing nested expressions like:

DebugInfo( BInt( BNot( IAdd(4,BNot(IAdd(6,7)) ) ) ) ); "

which yields: "[BInt:1]( [BNot:1]( [IAdd:2]( [Dig:4], [BNot:1]( [IAdd:2]( [Dig:6], [Dig:7] ) ) ) ) )"

The macro functions in the example expression are in inactive form. The problem is happening when I activate the form - the parse chain for the individual arguments can get arbitrarily long and they aren't getting resolved completely before they are getting used

+3  A: 

This is the usual idiom for this:

#define mSwitch(Root, Case) mSwitch_(Root, Case)
#define mSwitch_(Root, Case) Root##_Case_##Case

All of the arguments to a C preprocessor macro are fully expanded before the macro itself is expanded, unless the # or ## operator is applied to them; then they're not expanded. So to get full expansion before ##, you pass the arguments through a wrapper macro that doesn't use ##.

Zack
Unrelatedly, out of morbid curiosity, where do people learn to write "`function( argument, argument )`" -- i.e. with spaces inside the parentheses? I see it fairly often and it makes my sense of aesthetics writhe in pain.
Zack
thanks, I tried that.I think the problem is getting exteneded because the intermediary operations may be applying pastes of their own.If I create an arbitrarily long enough list of:#define mSwitch( A, B ) mSwitch1(A,B)#define mSwitch1( A, B ) mSwitch2(A,B)...#define mSwitchN( A, B ) Root##_Case_##Caseit eventually works.Is there anything else to try?
VonRiphenburger
@Zack, it's required style in some places (like the one I work in). You'll get used to it.
JSBangs
There's no other way to control whether or not this happens, but one level of wrapper *should* be enough regardless of what else is going on. I would need to see a complete self-contained example where things go wrong, to give more specific advice.(It's quite possible that you've hit an MSVC bug, by the way. Have you tried the 2008 edition? Or gcc?)
Zack
@JS Bangs, I know a lot of places have that in their required style guide (thankfully *not* where I work) but where does it *come* from? Who invented it?
Zack
yeah, zack, I think it is a bug. I can't really give a concise example because the problem is actually occurring in preprocessor library I am writing that allows fully recursive macro definitions. The pasting problem is happening when I am parsing the arguments of a macro Fn and the additional stuff that needs to get resolved is the macros that perform the actual parsing on the argument before I activate it.
VonRiphenburger
I'm betting bug, yes, but your longer example doesn't help me. I can't figure out what's going on from a bunch of `#define`s and then some apparently-unrelated function calls. I need a complete, self-contained thing I can paste into a .c file and feed to various compilers and see what happens. Ideally also you would provide the result of preprocessing with MSVC 2005, which I cannot conveniently test.
Zack
hmmm, well, if the standard says passing arguments through one level of indirection (that has no pasting in it itself) should result in complete expansion, then it is a bug. It definitely does not resolve completely. I'll have to look for a work-around. It appears to require one level of indirection for EACH expansion that involves a paste operation.
VonRiphenburger
"It appears to require one level of indirection for EACH expansion that involves a paste operation" -- yeah, that's a bug. The way the standard puts it is a bit more complicated than "should result in complete expansion", but yes, it's supposed to repeatedly expand the contents of macro arguments till it can't expand them any more and only then substitute that text into the expansion of the macro proper.
Zack
Thanks, zack, thats what I thought too, and it would sure make my life easier if it worked that way.
VonRiphenburger