The C language automatically generates the enum value and name mapping code

  • 2020-05-07 20:01:38
  • OfStack

It seems that not many people continue to do C these days, and most young people go to the Internet and mobile apps. Indeed, those two areas are now cash-rich and always in short supply. Just said that in the WeChat group of an old colleague, someone just put out that he has a team to do App for a few minutes, wow, several people said that there is a project, asked to add friends private chat. I thought about changing careers, too, but I was too old to have an Internet or an app team willing to take it. In a few more years, the world of C programs will be filled with little old men like me who will continue to entertain themselves and envy the young.

At work, you often need to do some printing, or log. In this case, enum has a lot of data, and if you just print out the integer value of it, it will obviously annoy the tester, who knows what that number is talking about. Even if you give him a document to look at, there is no excuse. Finally, the enum name has to be obediently printed out to calm down.

That's what helped us with this conversion problem.

For example, there is an example.h file:


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

We need a function to translate enum into a string; Also a function to find the enum value of the string; You can provide 1 part of the name. p_enum.pl does this, just execute:

perl p_enum.pl example.h -o:example_map
p_enum.pl accepts directories, wildcards, or multiple files. -o :example_map is the name of the specified output. Here we get example_map.h and 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*/


/*
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));
};

p_enum.pl is using the lex and yacc libraries I made myself. Originally, I learned some experimental code when compiling principles, but later I found that it was still very powerful for text extraction, so I had enum related automatic generation tools. Interested, can refer to, or there is a question message.

Well, one more thing, p_enum.pl does not support the inclusion of compilation control macros in the enum definition. If you have this requirement, you need to modify the enum.lex and enum.yacc files to support it. I hate compiling macros so much that I won't do this update.

Supplementary instructions on how to set up the usage environment:
linux environment, perl_zlib recommended to unzip in your home directory. Then add the zlib path to your user profile.bashrc (or.profile, slightly different from linux). My configuration looks like this:


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;

Only the zLib path in PERL5LIB is required. perl5 is for the extra perl library, one post for reference.

windows environment, you need to run zlib.bat to set the environment variables before you can run p_enum.pl. Of course, make sure you have activeperl installed.


Related articles: