I am attempting to make a section of code a bit more generic for a microcontroller that I am currently programming for.
What I want is a specific macro, formed from other tokens via concatenation. The problem is that one of the tokens is defined as a specific memory address (i.e. a register) and thus "garbage" is substituted mid-way. The following snippet illustrates the problem:
#include <stdio.h>
#include <stdint.h>
// The actual final token that I want (because I want the value of 10)
#define I_DRINK_BEER 10
// This line is the problematic line!
// It us defined in the microcontroller-specific header
// If this line is not defined, it works perfectly as desired.
#define DRINK (*(uint32_t*) (0x8000))
#define ACTION DRINK
#define INDIRECT(who,action,what) who ## action ## what
#define TOKEN_PASTE(who,action,what) INDIRECT(who,action,what)
#define CONSUMPTION(who,what) TOKEN_PASTE(who,ACTION,what)
int main(void)
{
printf("Value = %d\n", CONSUMPTION(I_,_BEER));
return 0;
}
If the line "#define DRINK ..." is commented out, the program compiles and executes as desired:
damien@damien-desktop:~$ gcc -o test test_macro_expansion.c
damien@damien-desktop:~$ ./test
Value = 10
But the inclusion of the offending line substitutes the complete address that makes the pre-processor complain:
test_macro_expansion.c: In function ‘main’:
test_macro_expansion.c:21:1: error: pasting "I_" and "(" does not give a valid preprocessing token
test_macro_expansion.c:21:1: error: pasting ")" and "_BEER" does not give a valid preprocessing token
test_macro_expansion.c:21:28: error: expected ‘)’ before ‘_BEER’
Is there a way I can tell the pre-processor not to substitute a particular token any further?
Why??
Before this seems a little esoteric, I have a timer for some particular functionality that is assigned to timer/counter "TCC0" in one project and "TCD1" in another project. It happens to be defined in as the base address of the register block for each timer, respectively. So, I have in my config header:
#define PERIPHERAL_TIMER TCC0
Which, works well in the main, because the registers of the timer can be referenced easily, for example:
value = PERIPHERAL_TIMER.CCA;
Deep in the toolchain, TCC0 is defined:
#define TCC0 (*(TC0_t *) 0x0800) /* Timer/Counter C0 */
The problem is that I have other macros defined in that have the TCC0) as part of the the name that I need elsewhere, for example:
// Note the TCC0 in the function argument!
EventSystem_SetEventSource(EVSYS_CHMUX_TCC0_OVF_gc);
Hence, I would like to define the symbol
// Conceptually what I want!
#define EVENT_SOURCE(timer) EVSYS_CHMUX_ ## timer ## _OVF_gc
// The "PERIPHERAL_TIMER" gets expanded to the address, not the token that I want
#define PERIPHERAL_EVENT EVENT_SOURCE(PERIPHERAL_TIMER)
I hope this clears up why I am asking the question.