Строгание условно скомпилированного перечисления в C

Наша система имеет большое количество перечислений, обозначающих такие вещи, как события, ошибки и т.д.

Я пытаюсь создать инфраструктуру, которая позволит нам регистрировать каждое полученное событие или сообщение об ошибке как строку (вместо простого целого), без необходимости создавать и поддерживать два списка для каждого перечисления.

Я нашел технику X Macro, вполне подходящую для моих нужд. Таким образом, вместо этого:

typedef enum
{
   valA,
   valB,
   valC
} some_enum;

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

Я делаю это:

#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)
};

Что все хорошо и хорошо, но дело в том, что некоторые из наших перечислений довольно большие, состоящие из сотен значений и заполненные условной компиляцией, и выглядят немного более похожими на это.

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;

Как оказывается, C не позволит условной компиляции внутри макроса. Eclipse утверждает: "Недопустимое использование макросов в макросе: SOME_ENUM, и когда я пытаюсь создать код, который он сбой из-за" ошибки: "#" не сопровождается параметром макроса "(с номером строки, соответствующим первому оператору #if внутри макроса).

Итак, теперь я совсем застрял и буду благодарен за любые советы.

Есть ли решение моей головоломки?

Если вы предлагаете решение, обратите внимание, что:

  • У меня не может быть более одного списка на enum
  • Это решение должно применяться к большому количеству перечислений (т.е. я не могу поместить каждое перечисление в свой собственный файл .h)

Спасибо.

Ответ 1

P99 имеет P99_DECLARE_ENUM и друзей, которые позволяют вам отлично справляться с enum. Вы получаете функции, возвращающие строки с именами и т.д. Это должно быть устойчивым к условной компиляции. Единственным ограничением является общее количество значений, которое вы можете иметь в одном типе enum, но, вероятно, были бы способы его расширения.