C preprocessor magic - c

I'm trying to use preprocessor tricks to declare a magic variable. Something like this:
DECLARE(x)
should expand to
int _DECLARED_VARIABLE_x_LINE_12
if the declaration was on line 12 of the input source. I was trying to use the ## token-pasting command and the __LINE__ macro, but I either get an uninterpreted "__LINE__" in there or the preprocessor seems to completely ignore my line. My current guess is:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__

The normal trick in such cases is to use a second macro. However, that does not seem to work with GCC (4.5.1 on MacOS X 10.6.4), and a third level of macro was needed:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
#define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE41(x, line) DECLARE42(x, line)
#define DECLARE40(x) DECLARE41(x, __LINE__)
int DECLARE(y);
int DECLARE40(c) = 129;
Output of 'gcc -E':
# 1 "magicvars.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "magicvars.c"
int _DECLARED_VARIABLE_y_LINE___LINE__;
int _DECLARED_VARIABLE_c_LINE_8 = 129;
I'm not sure I have a good explanation of why the third level of macro was needed.
I am also curious to know how you are ever going to refer to these variables after you've created them.
I went through a number of variations before managing to hit on the one that worked:
#define DECLARE(x) _DECLARED_VARIABLE_ ## x ## _LINE_ ## __LINE__
#define DECLARE11(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE10(x) DECLARE11(x, __LINE__)
#define DECLARE23(line) _LINE_ ## line
#define DECLARE22(x) _DECLARED_VARIABLE_ ## x
#define DECLARE21(x, line) DECLARE22(x) ## DECLARE23(line)
#define DECLARE20(x) DECLARE21(x, __LINE__)
#define DECLARE32(line) _LINE_ ## line
#define DECLARE31(x, line) _DECLARED_VARIABLE_ ## x ## DECLARE32(line)
#define DECLARE30(x) DECLARE31(x, __LINE__)
#define DECLARE42(x, line) _DECLARED_VARIABLE_ ## x ## _LINE_ ## line
#define DECLARE41(x, line) DECLARE42(x, line)
#define DECLARE40(x) DECLARE41(x, __LINE__)
int DECLARE(y);
int DECLARE10(z) = 12;
int DECLARE20(a) = 37;
int DECLARE30(b) = 91;
int DECLARE40(c) = 129;
Have fun working out why the non-working ones didn't work. They did, however, point me towards the working answer. (I note that the Sun C compiler produces essentially the same results as GCC on the same input.)

The preprocessor removes the ## operators from the macro replacement list before attempting to look for further macros for recursive replacement. This means that your reference to __LINE__ gets "glued" to the rest of the macro before it has a chance to get recognized as __LINE__ and replaced with the actual line number.
For this reason, if you want to embed the line number into your macro, you have no other choice but to pass it through a macro parameter
#define DECLARE_(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
#define DECLARE(x) DECLARE_(x, __LINE__)
And that will formally solve the immediate problem in your original macro definition.
However, this still will not work as expected due to another quirk in C/C++ preprocessor specification: parameter names adjacent to ## are replaced with the corresponding arguments values without the recursive macro expansion in the argument value. I.e. L will be replaced with __LINE__, without changing __LINE__ to the actual line number first.
To ensure the recursive macro expansion for parameter L, one needs to introduce another "level of indirection" in macro definition
#define DECLARE__(x, L) _DECLARED_VARIABLE_##x##_LINE_##L
#define DECLARE_(x, L) DECLARE__(x, L)
#define DECLARE(x) DECLARE_(x, __LINE__)
In this case, when processing DECLARE_(x, L) macro, the preprocessor will handle L recursively: first replace it with __LINE__ and then replace __LINE__ with the actual line number. DECLARE__ will receive the complete line number.

There was an issue with __LINE__ in debug mode with Visual Studio if you were using Edit and Continue. Here is a reference to it. That issue is a few years old though. If that issue is resolved, then Jonathan Leffler's solution will work fine.

There are two special expansion rules regarding ## operator:
Operands to ## operator are not expanded before pasting.
Macro arguments are not expanded if they are concatenated with ##.

Related

C - X Macro Self Iteration / Expansion

