Reputation: 60
I want to create parameterized preprocessor macro for IBM Metal C Prolog.
The initial unparametrized form is
#pragma prolog(Foo, " #MCPROLG MAIN=(YES,16,132)")
The real prolog is more complex, but for the sake of the question the important part is that there are values within a string.
#pragma
directive itself can't be part of a macro, so I replace that with _Pragma
like that:
_Pragma("prolog(Foo, \" #MCPROLG MAIN=(YES,16,132)\")")
I can parameterize Foo like this:
#define STR(...) #__VA_ARGS__
#define PROLOG(function) _Pragma(STR(prolog( function , " #MCPROLG MAIN=(YES,16,132)")))
How can I create macro that parameterizes the value 16?
It appears that I need to concatenate strings within preprocessor, I've tried following approaches. All use this stringization macro:
#define STR(...) #__VA_ARGS__
Token that is replaced with 16 (let's name it size
) can't be within a string itself so that it is replaced.
#define PROLOG(function, size) _Pragma(STR(prolog( function , " #MCPROLG MAIN=(YES, size ,132)")))
_Pragma only accepts a single string, so I can't peruse C string concatenation like this:
#define PROLOG(function, size) _Pragma(STR(prolog( function , " #MCPROLG MAIN=(YES," #size ",132)")))
I can't stringize the whole second argument of prolog like this:
#define PROLOG(function, size) _Pragma(STR(prolog( function , STR( #MCPROLG MAIN=(YES, size ,132)))))
because #MCPROLG
needs to stay within a string so that its # is not treated as stringization token.
Upvotes: 0
Views: 200
Reputation: 2674
To address issue 1 (need to expand a parameter in the replacement list), you need an indirect stringify macro:
#define STR(X) STR_I(X)
#define STR_I(X) #X
You may make this variadic if you want but it's not necessary here (the commas in your string are surrounded by parentheses; the preprocessor will match those; e.g., FOO(A=(B,C,D))
, given FOO
is a function-like macro, has one argument).
To address issue 2, yes, you need to stringify the whole thing. Effectively there's no such thing as string literal concatenation to the preprocessor (because it runs in translation phase 4, and string literal concatenation doesn't happen until translation phase 6).
To address issue 3, just produce a hash from another macro (root it at an object-like macro, where #
has no special meaning):
#define HASH #
#define HASHM() HASH
The function-like variant allows you to produce the same hash right next to something else (HASHMCPROLG
does nothing useful; HASH MCPROLG
produces # MCPROLG
, HASHM()MCPROLG
produces #MCPROLG
).
Those pieces in hand, the rest is easy:
#define PROLOG(FN_,SZ_) _Pragma(STR(prolog(FN_, STR( HASHM()MCPROLG MAIN=(YES,SZ_,132)))))
Here I'm assuming you also need an end parentheses around the pragma prolog and that in the question this was a typo; that is, it should be:
_Pragma("prolog(foo, \"#MCPROLG MAIN=(YES,16,132)\")")
...not:
_Pragma("prolog(foo, \"#MCPROLG MAIN=(YES,16,132)\"")
Upvotes: 1