I am trying to write macros set_DIR(), clr_DIR(), etc. in a library for microcontrollers from family AVR16-AVR128.
I have problem wiht adding letter V to port names in a macro.
In code below I described when is a place, where preprocessor should add letter V if virtual ports are enabled.
I can't use functions. Virtual ports changes bits in ports in 1 cycle of CPU clock, and I need it. So I must use macros to generate fastest code.
//=== From microcontroller toolchain header: ioavr128db64.h =========
/* Virtual Ports */
typedef struct VPORT_struct
{
register8_t DIR;
register8_t OUT;
register8_t IN;
register8_t INTFLAGS;
} VPORT_t;
#define VPORTA (*(VPORT_t *) 0x0000)
#define VPORTB (*(VPORT_t *) 0x0004)
#define VPORTC (*(VPORT_t *) 0x0008)
// ... etc.
//--- PORTS definitions (normal ports) -----
typedef struct PORT_struct
{
register8_t DIRSET;
register8_t DIRCLR;
// etc.
} PORT_t;
#define PORTA (*(PORT_t *) 0x0400)
#define PORTB (*(PORT_t *) 0x0420)
#define PORTC (*(PORT_t *) 0x0440)
// ... etc.
//========== My definitions ==================================
/* chceck if virtual ports are available */
// Caution! VVV is place where preprocessor should add letter V to choosen port
#ifdef VPORTA
#define VPORTS 1
#define set_DIR(x, y) VVV(x).DIR |= (y) /* should generate: VPORTA.DIR |= 3 */
#define clr_DIR(x, y) VVV(x).DIR &=~(y) /* should generate: VPORTA.DIR &=~ 3 */
/* etc. */
#else
#define VPORTS 0
#define set_DIR(x, y) (x).DIRSET = (y) /* should generate: PORTA.DIRSET = 3 */
#define clr_DIR(x, y) (x).DIRCLR = (y) /* should generate: PORTA.DIRCLR = 3 */
/* etc. */
#endif
//Caution! Its very important - must be like this!
#define PORT PORTA /* may be chanched e.g. PORTC */
int main(void)
{
//example
set_DIR(PORT, 3);
return 0;
}
When I place where are VVV i pasted one letter V an error occurs:
Severity Code Description Project File Line
Warning implicit declaration of function 'V' [-Wimplicit-function-declaration] tests main.c 11
How can fix it?
Change
#define set_DIR(x, y) x ## .DIR |= ## yto#define set_DIR(x, y) ((x).DIR |= (y)).In macro processing,
##is processed before the result is rescanned for further macro replacement, soPORTwas combined with another token before it could be replaced byVPORTA. When the##are removed, that is not an issue.Parsing expressions is part of the main C processing. It is not part of preprocessing, including macro replacement, and you should not try to use the
##operator for that.##is for combining grammatical tokens.In macros, you mostly simply write C code as if the macro parameters were ordinary identifiers, except they should often be parenthesized so that, when the argument is an expression with operators, it is taken as a single item in parentheses in the code resulting from macro expansion.