3

I want to generate a enum with a X-Macro. The enum has to increace based on prev size.

I have this

#define LIST
VAR(one, 0x02)
VAR(two, 0x02)
VAR(tree, 0x03)

and want to generate this

enum{
one = 0x02 + 0,
two = 0x02 + one,
tree = 0x03 + two
}

but this does not work

#define VAR(NAME, SIZE) STORED_LOCATION_##NAME = SIZE + (STORED_LOCATION_##NAME-1)
enum{STORED_VARIABLES};
#undef VAR

This works but i thing it can been easier

#define LIST \
VAR(one     ) STR(STORED_LOCATION   )\
VAR(two     ) PRE(one           )\
VAR(tree    ) PRE(two           )\
VAR(fore    ) PRE(tree          )\

enum
{
    one     = 0x00,
    two     = 0x01 + one,
    tree    = 0x01 + two,
    fore    = 0x01 + tree,
};

#define STR(OFFSET) OFFSET,
#define PRE(NAME) sizeof(##NAME) + STORED_LOCATION_##NAME,
#define VAR(NAME) STORED_LOCATION_##NAME =
enum{STORED_VARIABLES};
#undef VAR
#undef PRE
#undef STR
DJJo14
  • 49
  • 1
  • 3

2 Answers2

0

A working semi-solution might be to declare an equivalent dummy packed struct and than use the offsets of it's fields to get the desired enum values.

Like that (working under gcc):

File "my.def":

VAR(one, 0x02)
VAR(two, 0x02)
VAR(tree, 0x03)

Declaring struct and enum:

#define VAR(NAME, SIZE) char NAME[SIZE];
typedef struct __attribute__ ((__packed__)) {
#include "my.def"
} myEnumStruct;
#undef VAR

#define VAR(NAME, SIZE) NAME = (offsetof(myEnumStruct, NAME) + sizeof(((myEnumStruct*)0)->NAME)),
typedef enum{
#include "my.def"
} myEnum;
#undef VAR

int main(int argc, char **argv) {
    myEnum t;
#define VAR(NAME, SIZE) t=NAME; printf("Value of " #NAME " is %i\n", t);
#include "my.def"
#undef VAR

    return EXIT_SUCCESS;
}

Which gives the desired:

Value of one is 2
Value of two is 4
Value of tree is 7


Good luck!

vlp
  • 7,811
  • 2
  • 23
  • 51
0

Your question is confusing because your second example output doesn't match your first (desired) output. Furthermore, your first output is probably not what you really want, as the enums generated actually are the offsets that follow. More likely, you would want to generate enums that act as offsets to named fields:

enum
{
    one = 0,
    two = 2,
    tree = 4
};

The following code essentially generates that using a macro I use generally for creating offsets (note that it can be freely interspersed with normal enums):

//This macro makes it easy to define an enumeration that defines an offset, rather than
// an increment. The enumTag represents the offset and the size forces the following
// enumeration tag to be offset by that amount, rather than 1.
// _ignore##enumTag creates a throwaway enumeration that only exists to perform the offset.
#define ENUM_OFFSET(enumTag, size) enumTag, _ignore##enumTag = enumTag + (size) - 1

//VAR_(enumTag, size)
#define VAR_LIST(VAR_)
    VAR_(one  ,0x02)
    VAR_(two  ,0x02)
    VAR_(tree ,0x03)

enum 
{
    VAR_LIST(ENUM_OFFSET)
};

If you really want (which seems odd):

enum
{
    one = 2,
    two = 4,
    tree = 7
};

You have to reformulate the offset macro.

#define ENUM_END_OFFSET(enumTag, size) _ignore1##enumTag, enumTag = _ignore1##enumTag + (size), _ignore2##enumTag = enumTag - 1,
enum 
{
    VAR_LIST(ENUM_END_OFFSET)
};
jsheaney
  • 99
  • 1
  • 3