c - Concatenation macro not properly expanding macro parameter -
the macro of interest (ioport_create_pin) part of library , works desired in general. converts specific pin on specific port library internal unique numeric representation.
it defined as:
#define ioport_create_pin(port, pin) ((ioport_ ## port) * 8 + (pin))
normal usage be
ioport_create_pin(portd, 4)
for example, concatenate ioport_ , portd ioport_portd. ioport_portd in example internal definition of library further expands numeric value.
however, since portd (defined #define portd (*(port_t *) 0x0660)
, not relevant here) part of definition
#define flashport portd
so using
ioport_create_pin(flashport, 4)
wrongly concatenates ioport_flashport instead of desired ioport_portd inside ioport_create_pin definition.
i had @ this interesting answer , tried apply 1 level of indirection hoping macro expanded, wasn't able right.
is there way "wrap" macro somehow make compiler evaluate flashport portd before concatenation?
edit:
john pointed out problem wrapping is, flashport expanded recursively, not flashport portd, (*(port_t *) 0x0660)
.
is there workaround?
normally, arguments function-like macro macro-expanded before being substituted macro's replacement text. argument expansion suppressed, however, macro arguments operands of concatenation (##
) or stringification (#
) operator -- that's reason performing double-expansion if want concatenate or stringify macro's replacement value instead of name.
i can not change ioport_create_pin macro. there way "wrap" macro somehow make compiler evauate flashport portd before concatenation?
my understanding want define new macro, e.g. wrapper()
can invoke instead of ioport_create_pin()
, expansion same ioport_create_pin()
arguments portd, 4
, , expansion not change same when flashport
used instead of portd
first argument.
whether doable depends in part on macro arguments. generally, straight-up wrapper understand asking for:
// illustrative purposes: #define ioport_portd correct! #define ioport_flashport wrong! // specified in 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 to:
direct call: ((wrong!) * 8 + (4)) wrapped call: ((correct!) * 8 + (4)) wrapped call: ((correct!) * 8 + (4))
the catch here if portd
defined macro in own right, hosed. cannot expand flashport
portd
; if flashport
expanded result of expansion expanded again, recursively, before substituted.
alternative approach
as far know or can determine, not possible create general-purpose alias preprocessor macro. no token-pasting or stringification involved, can have done, , define 1 macro expand name of another, doesn't play pasting or stringification.
if for-purpose solution acceptable, however, there alternatives. example, if can identify token-pasting operations can involve alias, can provide aliases pasted-together macros, too. in case, might this:
// illustrative purposes: #define ioport_portd correct! #define portd oops // specified in question: #define flashport portd #define ioport_create_pin(port, pin) ((ioport_ ## port) * 8 + (pin)) // patch token-pasting: #define ioport_flashport ioport_portd // demo: direct call: ioport_create_pin(flashport, 4)
the preprocessor expands to
direct call: ((correct!) * 8 + (4))
that doesn't scale well, of course, , requires knowledge or study of overall macro set involved, solve limited-scope problem presented in question.
Comments
Post a Comment