I'm trying to write a macro which simplifies setting multiple bits in an integer. This commonly occurs in microcontroller code when initializing configuration registers. For example, one might configure an 8-bit timer by setting 3 bits in the register TCCR0A
like this:
// WGM01, WGM00 and COM0A1 are constants between 0 and 7
// There are hundreds of these constants defined in avr-libc
TCCR0A |= (1<<WGM01) | (1<<WGM00) | (1<<COM0A1);
// Another way to write this:
#define _BV(bit) (1 << (bit)) // <-- defined in avr-libc
TCCR0A |= _BV(WGM01) | _BV(WGM00) | _BV(COM0A1);
However, I'd find it a lot easier to write something like this:
TCCR0A |= BITS(WGM01, WGM00, COM0A1); // <- Variable # of arguments please!
Since I can't imagine that nobody has thought of this yet, I searched around but found nothing which does exactly this. I wonder if this is possible at all, but I gave it a shot anyways while reading https://gcc.gnu.org/onlinedocs/cpp/Variadic-Macros.html and https://github.com/pfultz2/Cloak/wiki/C-Preprocessor-tricks,-tips,-and-idioms.
Here's what I tried so far. I imagine the solution must be recursive macro, but didn't get very far when trying to get it to expand correctly. Since all my registers are 8 bits long, 8 expansion passes should be sufficient (for a first try).
#define BITS_EVAL(...) BITS_EVAL1(BITS_EVAL1(BITS_EVAL1(__VA_ARGS__)))
#define BITS_EVAL1(...) BITS_EVAL2(BITS_EVAL2(BITS_EVAL2(__VA_ARGS__)))
#define BITS_EVAL2(...) __VA_ARGS__
#define BITS(bit, ...) ((1 << bit) | BITS_EVAL(BITS(__VA_ARGS__)))
The above doesn't quite work. What it currently does is:
// BITS(2,5,7) --> ((1 << 2) | BITS(5, 7))
However, what I would like to achieve is one of these (or equivalent):
// BITS(2,5,7) --> ((1 << 2) | (1 << 5) | (1 << 7))
// BITS(2,5,7) --> ((1 << 2) | ((1 << 5) | ((1 << 7))))
Can anyone help me with my quest, or tell me that it's impossible to achieve this?