C代碼工具--自動生成enum值和名字映射代碼

這年頭好像繼續作C語言的人很少了,年輕人大多去互聯網和移動應用。確實,那兩個領域如今來錢快,且老是供不該求。就說剛剛在一箇舊同事的微信羣裏,有人剛放出本身有團隊能夠作App幾分鐘,哇塞,好幾我的說有項目,要求加好友私聊。我也想過轉行,惋惜人老珠黃,沒有互聯網或是應用團隊願意接收。估計再過些年,C程序世界裏就只有我這樣的小老頭們繼續自娛自樂了,羨慕死年輕人了!linux

日常工做中,常常要作一些打印,或是日誌。而這裏面,enum類型的數據就不少,若是隻是打印出它的整數值,顯然會讓測試人員很惱火,鬼知道那數字說的是什麼。就算你給他個文檔對着看,也絲絕不能獲得原諒。最後,都得乖乖的把這個enum對應的名字打印出來才能平息。windows

今天說的這個,就是幫忙搞定這個轉換問題的。bash


好比,有這麼個example.h文件:微信

enum InfoStateE{
  eInfoStateIdle,
  eInfoStateIniting,
  eInfoStateInited,
  eInfoStateReady,
  eInfoStateActive,
  eInfoStateStandby,
  eInfoStateRelease,
};

咱們須要個函數,把enum值翻譯成字符串;另外也要個函數,能查找字符串對應的enum值;能夠提供名字的一部分。p_enum.pl就是作這個的,只須要執行:ide

perl p_enum.pl example.h -o:example_map
p_enum.pl接受目錄,通配符,或是多個文件。-o:example_map是指定輸出的文件名。這裏咱們獲得了example_map.h和example_map.c兩個文件:函數

/*
FILE: example_map.h
This file was created at Fri Dec 11 16:40:56 CST 2015

Auto-generated source. Don't change it manually.
Contact with hhao020@gmail.com for bug reporting and supporting.
*/

#ifndef EXAMPLE_MAP
#define EXAMPLE_MAP

#ifdef __cplusplus
    extern "C" {
#endif

#include "zType_Def.h"
extern const char* InfoStateE2Name(dword_t e);
extern dword_t InfoStateE2Value(char* name, int bAppro);
extern int InfoStateEMapShow();

#ifdef __cplusplus
}
#endif

#endif /*EXAMPLE_MAP*/
View Code
/*
FILE: example_map.c
This file was created at Fri Dec 11 16:40:56 CST 2015

Auto-generated source. Don't change it manually.
Contact with hhao020@gmail.com for bug reporting and supporting.
*/

#define _GNU_SOURCE 
#include <string.h>
#include <stdio.h>
#include <stdlib.h>


#include "zAutoCodeApi.h"
#ifndef ENUM_PRIMARY_FUNCTIONS
static char *zEnum2Name(dword_t e, zEnum2NameMap_t arr[], int nSize)
{
  int i;

  for(i=0; i<nSize; i++)
  {
    if(arr[i].e == e) return arr[i].name;
  }
  
  return 0;
}

static int zName2Enum(char* name, zEnum2NameMap_t arr[], int nSize, int bAppro)
{
  int i;

  for(i=0; i<nSize; i++)
  {
    if(bAppro)
    {
      if(strcasestr(arr[i].name, name)) return arr[i].e;
    }
    else
    {
      if(!strcmp(arr[i].name, name)) return arr[i].e;
    }
  }
  
  return -1;
}

static int zEnumMapShow(zEnum2NameMap_t arr[], int nSize)
{
  int i;
  for(i=0; i<nSize; i++)
  {
    printf("%3d %d-> %s \n", i, arr[i].e, arr[i].name);
  }
  
  return 0;
}
#endif /*ENUM_PRIMARY_FUNCTIONS*/

#include "example_map.h"



#include "example.h"

zEnum2NameMap_t InfoStateE_map_t[]=
{
  {eInfoStateIdle, "eInfoStateIdle"},
  {eInfoStateIniting, "eInfoStateIniting"},
  {eInfoStateInited, "eInfoStateInited"},
  {eInfoStateReady, "eInfoStateReady"},
  {eInfoStateActive, "eInfoStateActive"},
  {eInfoStateStandby, "eInfoStateStandby"},
  {eInfoStateRelease, "eInfoStateRelease"},
}; /*InfoStateE_map_t*/

const char* InfoStateE2Name(dword_t e)
{
  char* pName = zEnum2Name(e, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
  
  if(pName) return pName;
  return "*NA*";
}

dword_t InfoStateE2Value(char* name, int bAppro)
{
  return zName2Enum(name, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t), bAppro);
};

int InfoStateEMapShow()
{
  return zEnumMapShow(InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
};
View Code

p_enum.pl是用了我本身作的lex和yacc庫。原本是學習編譯原理時的一些實驗代碼,後來發現它對於文本提取仍是很強大,因而有了enum相關的自動生成工具。有興趣的,能夠參考,或者有問題留言。工具

嗯,還有一點,p_enum.pl不支持enum定義裏包含編譯控制宏。若是你有這個需求,須要本身修改enum.lex和enum.yacc文件來支持。我很是厭惡編譯宏,所以不會作這個更新。學習

如何設置使用環境的補充說明:
linux環境,perl_zlib建議解壓在你的home目錄下。而後在你的用戶配置文件.bashrc(或是.profile,不一樣linux略有差異)裏面添加zlib的路徑。個人配置裏是這樣的:
export PATH="$HOME/perl/Debug:$PATH"
export PERL5LIB="$HOME/perl/zLib:$HOME/perl5/lib/perl5"
PERL_MB_OPT="--install_base \"$HOME/perl5\""; export PERL_MB_OPT;
PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"; export PERL_MM_OPT;
這當中只有PERL5LIB裏的zLib路徑是必須的。perl5是我用來裝額外的perl庫用的,一塊兒貼出來供參考。測試

windows環境,須要先運行zlib.bat來設置環境變量,而後才能運行p_enum.pl。固然,你還要確認安裝了activeperl。spa

相關文章
相關標籤/搜索