2
votes

How can I test the string value of a macro parameter in C at compile time?

I'm writing wrapper macros for a micro-controller in C (GNU).

I have some macros that work like this:

#define _ReadBits(port, mask)      (PORT ## port) & (mask)
#define ReadBits(portmask)         _ReadBits(portmask) 
#define SWITCH D, (1<<7)

This way I can say:

foo = ReadBits(SWITCH);

and I'll get

foo = PORTD & (1<<7);

That works great. I want to expand these to do something like this:

#define _ConfigAnalog(port, mask)  BUILD_BUG_ON(port != B); AD1PCFGCLR = (mask)
#define ConfigAnalog(portmask)    _ConfigAnalog(portmask)

That is, I want a compile-time error to happen if parameter port isn't B (because this micro-controller can configure only port B as analog).

Is there some way to do this in C?

2

2 Answers

4
votes

Figured it out myself:

#define PORT_B_SUPPORTS_ANALOG

#define __CheckPort(p)  PORT_##p##_SUPPORTS_ANALOG
#define __ConfigAnalogBits(mask) AD1PCFGCLR = (mask)

#define _ConfigAnalogBits(port, mask)  __CheckPort(port); __ConfigAnalogBits(mask)
#define ConfigAnalogBits(portmask)     _ConfigAnalogBits(portmask)

#define NO_GOOD C, (1<<3)
#define VOLTAGE B, (1<<3)

void tryit(void)
{
    ConfigAnalogBits(VOLTAGE);
    //ConfigAnalogBits(NO_GOOD);
}

If "port" is B then _CheckPort compiles into a null statement.

If "port" is anything else, a build error happens.

0
votes

How can I test the string value of a macro parameter in C at compile?

You can't.

According to C99 6.10.1 Conditional inclusion, pre-processor conditions must be an integer constant expressions, and may test whether a macro is defined (using #if, #ifdef identifier or #if defined(identifier)).