0

I have a set of #defines like that:

#define PORTA port_a
#define PORTB port_b
#define PORTC port_c

And some re-definitions of these into:

#define MY_PORT1 PORTA
#define MY_PORT2 PORTB
#define MY_PORT3 PORTC

And also a series of xxx_set(param1, param2) functions where xxx belongs to each PORTx, so:

PORTA_set(param1, param2)
PORTB_set(param1, param2)
PORTC_set(param1, param2) 

I need to call these functions but using a single one, with my "custom port name" as the first parameter, so example:

set(MY_PORT1, param1, param2) must expand to PORTA_set(param1, param2), and so on.

I tried after reading several similar questions, related to expansion of macros into concatenations:

#define CAT_I( x, y ) x ## y
#define CAT( x, y ) CAT_I( x, y )
#define set( port, param1, param2 ) CAT( port, _set )(param1, param2)

But this throws me error

expected ';' before '_set'
pasting ")" and "_set" does not give a valid preprocessing token

What am I missing?

1
  • pasting ")" and "_set" what does port_a expand to? Is there no "in expansion of.. in expansion of..." messages? Are there no "file:line:column" in error messages? Please post the full error message. Commented May 27, 2021 at 18:17

3 Answers 3

0

It seems like you have:

#define port_a (something something)

which then does not work, because preprocessor can't concatenate ) with _set. No, you can't "halfway" expand a macro.

But why write all these PORT all the time. Just write the letters.

#define PORTA port_a
#define PORTB port_b
#define PORTC port_c

#define MY_PORT1   A
#define MY_PORT2   B
#define MY_PORT3   C

#define _set_in(x) PORT##x##_set
#define set(port, param1, param2)  _set_in(port)(param1, param2)
Sign up to request clarification or add additional context in comments.

1 Comment

This is the most acceptable for my situation. And yes, "port_a" was a way to simplify my code, but in reality it is a variable wrapped into "( )". Now it is clear and I've followed your suggestion regarding the single letters.
0

I think you've just got too many macros. Not sure why the token pasting examples all use macros called CAT. I don't think it helps, and it seems to be adding excessive complexity.

#define setport( port, param1, param2 ) port##_set(param1, param2) ought to work.

Note that it's a bad idea to use set as the name of a macro and part of the definition. That's why this macro is called setport

Comments

0

I need to call these functions but using a single one, with my "custom port name" as the first parameter

If that is the purpose, you might want to consider a different approach, which uses C11 generic selection:

#include <stdio.h>

// Define some helper types or tags.
typedef struct PORTA PORTA;
typedef struct PORTB PORTB;
typedef struct PORTC PORTC;

typedef PORTA port_a;
typedef PORTB port_b;
typedef PORTC port_c;

typedef PORTA MY_PORT1;
typedef PORTB MY_PORT2;
typedef PORTC MY_PORT3;

// The actual functions to be called:
void PORTA_set(int a, int b) {
    printf("PORT A   args: %d %d\n", a, b);
}

void PORTB_set(int a, int b) {
    printf("PORT B   args: %d %d\n", a, b);
}

void PORTC_set(int a, int b) {
    printf("PORT C   args: %d %d\n", a, b);
}

// Macroes that perform the selection:
#define set_impl(X, a, b) _Generic( X, \
                                    PORTA*: PORTA_set, \
                                    PORTB*: PORTB_set, \
                                    PORTC*: PORTC_set \
)(a, b)

#define set_(type, a, b) set_impl((type *)NULL, (a), (b))

int main(void)
{
    // Calls with the wanted interface.
    set_(port_a, 0, 1);
    set_(MY_PORT2, 42, 17);
    set_(PORTC, 8, 99);

    // Direct call example.
    PORTC_set(-3, 0);
}

Testable here.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.