0

I have a list of command ENUMs that can either be a request type, or a response type.

typedef enum {
     ENUM1,
     ENUM2,
     ...
} command_t;

And, I was planning on using X Macros to generate its ENUM, as well as name-string mapping table as follows:

// commmands.def
X(ENUM1),
X(ENUM2),

// main.h
#define X(ENUMVAL, ...) ENUMVAL
typedef enum {
    #include "commands.def"
} myenum_e;
#undef X

#define X(ENUMVAL, NAME) {.name = NAME, .val = ENUMVAL}
name_val_map_t name_val_map_table = {
    #include "commands.def"
} mytable_t;
#undef

Additionally, I also need to generate two sub-lists, namely, a req_list and a rsp_list. Is there a way I can keep just the one commands.def file and achieve this? I was trying something on the lines of:

// commmands.def   
// NAME, REQ, RSP
X(ENUM1, 1, 0),
X(ENUM2, 0, 1),

// main.h
#define IF(cond, foo) IF_IMPL(cond, foo)
#define IF_IMPL(cond, foo) IF_ ## cond (foo)
#define IF_0(foo)
#define IF_1(foo) foo

#define X(ENUMVAL, REQ, RSP) IFCOND(REQ, case: ENUMVAL)
void _is_req(myenum_e command) {
    switch(command) {
    #include commands.def
        return 1;
    default: return 0;
    }
}
#undef X

#define X(ENUMVAL, REQ, RSP) IFCOND(RSP, case: ENUMVAL)
void _is_rsp(myenum_e command) {
    switch(command) {
    #include commands.def
        return 1;
    default: return 0;
    }
}
#undef X

Is something like this possible? Thanks in advance!

  • You'd need to put the colon after the ENUMVAL in `IFCOND(RSP, case ENUMVAL:)`, but that's trivia. You'd also need double quotes around `command.def` in the `#include` lines — again, trivia. – Jonathan Leffler Mar 03 '20 at 05:52
  • Note that you should not, in general, create function, variable, tag or macro names that start with an underscore. Part of [C11 §7.1.3 Reserved identifiers](https://port70.net/~nsz/c/c11/n1570.html#7.1.3) says: — _All identifiers that begin with an underscore and either an uppercase letter or another underscore are always reserved for any use._ — _All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces._ See also [What does double underscore (`__const`) mean in C?](https://stackoverflow.com/q/1449181) – Jonathan Leffler Mar 03 '20 at 05:54
  • Surely you create an array of the full list of enumeration names, and add a single column indicating request or response (if there are no commands that are both request and response), and then write a function which returns the command type — . You can wrap that with `bool is_req(myenum_e cmd) { return cmd_type(cmd) == 1; }` (or `0` if the logic is that way around). The `switch` statements are not really desirable. Your functions can't return `void` and contain `return 0;` or `return. 1;` (more trivia). – Jonathan Leffler Mar 03 '20 at 05:59
  • When you experiment with macros, look at the preprocessed source code to check the effects. Each compiler (system) I know can output the preprocessed source, for example GCC with the option `-E`. – the busybee Mar 03 '20 at 07:25

0 Answers0