Skip to content

Instantly share code, notes, and snippets.

@hildjj
Last active December 16, 2015 12:49
Show Gist options
  • Save hildjj/5437270 to your computer and use it in GitHub Desktop.
Save hildjj/5437270 to your computer and use it in GitHub Desktop.
Generate enums and their string versions.
#ifndef ENUM_H
#define ENUM_H
#include <stddef.h>
#include <string.h>
#include <stdbool.h>
/* Entry points */
/* Define an enum, suitable for putting in a .h file */
#define ENUM(NAME,...) SENUM(,NAME,__VA_ARGS__)
/* Implement functions for the given enum; put this in exactly one .c file */
#define ENUM_IMPL(NAME) SENUM_IMPL(,NAME)
/* Both of the above, set up for static use in a single .c file */
#define STATIC_ENUM(NAME, ...) SENUM(static,NAME, __VA_ARGS__) SENUM_IMPL(static,NAME)
/* implementation */
#define VSTR_1(a) #a
#define VSTR_2(a,...) #a, VSTR_1(__VA_ARGS__)
#define VSTR_3(a,...) #a, VSTR_2(__VA_ARGS__)
#define VSTR_4(a,...) #a, VSTR_3(__VA_ARGS__)
#define VSTR_5(a,...) #a, VSTR_4(__VA_ARGS__)
#define VSTR_6(a,...) #a, VSTR_5(__VA_ARGS__)
#define VSTR_7(a,...) #a, VSTR_6(__VA_ARGS__)
#define VSTR_8(a,...) #a, VSTR_7(__VA_ARGS__)
#define VSTR_9(a,...) #a, VSTR_8(__VA_ARGS__)
#define VSTR_10(a,...) #a, VSTR_9(__VA_ARGS__)
#define VSTR_11(a,...) #a, VSTR_10(__VA_ARGS__)
#define VSTR_12(a,...) #a, VSTR_11(__VA_ARGS__)
#define VSTR_13(a,...) #a, VSTR_12(__VA_ARGS__)
#define VSTR_14(a,...) #a, VSTR_13(__VA_ARGS__)
#define VSTR_15(a,...) #a, VSTR_14(__VA_ARGS__)
#define VSTR_16(a,...) #a, VSTR_15(__VA_ARGS__)
#define VSTR_17(a,...) #a, VSTR_16(__VA_ARGS__)
#define VSTR_18(a,...) #a, VSTR_17(__VA_ARGS__)
#define VSTR_19(a,...) #a, VSTR_18(__VA_ARGS__)
#define VSTR_20(a,...) #a, VSTR_19(__VA_ARGS__)
#define VSTR_21(a,...) #a, VSTR_20(__VA_ARGS__)
#define VSTR_22(a,...) #a, VSTR_21(__VA_ARGS__)
#define VSTR_23(a,...) #a, VSTR_22(__VA_ARGS__)
#define VSTR_24(a,...) #a, VSTR_23(__VA_ARGS__)
#define VSTR_25(a,...) #a, VSTR_24(__VA_ARGS__)
#define VSTR_26(a,...) #a, VSTR_25(__VA_ARGS__)
#define VSTR_27(a,...) #a, VSTR_26(__VA_ARGS__)
#define VSTR_28(a,...) #a, VSTR_27(__VA_ARGS__)
#define VSTR_29(a,...) #a, VSTR_28(__VA_ARGS__)
#define VSTR_30(a,...) #a, VSTR_29(__VA_ARGS__)
#define VSTR_31(a,...) #a, VSTR_30(__VA_ARGS__)
#define VSTR_32(a,...) #a, VSTR_31(__VA_ARGS__)
#define VSTR_33(a,...) #a, VSTR_32(__VA_ARGS__)
#define VSTR_34(a,...) #a, VSTR_33(__VA_ARGS__)
#define VSTR_35(a,...) #a, VSTR_34(__VA_ARGS__)
#define VSTR_36(a,...) #a, VSTR_35(__VA_ARGS__)
#define VSTR_37(a,...) #a, VSTR_36(__VA_ARGS__)
#define VSTR_38(a,...) #a, VSTR_37(__VA_ARGS__)
#define VSTR_39(a,...) #a, VSTR_38(__VA_ARGS__)
#define VSTR_40(a,...) #a, VSTR_39(__VA_ARGS__)
#define VSTR_41(a,...) #a, VSTR_40(__VA_ARGS__)
#define VSTR_42(a,...) #a, VSTR_41(__VA_ARGS__)
#define VSTR_43(a,...) #a, VSTR_42(__VA_ARGS__)
#define VSTR_44(a,...) #a, VSTR_43(__VA_ARGS__)
#define VSTR_45(a,...) #a, VSTR_44(__VA_ARGS__)
#define VSTR_46(a,...) #a, VSTR_45(__VA_ARGS__)
#define VSTR_47(a,...) #a, VSTR_46(__VA_ARGS__)
#define VSTR_48(a,...) #a, VSTR_47(__VA_ARGS__)
#define VSTR_49(a,...) #a, VSTR_48(__VA_ARGS__)
#define VSTR_50(a,...) #a, VSTR_49(__VA_ARGS__)
#define VSTR_51(a,...) #a, VSTR_50(__VA_ARGS__)
#define VSTR_52(a,...) #a, VSTR_51(__VA_ARGS__)
#define VSTR_53(a,...) #a, VSTR_52(__VA_ARGS__)
#define VSTR_54(a,...) #a, VSTR_53(__VA_ARGS__)
#define VSTR_55(a,...) #a, VSTR_54(__VA_ARGS__)
#define VSTR_56(a,...) #a, VSTR_55(__VA_ARGS__)
#define VSTR_57(a,...) #a, VSTR_56(__VA_ARGS__)
#define VSTR_58(a,...) #a, VSTR_57(__VA_ARGS__)
#define VSTR_59(a,...) #a, VSTR_58(__VA_ARGS__)
#define VSTR_60(a,...) #a, VSTR_59(__VA_ARGS__)
#define VSTR_61(a,...) #a, VSTR_60(__VA_ARGS__)
#define VSTR_62(a,...) #a, VSTR_61(__VA_ARGS__)
#define VSTR_63(a,...) #a, VSTR_62(__VA_ARGS__)
#define VSTR_64(a,...) #a, VSTR_63(__VA_ARGS__)
#define VSTR_65(a,...) #a, VSTR_64(__VA_ARGS__)
#define VSTR_66(a,...) #a, VSTR_65(__VA_ARGS__)
#define VSTR_67(a,...) #a, VSTR_66(__VA_ARGS__)
#define VSTR_68(a,...) #a, VSTR_67(__VA_ARGS__)
#define VSTR_69(a,...) #a, VSTR_68(__VA_ARGS__)
#define VSTR_70(a,...) #a, VSTR_69(__VA_ARGS__)
#define VSTR_71(a,...) #a, VSTR_70(__VA_ARGS__)
#define VSTR_72(a,...) #a, VSTR_71(__VA_ARGS__)
#define VSTR_73(a,...) #a, VSTR_72(__VA_ARGS__)
#define VSTR_74(a,...) #a, VSTR_73(__VA_ARGS__)
#define VSTR_75(a,...) #a, VSTR_74(__VA_ARGS__)
#define VSTR_76(a,...) #a, VSTR_75(__VA_ARGS__)
#define VSTR_77(a,...) #a, VSTR_76(__VA_ARGS__)
#define VSTR_78(a,...) #a, VSTR_77(__VA_ARGS__)
#define VSTR_79(a,...) #a, VSTR_78(__VA_ARGS__)
#define VSTR_80(a,...) #a, VSTR_79(__VA_ARGS__)
#define VSTR_81(a,...) #a, VSTR_80(__VA_ARGS__)
#define VSTR_82(a,...) #a, VSTR_81(__VA_ARGS__)
#define VSTR_83(a,...) #a, VSTR_82(__VA_ARGS__)
#define VSTR_84(a,...) #a, VSTR_83(__VA_ARGS__)
#define VSTR_85(a,...) #a, VSTR_84(__VA_ARGS__)
#define VSTR_86(a,...) #a, VSTR_85(__VA_ARGS__)
#define VSTR_87(a,...) #a, VSTR_86(__VA_ARGS__)
#define VSTR_88(a,...) #a, VSTR_87(__VA_ARGS__)
#define VSTR_89(a,...) #a, VSTR_88(__VA_ARGS__)
#define VSTR_90(a,...) #a, VSTR_89(__VA_ARGS__)
#define VSTR_91(a,...) #a, VSTR_90(__VA_ARGS__)
#define VSTR_92(a,...) #a, VSTR_91(__VA_ARGS__)
#define VSTR_93(a,...) #a, VSTR_92(__VA_ARGS__)
#define VSTR_94(a,...) #a, VSTR_93(__VA_ARGS__)
#define VSTR_95(a,...) #a, VSTR_94(__VA_ARGS__)
#define VSTR_96(a,...) #a, VSTR_95(__VA_ARGS__)
#define VSTR_97(a,...) #a, VSTR_96(__VA_ARGS__)
#define VSTR_98(a,...) #a, VSTR_97(__VA_ARGS__)
#define VSTR_99(a,...) #a, VSTR_98(__VA_ARGS__)
#define VSTR_100(a,...) #a, VSTR_99(__VA_ARGS__)
#define VSTR_101(a,...) #a, VSTR_100(__VA_ARGS__)
#define VSTR_102(a,...) #a, VSTR_101(__VA_ARGS__)
#define VSTR_103(a,...) #a, VSTR_102(__VA_ARGS__)
#define VSTR_104(a,...) #a, VSTR_103(__VA_ARGS__)
#define VSTR_105(a,...) #a, VSTR_104(__VA_ARGS__)
#define VSTR_106(a,...) #a, VSTR_105(__VA_ARGS__)
#define VSTR_107(a,...) #a, VSTR_106(__VA_ARGS__)
#define VSTR_108(a,...) #a, VSTR_107(__VA_ARGS__)
#define VSTR_109(a,...) #a, VSTR_108(__VA_ARGS__)
#define VSTR_110(a,...) #a, VSTR_109(__VA_ARGS__)
#define VSTR_111(a,...) #a, VSTR_110(__VA_ARGS__)
#define VSTR_112(a,...) #a, VSTR_111(__VA_ARGS__)
#define VSTR_113(a,...) #a, VSTR_112(__VA_ARGS__)
#define VSTR_114(a,...) #a, VSTR_113(__VA_ARGS__)
#define VSTR_115(a,...) #a, VSTR_114(__VA_ARGS__)
#define VSTR_116(a,...) #a, VSTR_115(__VA_ARGS__)
#define VSTR_117(a,...) #a, VSTR_116(__VA_ARGS__)
#define VSTR_118(a,...) #a, VSTR_117(__VA_ARGS__)
#define VSTR_119(a,...) #a, VSTR_118(__VA_ARGS__)
#define VSTR_120(a,...) #a, VSTR_119(__VA_ARGS__)
#define VSTR_121(a,...) #a, VSTR_120(__VA_ARGS__)
#define VSTR_122(a,...) #a, VSTR_121(__VA_ARGS__)
#define VSTR_123(a,...) #a, VSTR_122(__VA_ARGS__)
#define VSTR_124(a,...) #a, VSTR_123(__VA_ARGS__)
#define VSTR_125(a,...) #a, VSTR_124(__VA_ARGS__)
#define VSTR_126(a,...) #a, VSTR_125(__VA_ARGS__)
#define VSTR_127(a,...) #a, VSTR_126(__VA_ARGS__)
#define VSTR_128(a,...) #a, VSTR_127(__VA_ARGS__)
#define _NUM_ARGS2(X,X128,X127,X126,X125,X124,X123,X122,X121,X120,X119,X118,X117,X116,X115,X114,X113,X112,X111,X110,X109,X108,X107,X106,X105,X104,X103,X102,X101,X100,X99,X98,X97,X96,X95,X94,X93,X92,X91,X90,X89,X88,X87,X86,X85,X84,X83,X82,X81,X80,X79,X78,X77,X76,X75,X74,X73,X72,X71,X70,X69,X68,X67,X66,X65,X64,X63,X62,X61,X60,X59,X58,X57,X56,X55,X54,X53,X52,X51,X50,X49,X48,X47,X46,X45,X44,X43,X42,X41,X40,X39,X38,X37,X36,X35,X34,X33,X32,X31,X30,X29,X28,X27,X26,X25,X24,X23,X22,X21,X20,X19,X18,X17,X16,X15,X14,X13,X12,X11,X10,X9,X8,X7,X6,X5,X4,X3,X2,X1,N,...) N
#define NUM_ARGS(...) _NUM_ARGS2(0, __VA_ARGS__ ,128,127,126,125,124,123,122,121,120,119,118,117,116,115,114,113,112,111,110,109,108,107,106,105,104,103,102,101,100,99,98,97,96,95,94,93,92,91,90,89,88,87,86,85,84,83,82,81,80,79,78,77,76,75,74,73,72,71,70,69,68,67,66,65,64,63,62,61,60,59,58,57,56,55,54,53,52,51,50,49,48,47,46,45,44,43,42,41,40,39,38,37,36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
#define _VSTR_N3(N, ...) VSTR_ ## N(__VA_ARGS__)
#define _VSTR_N2(N, ...) _VSTR_N3(N, __VA_ARGS__)
#define VSTR_N(...) _VSTR_N2(NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
#define SENUM(st,NAME,...) \
enum NAME { \
__VA_ARGS__, LAST_##NAME \
}; \
st const char *NAME##_names[] = {\
VSTR_N(__VA_ARGS__), \
NULL \
}; \
st bool is_valid_##NAME(enum NAME val); \
st const char *NAME ## _to_string(enum NAME val); \
st enum NAME string_to_ ## NAME(const char *str);
#define SENUM_IMPL(st,NAME) \
st bool is_valid_##NAME(enum NAME val) { return (val >= 0) && (val < LAST_##NAME); } \
st const char *NAME ## _to_string(enum NAME val) { \
if (!is_valid_##NAME(val)) { \
return "Unknown value for " #NAME; \
} \
return NAME##_names[val]; \
} \
st enum NAME string_to_ ## NAME(const char *str) { \
int i; \
for (i=0; i<LAST_##NAME; i++) { \
if (strcmp(NAME##_names[i], str) == 0) { \
return i; \
} \
}\
return -1; \
}
#endif /* ENUM_H */
@hildjj
Copy link
Author

hildjj commented Apr 22, 2013

Uses the approach from http://stackoverflow.com/a/5048661/8388. Invoke like this:

ENUM(foo, A, B, C)

Where "foo" is the name of the enum, and A, B, and C are the values.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment