enum値の逆引きをする関数を生成する

以前、同期からされた質問で、

enum enum_type{ hoge,fuga,aho };

という宣言に対して、

enum enum_type v = fuga;
printf("%s",search(v)); //=> fuga

という感じで、enumに定義した識別子を文字列として出力するようなsearch関数を自動的に作れないか?というもの。
そのときはそんなんできねーよってことで終わってしまったんだけど、エラー出力のときとかに役に立つしなんとかなんないかなーと自分なりに考えてみた。
最初のマクロ

#define ENUMERATION(type, e0,e1,e2,e3) enum type { e0,e1,e2,e3 }; \
    const char type[][16] = { #e0,#e1,#e2,#e3 };

ENUMERATION(test, hoge, fuga, aho, baka);

...
	printf("%s",test[fuga]); //=> fuga

配列の中に文字列化した識別子を入れてみる。enumの途中でaho=100とかはこの際考えてない。多少メモリ喰うけど、検索の必要もないしいいんじゃないかと。
ただ、マクロが可変引数を扱えないのでenumに要素を追加しようと思ったら、4箇所も書き換えなくてはいけない。ENUMERATIONの引数に追加するだけで何とかならんのか…?

調べてみると、C99では__VA_ARGS__によってマクロで可変引数が扱えるようになったらしい。C89が望ましいんだけど、試しに使ってみる。

#define ENUMERATION(type, ...) enum type { __VA_ARGS__ };

…って、__VA_ARGS__から引数それぞれに対して文字列化するやり方がわからんつーか存在しないのか??
しょうがないので、#__VA_SRGS__という文字列を保存しておいて、問い合わせがあるたびに文字列をサーチする関数を作った。
最終的なコードは以下

#define ENUMERATION_INIT() char _enum_ret[16];
#define ENUMERATION(type, ...) enum type { __VA_ARGS__ };\
        char *type = #__VA_ARGS__;\
        char *search_##type(enum type e) {\
        _enum_search(type,_enum_ret,e);\
        return _enum_ret;\
}
static void _enum_search(char *enum_type, char *tmp, int n)
{
    int len=0,cnt=0;
    char *st,*end;
    for(st = enum_type ; st != '\0' && cnt < n ; st++)
        if(*st == ',') cnt++;
    if(st == '\0') { *tmp = '\0'; return; }
    while(st ==" ") st++;
    for(end = st ; end != '\0' && *end != ',' && *end != ' '; len++, end++) ;
    strncpy(tmp,st,len);
    tmp[len] = '\0';
}

えらい長くなった……
使ってみる。

ENUMERATION_INIT();
ENUMERATION(word, hoge,fuga,aho,baka);
ENUMERATION(word2, poi,hoi,hei,doi);

....
    enum word a = fuga;

    printf("%s\n",search_word(a));  //=>fuga
    printf("%s\n",search_word2(0));  //=>poi
    printf("%s\n",search_word(aho)); //=>aho

最初のマクロと比べると検索に時間かかるなあ。それにINITとかめんどうで嫌だなあ……enum typeごとに検索結果格納用のバッファ作ってもいいけど、メモリが無駄。
だいたい可変引数を解釈してくれれば最初の2行のマクロでよかったのに。