3
votes

Our system has a large number of enums denoting stuff such as events, errors etc.

I'm trying to build infrastructure that would allow us to log each received event or error message as a string (instead of a plain integer), without having to build and maintain two lists for each enum.

I found the X Macro technique quite suitable for my needs. Thus, instead of doing this:

typedef enum
{
   valA,
   valB,
   valC
} some_enum;

const char* some_enum_strings[] =
{                                                                                       
    "valA",
    "valB",
    "valC"
};

I'm doing this:

#define DEF_STRINGIFY(_x_) #_x_,
#define DEF_ENUM(_x_) _x_,

#define ENUM_NAME(_x_) \
    _x_(valA) \
    _x_(valB) \
    _x_(valC) 

typedef enum
{
    SOME_ENUM(DEF_ENUM)
} some_enum;

const char* some_enum_strings[] =
{                                                                                       
    SOME_ENUM(DEF_STRINGIFY)
};

That's all good and well, but the thing is some of our enums are quite big, comprising hundreds of values and filled with conditional compilation, and look a bit more like this

typedef enum
{
   valA,
#if defined (SYS_A)
   valB,
#endif
   valC,
   valD,
#if defined (SYS_B) || defined (SYS_D)
   valE,
#else
   valF,
#endif
   valG
/* etc. */
} some_enum;

As is turns out, C wouldn't allow conditional compilation within a macro. Eclipse claims "Invalid use of macro pasting in macro: SOME_ENUM, and when I try to build the code it fails due to "error: '#' is not followed by a macro parameter" (With the line number matching the first #if statement within the macro).

So now I'm quite stuck, and would appreciate any advice.

Is there a solution to my conundrum?

When suggesting a solution, please note that:

  • I can't have more than one list per enum
  • This solution needs to be applied to a large number of enums (i.e., I can't really put each enum in its own .h file)

Thanks.

1
What I'd do: take any simple C compiler that has source code available - tcc (Fabrice Bellard's), sdc (Small Device C Compiler), whatever, as long as it's complete enough to parse your code correctly. Only thing that matters is that you can quickly zero-in on the part of the source code that builds up the enums. You then it so that it produces text output - functions that have a big select, and a case for each value, and return the string. And that's pretty much the only solution that won't be totally awkward, and will keep on working. Remove codegen etc from the compiler to slim it up.Kuba hasn't forgotten Monica

1 Answers

1
votes

P99 has P99_DECLARE_ENUM and friends that lets you handle enums quite nicely. You obtain functions that return strings with the names, etc. This should be robust against conditional compilation. The only limit is the total amount of values that you can have in one enum type, but there would be probably ways to extend this.