i found this macro in one kernel code.. http://lxr.free-electrons.com/source/arch/alpha/include/asm/io.h?v=3.0;a=arm#L140
#define IO_CONCAT(a,b) _IO_CONCAT(a,b)
#define _IO_CONCAT(a,b) a ## _ ## b
i am unable to understand the meaning of this.Does anybody know this?
Edit :
Then here what it will return
return IO_CONCAT(__IO_PREFIX,readl)(addr);
Double hash is used to concatenate two tokens together:
#define CONCAT(a,b) a ## b
CONCAT(x, y) # Gives 'xy'
However, such naive implementation doesn't work in case when one of the arguments being passed is a macro itself:
#define Z y
CONCAT(x, Z) # Gives 'xZ', not 'xy' as one might expect
That is why macro indirection is used in your question:
#define CONCAT(a,b) __CONCAT(a,b)
#define __CONCAT(a,b) a ## b
#define Z y
CONCAT(x, Z) # Gives 'xy'
Now consider the concrete example you're asking about:
return IO_CONCAT(__IO_PREFIX,readl)(addr);
Here __IO_PREFIX
is obviously a macro (uppercase identifiers in Linux kernel are often macros). It is defined in several places, one of them is:
#define __IO_PREFIX generic
Now let's see which steps are taken to expand the original statement:
__IO_PREFIX
:
return IO_CONCAT(generic,readl)(addr);
IO_CONCAT(...)
:
return _IO_CONCAT(generic,readl)(addr);
_IO_CONCAT(...)
:
return generic_readl(addr);
That's token pasting. It concatenates the tokens together. So IO_CONCAT(foo,bar)
would expand to foo_bar
.
It is defined in C99 in §6.10.3.3:
If, in the replacement list of a function-like macro, a parameter is immediately preceded or followed by a
##
preprocessing token, the parameter is replaced by the corresponding argument’s preprocessing token sequence; however, if an argument consists of no preprocessing tokens, the parameter is replaced by a placemarker preprocessing token instead.)For both object-like and function-like macro invocations, before the replacement list is reexamined for more macro names to replace, each instance of a
##
preprocessing token in the replacement list (not from an argument) is deleted and the preceding preprocessing token is concatenated with the following preprocessing token. Placemarker preprocessing tokens are handled specially: concatenation of two placemarkers results in a single placemarker preprocessing token, and concatenation of a placemarker with a non-placemarker preprocessing token results in the non-placemarker preprocessing token. If the result is not a valid preprocessing token, the behavior is undefined. The resulting token is available for further macro replacement. The order of evaluation of##
operators is unspecified.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With