The macro of interest (IOPORT_CREATE_PIN) is part of a library and works as desired in general. It converts a specific pin on a specific port to a library internal unique numeric representation.
It is defined as:
#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin))
Normal usage would be
IOPORT_CREATE_PIN(PORTD, 4)
for example, which would just concatenate IOPORT_ and PORTD to IOPORT_PORTD. IOPORT_PORTD in this example is an internal definition of the library that further expands to numeric value.
However, since PORTD (defined as #define PORTD (*(PORT_t *) 0x0660), which is not really relevant here) is already part of another definition
#define FLASHPORT PORTD
So using
IOPORT_CREATE_PIN(FLASHPORT, 4)
wrongly concatenates to IOPORT_FLASHPORT instead of the desired IOPORT_PORTD inside the IOPORT_CREATE_PIN definition.
I had a look at this interesting answer and tried to apply one level of indirection hoping the macro would be properly expanded, but I wasn't able to get it right.
Is there a way to "wrap" that macro somehow to make the compiler evaluate FLASHPORT to PORTD before the concatenation?
EDIT:
As John pointed out the problem with wrapping is, that FLASHPORT would be expanded recursively, not just from FLASHPORT to PORTD, but to (*(PORT_t *) 0x0660).
Is there any workaround?
Normally, the arguments to a function-like macro are themselves macro-expanded before being substituted into the macro's replacement text. Argument expansion is suppressed, however, for macro arguments that are operands of the concatenation (##) or stringification (#) operator -- that's the reason for performing a double-expansion if you want to concatenate or stringify a macro's replacement value instead of its name.
I can not change the IOPORT_CREATE_PIN macro. Is there a way to "wrap" that macro somehow to make the compiler evauate FLASHPORT to PORTD before the concatenation?
My understanding is that you want to define a new macro, e.g. WRAPPER() that you can invoke instead of IOPORT_CREATE_PIN(), whose expansion is the same as IOPORT_CREATE_PIN() for arguments PORTD, 4, and whose expansion does not change same when FLASHPORT is used instead of PORTD as the first argument.
Whether that is doable depends in part on the macro arguments. Generally, a straight-up wrapper does what I understand you to be asking for:
// For illustrative purposes:
#define IOPORT_PORTD correct!
#define IOPORT_FLASHPORT wrong!
// As specified in the question:
#define FLASHPORT PORTD
#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin))
// Wrapper:
#define WRAPPER(port,pin) IOPORT_CREATE_PIN(port, pin)
// Demo:
Direct call: IOPORT_CREATE_PIN(FLASHPORT, 4)
Wrapped call: WRAPPER(FLASHPORT, 4)
Wrapped call: WRAPPER(PORTD, 4)
The preprocessor exands that to:
Direct call: ((wrong!) * 8 + (4))
Wrapped call: ((correct!) * 8 + (4))
Wrapped call: ((correct!) * 8 + (4))
The catch here is that if PORTD is defined as a macro in its own right, then you are hosed. You then cannot just expand FLASHPORT to PORTD; if FLASHPORT is expanded then the result of that expansion will be expanded again, recursively, before it is substituted.
Alternative Approach
As far as I know or can determine, it is not possible to create a general-purpose alias for a preprocessor macro. Where no token-pasting or stringification is involved, you can do as you have done, and simply define one macro to expand to the name of another, but that doesn't play well with pasting or stringification.
If a for-purpose solution is acceptable, however, then there are alternatives. For example, if you can identify all the token-pasting operations that can involve your alias, then you can provide aliases for the pasted-together macros, too. In your case, that might look like this:
// For illustrative purposes:
#define IOPORT_PORTD correct!
#define PORTD OOPS
// As specified in the question:
#define FLASHPORT PORTD
#define IOPORT_CREATE_PIN(port, pin) ((IOPORT_ ## port) * 8 + (pin))
// Patch up the token-pasting:
#define IOPORT_FLASHPORT IOPORT_PORTD
// Demo:
Direct call: IOPORT_CREATE_PIN(FLASHPORT, 4)
The preprocessor expands that to
Direct call: ((correct!) * 8 + (4))
That doesn't scale well, of course, and it requires some knowledge or study of the overall macro set involved, but it would solve the limited-scope problem presented in the question.
Try this:
#define MY_IOPORT_CREATE_PIN(port, pin) IOPORT_CREATE_PIN(port ,pin)
and then use MY_IOPORT_CREATE_PIN instead of IOPORT_CREATE_PIN
Related
This question already has answers here:
How to force macro to not expand
(1 answer)
Pre-processor: Expand a macro only once
(3 answers)
C: is it possible to expand marcos before pasting, but not recursively?
(1 answer)
Closed 9 months ago.
Given macro definitions like this:
#define GPIOA ((1234)+42)
#define GPIOB ((1234)+84)
#define LEDA_GPIO_Port GPIOA
#define LEDB_GPIO_Port GPIOB
#define MY_PORT_GPIOA 0
#define MY_PORT_GPIOB 1
I would like to define a macro MY_PORT which, given LEDA as argument somehow substitutes this to LEDA_GPIO_Port, then to GPIOA, turns that into MY_PORT_GPIOA and this into 0. So MY_PORT(LEDA) should evaluate to 0 and MY_PORT(LEDB) to 1. If the macros GPIOA/GPIOB wouldn't exist, this would be easy, but since they are defined as complex expressions (starting with parentheses) only one substitution must be performed, and the occurence of GPIOA must not be substituted by that expression.
I tried
#define MY_PORT2(port) MY_PORT_##port
#define MY_PORT(name) MY_PORT2(name##_GPIO_Port)
but here MY_PORT(LEDA) returns MY_PORT_LEDA_GPIO_Port, i.e. it lacks one substituion.
#define CONCAT(a,b) a##b
#define MY_PORT2(port) CONCAT(MY_PORT,port)
#define MY_PORT(name) MY_PORT2(name##_GPIO_Port)
does not compile, as it tries to concatenate the definition for GPIOA, i.e. one subtitution too many.
Is it even possible to do exactly one subtitution?
In C I have a define like:
#define VALUE 5
But the user can set a function too:
#define VALUE get_value()
For historical reasons
#define VALUE 0
means "the value is not set, use the default"
The question is how to write an #if that decides if VALUE is 0.
#if VALUE == 0
...
#else
...
#endif
gives "missing binary operator before token "("" error with GCC.
EDIT:
To make the use case clearer:
#if VALUE == 0
set_default_value();
#else
set_value(VALUE)
#endif
So I don't need VALUE to be evaluated in the #if just see if it's literally '0' or not.
You can use preprocessing pattern matching.
#define SECOND(...) SECOND_I(__VA_ARGS__,,)
#define SECOND_I(A,B,...) B
#define GLUE(A,B) GLUE_I(A, B)
#define GLUE_I(A,B) A##B
#define ZERO_TEST(X_) SECOND(GLUE(ZERO_TEST_AGAINST_,X_),0)
#define ZERO_TEST_AGAINST_0 ,1
The key construct here is the SECOND macro, which indirectly expands to its second argument. For pattern matching, you would use this by carefully constructing a first argument; since SECOND normally expands to its second argument, whatever you construct is normally ignored. But since SECOND expands to its second argument indirectly, you can cherry pick a particular pattern by having the first argument expand in particular cases with a comma, which would shove in a new second argument.
In this case we have an indirect paste at the end of ZERO_TEST_AGAINST_, and we're looking for the result of that to be ZERO_TEST_AGAINST_0.
To use this:
#if ZERO_TEST(VALUE)
set_default_value();
#else
set_value(VALUE)
#endif
Demo
http://coliru.stacked-crooked.com/a/2a6afc189637cfd3
Caveat
This fits your spec precisely as given; the indirect paste would not work with this form if you have parenthetical definitions:
#define VALUE (5)
...or:
#define VALUE (get_value() << 2) | 1
...since ZERO_TEST_AGAINST_ and ( do not join to make a valid token.
A generic solution is likely impossible, but you can hack something together:
#define CAT(x, ...) CAT_(x, __VA_ARGS__)
#define CAT_(x, ...) x##__VA_ARGS__
#define CHECK_VALUE_CHECK_0 )(
#define CHECK_VALUE_FALSE(...) CHECK_VALUE_TRUE
#define CHECK_VALUE_TRUE() 1
#define CHECK_VALUE CHECK_VALUE_(CAT(CHECK_VALUE_CHECK_, VALUE))
#define CHECK_VALUE_(...) CHECK_VALUE_FALSE(__VA_ARGS__)
#if CHECK_VALUE
#error Value is 0.
#else
#error Value is not 0.
#endif
Now, if VALUE is defined to 0, the macro CHECK_VALUE will expand to 1. Otherwise it will expand to CHECK_VALUE_TRUE, which as an unknown identifier, is considered falsey by #if.
This solution is hacky:
If VALUE starts with 0,, its causes a hard error.
If VALUE starts with something other than a letter or digit or _ (e.g. (), it causes a hard error.
...
A preprocessor cannot evaluate C-Functions, such as get_value(). It can only handle static data, as its replaced with code prior to compilation, so your statements are not executed at runtime.
if (VALUE == 0) in your C-Code would get replaced for example with if (get_value() == 0) prior to compilation. The Preprocessor is not able to evaluate the return value of get_value() (even if it would always return 0).
A #define VALUE 5 line makes the C preprocessor replace the string VALUE with the string 5 wherever it sees it (outside "strings", that is). The resulting program will not even contain VALUE anymore, and that is what the compiler proper sees(1).
Do an experiment: Get your program (cut it down to a few lines), and run:
cc -E proggie.c > proggie.i
Under Unixy systems you'll get a file proggie.i that contains preprocessed C, which is what the compiler proper sees. No VALUE in sight, and trying to set VALUE in the source ends up as trying to set 0, which obviously won't work.
(1) Historically, C compilers ran a chain of programs over the source (then memories where measured in KiB, not GiB), the first --preprocessor-- was usually called cpp; today's compilers usually don't have a separate preprocessor anymore. But conceptually the first step is still preprocessing the code (handle #include, #if and #defined macros).
I think you're misunderstand how the historical 'the value is not set' works.
In the C preprocessor, whenever you have an #if directive any identifier in the expression that is not an macro (and is not the special function defined) will be replaced by the constant 0 prior to evaluating the #if. So with your example
#define VALUE get_value()
#if VALUE == 0
what happens is the VALUE macro is expanded, then, since there is no get_value macro defined, it is replaced by 0, leaving you with
#if 0() == 0
which gives you the syntax error you see.
I'm trying this for over a week with no success.
I'm creating a logger interface between two processors and I need help with defining automated MACROS.
What do I mean?
Let's say I have a logger message defined as LOGGER_MSG_ID_2 that takes two parameter of uint8 and uint16 types.
I have an enum defined as:
typedef enum{
PARAM_NONE,
PARAM_SIZE_UINT8,
PARAM_SIZE_UINT16,
PARAM_SIZE_UINT32
}paramSize_e;
So LOGGER_MSG_ID_2 will have a bitmap defined as:
#define LOGGER_MSG_ID_2_BITMAP (PARAM_SIZE_UINT16 << 2 | PARAM_SIZE_UINT8)
This bitmap is 1 Byte size, so the maximum number of parameters is 4.
Later on I have a list that defines all parameters type according to message ID:
#define ID_2_P0_TYPE uint8 // first parameter
#define ID_2_P1_TYPE uint16 // 2nd parameter
#define ID_2_P2_TYPE 0 // 3rd parameter
#define ID_2_P3_TYPE 0 // 4th parameter
As I said, I have a limitation of 4 parameters, so I would like to define them and let the MACRO decide weather to use them or not. I defined them as 0 but it can be whatever that works.
I have other MACROS that uses the bitmap to get all kind of attributes, such as number of parameters and message size.
Now it's the tricky part. I want to build a MACRO that creates a bitmap from types. The reason is that I don't want redundancy between the bitmap and parameters definitions.
My problem is that everything I tried failed to compile.
Eventually I would like to have a MACRO such as:
#define GET_ENUM_FROM_TYPE(_type)
that gives me PARAM_SIZE_UINT8, PARAM_SIZE_UINT16 or PARAM_SIZE_UINT32 according to type.
Limitations: I'm using arm compiler on windows (armcl.exe) and C99. I can't use C11 Generic().
I tried the following:
#define GET_ENUM_FROM_TYPE(_type) \
(_type == uint8) ? PARAM_SIZE_UINT8 : \
((_type == uint16) ? PARAM_SIZE_UINT16 : \
((_type == uint32) ? PARAM_SIZE_UINT32 : PARAM_NONE))
Eventually I want to use it like:
#define LOGGER_MSG_ID_2_BITMAP \
(GET_ENUM_FROM_TYPE(ID_2_P3_TYPE) << 6 | \
GET_ENUM_FROM_TYPE(ID_2_P2_TYPE) << 4 | \
GET_ENUM_FROM_TYPE(ID_2_P1_TYPE) << 2 | \
GET_ENUM_FROM_TYPE(ID_2_P0_TYPE))
But when I use it, it doesn't compile.
I have a table of bitmaps:
uint8 paramsSizeBitmap [] = {
LOGGER_MSG_ID_1_BITMAP, /* LOGGER_MSG_ID_1 */
LOGGER_MSG_ID_2_BITMAP, /* LOGGER_MSG_ID_2 */
LOGGER_MSG_ID_3_BITMAP, /* LOGGER_MSG_ID_3 */
LOGGER_MSG_ID_4_BITMAP, /* LOGGER_MSG_ID_4 */
LOGGER_MSG_ID_5_BITMAP, /* LOGGER_MSG_ID_5 */
LOGGER_MSG_ID_6_BITMAP, /* LOGGER_MSG_ID_6 */
LOGGER_MSG_ID_7_BITMAP, /* LOGGER_MSG_ID_7 */
LOGGER_MSG_ID_8_BITMAP, /* LOGGER_MSG_ID_8 */
LOGGER_MSG_ID_9_BITMAP, /* LOGGER_MSG_ID_9 */
LOGGER_MSG_ID_10_BITMAP, /* LOGGER_MSG_ID_10 */
};
And I get this error:
line 39: error #18: expected a ")"
line 39: error #29: expected an expression
(line 39 is LOGGER_MSG_ID_2_BITMAP)
Where do I go wrong?
----- Edit -----
For now I have a workaround that I don't really like.
I don't use uint64 so I made a use of sizeof() MACRO and now my MACRO looks like this:
#define GET_ENUM_FROM_TYPE(_type) \
(sizeof(_type) == sizeof(uint8)) ? PARAM_SIZE_UINT8 : \
((sizeof(_type) == sizeof(uint16)) ? PARAM_SIZE_UINT16 : \
((sizeof(_type) == sizeof(uint32)) ? PARAM_SIZE_UINT32 : PARAM_NONE))
and my paraemters list is:
#define NO_PARAM uint64
#define ID_2_P0_TYPE uint8
#define ID_2_P1_TYPE uint16
#define ID_2_P2_TYPE NO_PARAM
#define ID_2_P3_TYPE NO_PARAM
It works fine but... you know...
I believe the solution is to use concatenation operator ##, and helper defines.
// These must match your enum
#define HELPER_0 PARAM_NONE
#define HELPER_uint8 PARAM_SIZE_UINT8
#define HELPER_uint16 PARAM_SIZE_UINT16
#define HELPER_uint32 PARAM_SIZE_UINT32
// Secondary macro to avoid expansion to HELPER__type
#define CONCAT(a, b) a ## b
// Outer parenthesis not strictly necessary here
#define GET_ENUM_FROM_TYPE(_type) (CONCAT(HELPER_, _type))
With that GET_ENUM_FROM_TYPE(ID_2_P1_TYPE) will expand to (PARAM_SIZE_UINT16) after preprocessing.
Note that suffix in HELPER_*** defines has to match exactly the content of ID_*_P*_TYPE macros. For example HELPER_UINT8 won't work (invalid case). (Thanks #cxw)
The basic problem is that == is not supported for types, only for values. Given
uint8 foo;
you can say foo==42 but not foo == uint8. This is because types are not first class in C.
One hack would be to use the C preprocessor stringification operator # (gcc docs). However, this moves all your computation to runtime and may not be suitable for an embedded environment. For example:
#define GET_ENUM_FROM_TYPE(_type) ( \
(strcmp(#_type, "uint8")==0) ? PARAM_SIZE_UINT8 : \
((strcmp(#_type, "uint16")==0) ? PARAM_SIZE_UINT16 : \
((strcmp(#_type, "uint32")==0) ? PARAM_SIZE_UINT32 : PARAM_NONE)) \
)
With that definition,
GET_ENUM_FROM_TYPE(uint8)
expands to
( (strcmp("uint8", "uint8")==0) ? PARAM_SIZE_UINT8 : ((strcmp("uint8", "uint16")==0) ? PARAM_SIZE_UINT16 : ((strcmp("uint8", "uint32")==0) ? PARAM_SIZE_UINT32 : PARAM_NONE)) )
which should do what you want, although at runtime.
Sorry, this doesn't directly answer the question. But you should reconsider this whole code.
First of all, _Generic would have solved this elegantly.
The dirty alternative to untangle groups of macros like these, would be to use so-called X macros, which are perfect for cases such as "I don't want redundancy between the bitmap and parameters definitions". You can likely rewrite your code with X macros and get rid of a lot of superfluous defines and macros. How readable it will end up is another story.
However, whenever you find yourself this deep inside some macro meta-programming jungle, it is almost always a certain indication of poor program design. All of this smells like an artificial solution to a problem that could have been solved in much better ways - it is a "XY problem". (not to be confused with X macros :) ). The best solution most likely involves rewriting this entirely in simpler ways. Your case doesn't sound unique in any way, it seems that you just want to generate a bunch of bit masks.
Good programmers always try to make their code simpler, rather than making it more complex.
In addition, you may have more or less severe bugs all over the code, caused by the C language type system. It can be summarized as:
Bit shifts or other bitwise arithmetic should never be used on signed types. Doing so can lead to all manner of subtle bugs and poorly-defined behavior.
Enumeration constants are always of type int which is signed. You should avoid mixing them with bitwise arithmetic. Avoid enums entirely for programs like this.
Small integer types such as uint8_t or uint16_t get implicitly type promoted to int when used in an expression. Meaning that the C language will bandwagon most of your attempts to get the correct type and replace everything with int anyway.
The resulting type of your macros will be int, which is not what you want.
let's say I want to select the behaviour of a certain preprocessor directive evaluating at compile time the concatenation of a constant string and the result of another macro.
#define CASE1 text1
#define CASE2 text2
#define CASE3 text3
#define SCENARIO 3
/** the following won't work - for examplification purposes only**/
#define FUNCTION CASE##SCENARIO
/** whenever I write FUNCTION, I expect to see text3 **/
I am having an hard time thinking of a viable solution, as the preprocessor is a one-pass beast. Is that even feasible ?
It's possible, you just need to add some extra layers of macros. The key is that when you use the token-pasting operator ##, the preprocessor will not expand its operands. But, if you add another layer of macros, the preprocessor will expand those arguments. For example:
#define CASE1 text1
#define CASE2 text2
#define CASE3 text3
#define SCENARIO 3
#define TOKENPASTE_HELPER(x, y) x ## y
#define TOKENPASTE(x, y) TOKENPASTE_HELPER(x, y)
#define FUNCTION TOKENPASTE(CASE, SCENARIO)
When the preprocessor expands FUNCTION, it expands TOKENPASTE. When it expands TOKENPASTE, it expands its arugments (so SCENARIO gets replaced by 3), since neither of its arguments are operands of the token-pasting operator. Next, it expands TOKENPASTE_HELPER, which does the actual token pasting to make CASE3. Finally, it expands the CASE3 macro to get text3.
For example:
#define FOO(x) (printf(x))
and
#define FOO(x) {printf(x)}
It seems that both are viable for preprocessing, but which is better?
If you're treating the macro as an expression, use the () form.
If you're treating it as a command (and never as an expression) then use the {} form. Or rather, use the do{}while(0) form as that has fewer substitution hazards when used near keywords like if:
#define FOO(x) do { \
printf(x); \
} while(0)
Parentheses () are used to enforce correct evaluation regardless of operator precedence, so that you hopefully won't get any nasty side effects when the macro is expanded.
Braces {} are used to make the macro a C block statement, although the canonical way to do this is:
#define FOO(x) \
do { \
... stuff ... \
} while (0)
Note that gcc provides an extension to the C language which makes it possible to return a value from a block - the last expression evaluated will be the value returned if the block is used as part of an expression.
The purpose of using parens in a macro is to control precedence when the macro is expanded. Consider:
#define X( a, b ) a * b
if the macro is used like this
X( 1 + 2, 3 )
we would presumably like the answer to be 9, but what we get on expansion is:
1 + 2 * 3
giving us 7. To avoid this kind of thing, we should have written the macro as:
#define X( a, b ) ((a) * (b))
If precedence is not an issue, brackets either type are not absolutely required, though braces may be needed depending on the ,macros semantics - if for example you want to create a local variable,
If you will ever need FOO(x) inside an expression, then you cannot use the {} form. For example:
result = FOO(some_variable);
or
if (FOO(some_variable))