I am curious if any of you can think of a way upon macro expansion to repeat the macro itself. Here is an incredibly small scale version of an overall bigger problem:
#include<stdio.h>
#define LETTERS\
X(A)\
X(B)\
X(C)\
X(D)
#define X(L) #L
int main(int nargs,char** args)
{
printf("%s\n",LETTERS);
return 0;
}
Output: ABCD
Desired output: AABCD BABCD CABCD DABCD
The desired output is clearly similar to a nested (N^2) loop over whatever input data.
The stringification doesn't matter, it's only there for compilation.
There are some obvious and some not so obvious solutions to the desired output.
One is to make a complete copy of the macro, then between each X element, you simply refer to the copy. This would be wasteful and I don't want to do it. Obviously you can't refer to the macro itself due to recursion. I have made many attempts to find a decent solution, and won't list all of them as it would take up way too much time. I am open to solutions that use other macros to repeat or expand the original, or solutions that use janky forms of recursion.
#include<stdio.h>
#define LETTERS_COPY\
X(A)\
X(B)\
X(C)\
X(D)
#define LETTERS\
X(A)\
LETTERS_COPY\
X(B)\
LETTERS_COPY\
X(C)\
LETTERS_COPY\
X(D)\
LETTERS_COPY
#define X(L) #L
int main(int nargs,char** args)
{
printf("%s\n",LETTERS);
return 0;
}
Again, this builds just fine and works, but requires a complete duplicate of the original data, interjecting itself between each X element.
If you use an iterating macro, like how one is defined in the P99 macro utility collection, then it becomes much easier to solve.
Since we intend to define an iterating macro, we don't need X-macros on the letters anymore.
#define LETTERS \
A \
,B \
,C \
,D
Below is a simplified iterating macro that supports up to 5 arguments. Hopefully you see how to extend the implementation if you need more.
#define XX(X, ...) \
XX_X(__VA_ARGS__, XX_5, XX_4, XX_3, XX_2, XX_1) \
(X, __VA_ARGS__)
#define XX_X(_1,_2,_3,_4,_5,X,...) X
#define XX_1(X, _) X(_)
#define XX_2(X, _, ...) X(_) XX_1(X, __VA_ARGS__)
#define XX_3(X, _, ...) X(_) XX_2(X, __VA_ARGS__)
#define XX_4(X, _, ...) X(_) XX_3(X, __VA_ARGS__)
#define XX_5(X, _, ...) X(_) XX_4(X, __VA_ARGS__)
So, if you invoke XX(X, LETTERS), it will expand into the X-macro version of LETTERS you had before.
The magic of the XX() macro is the meta nature of the XX_X() macro, which selects the right numeric macro to use. The numeric macro is passed in reverse order to the XX_X() macro when it is invoked by XX(). This makes it so that XX_X() selects a lower numeric macro if __VA_ARGS__ contains fewer arguments.
Now, we create a macro to turn the argument into a string:
#define STR(X) STR_(X)
#define STR_(X) #X
This allows you to easily create the string with all your letters.
And printing your iterative output just needs another macro.
int main () {
const char *letters = XX(STR, LETTERS);
#define LETTERS_PRINT(X) printf("%s%s\n", #X, letters);
XX(LETTERS_PRINT, LETTERS)
}
We see that the solution applies XX() twice. Once to create the string of all your letters. Once to create the output, which is prepending each letter to the combined letters.
Try it online!
For anyone wondering, the best I could do was make a second X macro that takes 2 args, and the outer list becomes a function macro that takes a single arg. This lets you pass data to the list, and to the second x macro, while still being able to unpack either X macro however you like.
#include<stdio.h>
#define _CAT(A,B) A##B
#define CAT(A,B) _CAT(A,B)
#define _STR(S) #S
#define STR(S) _STR(S)
#define LETTERS(L)\
XX(L,X(A))\
XX(L,X(B))\
XX(L,X(C))\
XX(L,X(D))
int main(int nargs,char** args)
{
#define X(L) L
#define XX(L1,L2) STR(CAT(L1,L2))
printf("%s\n",LETTERS(A));
printf("%s\n",LETTERS(B));
printf("%s\n",LETTERS(C));
printf("%s\n",LETTERS(D));
#undef XX
#undef X
return 0;
}

C Preprocessor: concatenate macro call with token

