1

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?

Community
  • 1
  • 1
Rev
  • 5,827
  • 4
  • 27
  • 51
  • I'm confused. What is the actual macro invocation you want to use, and what do you want its expansion to be? – John Bollinger Jun 28 '16 at 12:47
  • How is `PORTD` defined? – 2501 Jun 28 '16 at 12:54
  • @JohnBollinger: See clarification. I hope I am not just overcomplicating a simple matter. – Rev Jun 28 '16 at 12:55
  • @2501: I included the definition. – Rev Jun 28 '16 at 12:57
  • 1
    Making `(*(PORT_t *) 0x0660)` as a part of an identifier name doesn't make sense. Are you trying to obtain a value from memory at preprocessing to get a name with a suffix of that value ? That is not possible. – 2501 Jun 28 '16 at 12:59
  • This looks relevant but I haven't tried it. http://stackoverflow.com/questions/2653214/stringification-of-a-macro-value – GroovyDotCom Jun 28 '16 at 13:01
  • 1
    @2501: The IOPORT_CREATE_PIN macro is part of a library and works as desired. It more or less converts a specific pin on a specific port to a library internal unique numeric representation. The only issue is that the use case I described does not concatenate the contents to one of the expected library definitions like IOPORT_PORTD for example, which hold constants to compute the result. – Rev Jun 28 '16 at 13:16
  • If `PORTD` is defined as `(*(PORT_t *) 0x0660)` then it makes absolutely no sense to concat it as a name. I think you're confusing `IOPORT_PORTD` which is defined somewhere else and `PORTD`. – 2501 Jun 28 '16 at 13:18
  • 1
    @2501: Is is indeed, as pointed out in my previous comment. Sorry if it wasn't clear from the question. But the relevant part is the desired concatenation of IOPORT_ and PORTD to IOPORT_PORTD, which I maybe wasn't able to communicate clearly. – Rev Jun 28 '16 at 13:28
  • 1
    Note: if you had just hard-coded all those macros you would be done long time ago. Meta programming is not always the best option. – Lundin Jun 28 '16 at 13:28

2 Answers2

1

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.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • The relevant point (and the "catch" indeed) that I wasn't aware of was that FLASHPORT will be expanded recursively. I was thinking the wrapper just reduces one level of expansion. Thats why what Grzegorz proposed (what was actually the first thing i tried after reading the link that I provided in the question) does not work. So I figure its not possible to achieve what I want? – Rev Jun 28 '16 at 13:40
  • 1
    I tried to make some clarifications to the question, because it seems there was lots of confusion about the actual goal. – Rev Jun 28 '16 at 13:54
  • @Rev1.0, yes, the question was confusing. There are aspects of it that are *still* unclear. Nevertheless, I have expanded my answer with some additional commentary and a description of a possible alternative approach. – John Bollinger Jun 28 '16 at 14:07
  • Please ask regarding the "unclear aspects" if necessary. But judging from your alternate approach suggestion I think you got my point. Even if it requires a second somewhat redundant define in the configuration header, its still clearer and easier to modify than having to make changes in the source file on the IOPORT_CREATE_PIN call. Thanks for the suggestion. – Rev Jun 28 '16 at 18:35
0

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

GroovyDotCom
  • 1,304
  • 2
  • 15
  • 29
  • As I mentioned in the comments to your question, this solution can already be found at http://stackoverflow.com/questions/2653214/stringification-of-a-macro-value – GroovyDotCom Jun 28 '16 at 13:31