C语言自动生成enum值和名字映射代码
这年头好像继续做C语言的人不多了,年轻人大多去互联网和移动应用。确实,那两个领域现在来钱快,且总是供不应求。就说刚刚在一个旧同事的微信群里,有人刚放出自己有团队可以做App几分钟,哇塞,好几个人说有项目,要求加好友私聊。我也想过转行,可惜人老珠黄,没有互联网或是应用团队愿意接收。估计再过些年,C程序世界里就只有我这样的小老头们继续自娱自乐了,羡慕死年轻人了!
平常工作中,经常要做一些打印,或是日志。而这里面,enum类型的数据就很多,如果只是打印出它的整数值,显然会让测试人员很恼火,鬼知道那数字说的是什么。就算你给他个文档对着看,也丝毫不能得到原谅。最后,都得乖乖的把这个enum对应的名字打印出来才能平息。
今天说的这个,就是帮忙搞定这个转换问题的。
比如,有这么个example.h文件:
enumInfoStateE{
eInfoStateIdle,
eInfoStateIniting,
eInfoStateInited,
eInfoStateReady,
eInfoStateActive,
eInfoStateStandby,
eInfoStateRelease,
};
我们需要个函数,把enum值翻译成字符串;另外也要个函数,能查找字符串对应的enum值;可以提供名字的一部分。p_enum.pl就是做这个的,只需要执行:
perlp_enum.plexample.h-o:example_map
p_enum.pl接受目录,通配符,或是多个文件。-o:example_map是指定输出的文件名。这里我们得到了example_map.h和example_map.c两个文件:
/*
FILE:example_map.h
ThisfilewascreatedatFriDec1116:40:56CST2015
Auto-generatedsource.Don'tchangeitmanually.
Contactwithhhao020@gmail.comforbugreportingandsupporting.
*/
#ifndefEXAMPLE_MAP
#defineEXAMPLE_MAP
#ifdef__cplusplus
extern"C"{
#endif
#include"zType_Def.h"
externconstchar*InfoStateE2Name(dword_te);
externdword_tInfoStateE2Value(char*name,intbAppro);
externintInfoStateEMapShow();
#ifdef__cplusplus
}
#endif
#endif/*EXAMPLE_MAP*/
/*
FILE:example_map.c
ThisfilewascreatedatFriDec1116:40:56CST2015
Auto-generatedsource.Don'tchangeitmanually.
Contactwithhhao020@gmail.comforbugreportingandsupporting.
*/
#define_GNU_SOURCE
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include"zAutoCodeApi.h"
#ifndefENUM_PRIMARY_FUNCTIONS
staticchar*zEnum2Name(dword_te,zEnum2NameMap_tarr[],intnSize)
{
inti;
for(i=0;i<nSize;i++)
{
if(arr[i].e==e)returnarr[i].name;
}
return0;
}
staticintzName2Enum(char*name,zEnum2NameMap_tarr[],intnSize,intbAppro)
{
inti;
for(i=0;i<nSize;i++)
{
if(bAppro)
{
if(strcasestr(arr[i].name,name))returnarr[i].e;
}
else
{
if(!strcmp(arr[i].name,name))returnarr[i].e;
}
}
return-1;
}
staticintzEnumMapShow(zEnum2NameMap_tarr[],intnSize)
{
inti;
for(i=0;i<nSize;i++)
{
printf("%3d%d->%s\n",i,arr[i].e,arr[i].name);
}
return0;
}
#endif/*ENUM_PRIMARY_FUNCTIONS*/
#include"example_map.h"
#include"example.h"
zEnum2NameMap_tInfoStateE_map_t[]=
{
{eInfoStateIdle,"eInfoStateIdle"},
{eInfoStateIniting,"eInfoStateIniting"},
{eInfoStateInited,"eInfoStateInited"},
{eInfoStateReady,"eInfoStateReady"},
{eInfoStateActive,"eInfoStateActive"},
{eInfoStateStandby,"eInfoStateStandby"},
{eInfoStateRelease,"eInfoStateRelease"},
};/*InfoStateE_map_t*/
constchar*InfoStateE2Name(dword_te)
{
char*pName=zEnum2Name(e,InfoStateE_map_t,TBL_SIZE(InfoStateE_map_t));
if(pName)returnpName;
return"*NA*";
}
dword_tInfoStateE2Value(char*name,intbAppro)
{
returnzName2Enum(name,InfoStateE_map_t,TBL_SIZE(InfoStateE_map_t),bAppro);
};
intInfoStateEMapShow()
{
returnzEnumMapShow(InfoStateE_map_t,TBL_SIZE(InfoStateE_map_t));
};
p_enum.pl是用了我自己做的lex和yacc库。本来是学习编译原理时的一些实验代码,后来发现它对于文本提取还是很强大,于是有了enum相关的自动生成工具。有兴趣的,可以参考,或者有问题留言。
嗯,还有一点,p_enum.pl不支持enum定义里包含编译控制宏。如果你有这个需求,需要自己修改enum.lex和enum.yacc文件来支持。我非常厌恶编译宏,因此不会做这个更新。
如何设置使用环境的补充说明:
linux环境,perl_zlib建议解压在你的home目录下。然后在你的用户配置文件.bashrc(或是.profile,不同linux略有差别)里面添加zlib的路径。我的配置里是这样的:
exportPATH="$HOME/perl/Debug:$PATH" exportPERL5LIB="$HOME/perl/zLib:$HOME/perl5/lib/perl5" PERL_MB_OPT="--install_base\"$HOME/perl5\"";exportPERL_MB_OPT; PERL_MM_OPT="INSTALL_BASE=$HOME/perl5";exportPERL_MM_OPT;
这当中只有PERL5LIB里的zLib路径是必须的。perl5是我用来装额外的perl库用的,一起贴出来供参考。
windows环境,需要先运行zlib.bat来设置环境变量,然后才能运行p_enum.pl。当然,你还要确认安装了activeperl。