I'm trying to concatenate a macro call with a token to create a new one, for instance:
#define TEST(X) X ## _TEST
#define CONCAT(X) TEST(X) ## _CONCAT
CONCAT(OK);
Then I check the output with gcc -E; I would want to get OK_TEST_CONCAT; but instead I get an error:
error: pasting ")" and "_CONCAT" does not give a valid preprocessing token
If I remove ## I get no error but the output is OK_TEST _CONCAT;
This is a minimal example, so the easiest here would be to combine everything in a single macro, but know that it's impossible for me to get rid of the first call to TEST. Is there a way to remove that space?
Thanks
EDIT:
Ok so from the confusion maybe my example was a little too minimal, that's my fault. Here is a more plausible use case:
I want all the prototypes in a certain header to be prefixed by the PREFIX defined in that header.
proto.h:
#define EXPAND(X) EXPAND_HELPER(X)
#define EXPAND_HELPER(X) X
#define PROTO(NAME) PREFIX ## NAME
other.h:
#include <proto.h>
#define PREFIX other
int PROTO(test)(int a, int b);
...
What I want is all the prototypes in other.h to have this form: int other_test(int a, int b);. But as it is they have this form: int PREFIX_test(int a, int b);. After googling I found that I needed to force PREFIX to rescan, so I tried this:
#define PROTO(NAME) EXPAND(PREFIX) ## NAME
which prompted my question. Now if I look at #Lundin's answer, I can adapt it to give what I want:
Solution:
#define PROTO(NAME) PROTO_HELPER(PREFIX, NAME)
#define PROTO_HELPER(PREFIX, NAME) PROTO_EXPAND(PREFIX, NAME)
#define PROTO_EXPAND(PREFIX, NAME) PREFIX ## NAME
Thanks!
All preprocessor tokens must be expanded before a function-like macro using ## or # is called. Because ## or # is applied before macro expansion. In your case TEST(X) only expands X into TEST(OK) and then the preprocessor attempts to paste TEST(OK) with _CONCAT which won't work. For each attempt to concatenate tokens, you must first expand all macros before ##, which is done by extra helper macros that force a rescanning/replacement.
The contrived solution given #define TEST(X) X ## _TEST would be this:
#define CONCAT(X) EXPAND_HELPER(TEST(X)) // expands TEST(X) to TEST(OK)
-->
#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT) // expands TEST(OK) to OK_TEST
-->
#define CONCAT_HELPER(X,Y) X ## Y
That is:
// NOTE: contrived solution, avoid
#define TEST(X) X ## _TEST
#define CONCAT_HELPER(X,Y) X ## Y
#define EXPAND_HELPER(X) CONCAT_HELPER(X, _CONCAT)
#define CONCAT(X) EXPAND_HELPER(TEST(X))
...
int CONCAT(OK) = 1; // becomes int OK_TEST_CONCAT = 1;
A much simpler solution would be:
#define CONCAT(X) X ## _TEST ## _CONCAT

Why can't I paste an object-like macro to a function? [duplicate]

This question already has answers here:
How can I concatenate twice with the C preprocessor and expand a macro as in "arg ## _ ## MACRO"?
(3 answers)
Closed 5 years ago.
I've defined an object-like macro and a function-like macro (from this question).
#define SYSTEM windows
#define CALL(function, ...) (function)(__VA_ARGS__)
Given this definition, CALL(foo, arg1, arg2) turns into foo(arg1, arg2).
I want CALL(foo, args) to turn into x__foo(args), x being whatever SYSTEM is defined to.
I have tried:
#define CALL(function, ...) SYSTEM##__function(__VA_ARGS__)
#define CALL(function, ...) (SYSTEM)##__##(function)(__VA_ARGS__)
#define CALL(function, ...) ((SYSTEM)##__##(function)(__VA_ARGS__)
They all result in compiler errors.
How can I define CALL so that it concatenates the value of SYSTEM, __, and the value of function?
You're going to need a few more levels of indirection to concatenate (paste) those values. The C preprocessor attempts to paste exactly what it sees. If what it's seeing is a macro or a value passed to a function, it doesn't realize that.
MACRO##SOMETHINGELSE will produce MACROSOMETHINGELSE.
(MACRO)##SOMETHINGELSE will result in an error upon compilation, because the preprocessor is attempting to paste the parenthesis.
SOMETHINGELSE##VALUEPASSEDTOMACRO will result in SOMETHINGVALUEPASSEDTOMACRO.
None of these are what you want, obviously. To add the indirection necessary to concatenate object-like-macro values and values passed to a function-like-macro, use two more definitions.
#define _cat(x, y) x ## y
#define cat(x, y) _cat(x, y)
Then you can define CALL to fit your needs.
#define SYSTEM windows
#define CALL(function, ...) cat(cat(SYSTEM, __), function) (__VA_ARGS__)
Writing CALL(foobar, x, y) calls windows__foobar(x, y) as desired.
#define SYSTEM windows
#define PASTE_CALL(prefix, function, ...) prefix ## __ ## function(__VA_ARGS__)
#define EVAL_CALL(prefix, function, ...) PASTE_CALL(prefix, function, __VA_ARGS__)
#define CALL(function, ...) EVAL_CALL(SYSTEM, function, __VA_ARGS__)
CALL(foo, arg1, arg2)
As desired, this generates:
# 1 "paste.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "paste.c"
windows__foo(arg1, arg2)

Macro concatenation inside other macro concatenation in c

I have the following macros:
#define __IR( x ) ICU.IR[ IR ## x ].BIT.IR
#define _IR( x ) __IR( x )
#define IR( x , y ) _IR( _ ## x ## _ ## y )
I use it in this way:
IR(SCI7, RXI7) = 0;
That expands to:
ICU.IR[ IR_SCI7_RXI7 ].BIT.IR = 0
Instead of use SCI7 and RXI7 I'd like to use sci(channel) and rxi(channel). So I've tried to create the following macros:
#define _sci(x) SCI ## x
#define sci(x) _sci(x)
#define _rxi(x) RXI ## x
#define rxi(x) _rxi(x)
#define channel 7
And then:
IR(sci(channel), rxi(channel)) = 0;
But it didn't work. The compiler returns me:
Error[Pe017]: expected a "]"
I've been trying to with other manners also but without success.
What I'm doing wrong?
The whole macro is expanded with the literal sub-epressions and the macros in the result expression are expanded after that.
So you could write:
#define __IR(x ) ICU.IR[ IR ## x ].BIT.IR
#define _IR(x, y) __IR(_ ## x ## _ ## y)
#define IR(x, y) _IR(x, y)
#define _sci(x) SCI ## x
#define sci(x) _sci(x)
#define _rxi(x) RXI ## x
#define rxi(x) _rxi(x)
#define channel 7
IR(sci(channel), rxi(channel)) = 0;
(The only thing I've really changed is the definition of _IR. On anther note, macro identifiers and symbold beginning with underscores are reserved for the compiler, so you might want to rename your secondary macros.)
You're making the mistake of believing a macro function is like a function call whereas it actually involves text substitution on source code.
In rough terms, the preprocessor will expand IR(sci(channel), rxi(channel)) = 0 to _IR( _sci(channel)_rxi(channel)) = 0 and expands that to ICU.IR[IR_sci(channel)_rxi(channel)].BIT.IR = 0. The result of all that is then compiled as C.
That bit between the square brackets is not a valid C expression at all. The compiler gets confused on that, hence the cryptic error message.
That's the explanation for the problem. The solution? You haven't given enough information to help anyone suggest one.

C Macro building with defines

I am having trouble getting this macro expanison right
#define foo Hello
#ifdef foo
#define wrapper(x) foo ## x
#else
#define wrapper(x) boo ## x
#endif
calling:
wrapper(_world)
I would like the result of
Hello_world
however, the macro is treating the "foo" define as a literal, and thus giving
foo_world
Can someone point out my mistake?
Thanks
I would recommend gnu-cpp-manual which clearly explains how macros are expanded.
Macro arguments are completely macro-expanded before they are substituted into a macro body, unless they(macro arguments) are stringified or pasted with other tokens (by the macro function that is directly applied to).
For example:
If an argument is stringified or concatenated, the prescan does not occur.
#define AFTERX(x) X_ ## x
#define XAFTERX(x) AFTERX(x)
#define TABLESIZE 1024
#define BUFSIZE TABLESIZE
AFTERX(BUFSIZE) => X_BUFSIZE: since AFTERX is to concatenate argument with prefix, its argument is not expanded, remaining BUFSIZE.
XAFTERX(BUFSIZE) => X_1024: XAFTERX does not do concatenation directly, so BUFSIZE will be expanded first.
Generally, arguments are scanned twice to expand macro called in them.
--- edit ---
So the better practice is: (code from QEMU source)
#ifndef glue
#define xglue(x, y) x ## y
#define glue(x, y) xglue(x, y)
#define stringify(s) tostring(s)
#define tostring(s) #s
#endif
glue(x,y) will concatenate x and y with both already expanded.

Resources