/* mkenum.c - turns a list of strings to a C enum */ /* PUBLIC DOMAIN - May 2007 - Jon Mayo */ #include #include #include #include #include #define MAX_IDENTIFIER 128 /* identifier max length of 127 characters */ #define MAX_STRING 512 /* string literal max length of 511 characters */ #define DEF_PREFIX "E_" /* default prefix on identifiers */ #define DEF_ENUM_NAME "myenum" /* default name of enum */ #define DEF_TYPEDEF_NAME NULL /* disabled */ #define DEF_STRTAB "myenum_tab" /* default name of string table */ #define DEF_STRTAB_STATIC 1 /* enable to make string table static */ struct entry { char *data; struct entry *next; }; struct entry *new_entry(const char *data) { struct entry *ret; unsigned len; assert(data!=NULL); ret=malloc(sizeof *ret); assert(ret!=NULL); len=strlen(data); ret->data=malloc(len+1); assert(ret->data!=NULL); ret->next=0; memcpy(ret->data, data, len+1); return ret; } int main() { struct entry *head, **prev; /* list that is used for string table */ const char *prefix = DEF_PREFIX; /* prefix to put on each identifier */ const char *enum_name = DEF_ENUM_NAME; /* must define */ const char *typedef_name = DEF_TYPEDEF_NAME; /* define to have typedef */ const char *strtab_name = DEF_STRTAB; /* define to have a table of strings */ int strtable_static = DEF_STRTAB_STATIC; /* 0/1 to turn on static */ char buf[MAX_IDENTIFIER]; /* input buffer for reading lines */ int e_cnt; /* count the enums as we read them */ if(typedef_name) { printf("typedef "); } printf("enum "); if(enum_name) { printf("%s ", enum_name); } printf("{\n"); prev=&head; e_cnt=0; while(fgets(buf, sizeof buf, stdin)) { unsigned i; /* TODO: handle condition when line is too large for input buffer */ if(strtab_name) { *prev=new_entry(buf); /* worry about parsing and escaping later */ prev=&(*prev)->next; } if(e_cnt!=0) { printf(",\n"); } for(i=0;buf[i];i++) { char ch = buf[i]; if(isalpha(ch)) { buf[i]=toupper(buf[i]); } else if(isdigit(ch)) { /* do nothing */ } else if(ch=='\n' || ch=='\r') { buf[i]=0; /* trim newline or CR characters */ } else { buf[i]='_'; /* anything "funny" is an underscore */ } } printf("\t%s%s", prefix, buf); e_cnt++; } printf("\n}"); if(typedef_name) { printf(" %s;\n", typedef_name); } else { printf(";\n"); } if(strtab_name) { struct entry *curr, *old; unsigned i, o; /* input index and output length */ if(strtable_static) { printf("static "); } printf("int %s[] = {\n", strtab_name); for(curr=head;curr;) { char buf[MAX_STRING]; assert(curr->data!=NULL); for(i=0,o=0;curr->data[i];i++) { char ch; switch(ch=curr->data[i]) { case '\r': case '\n': break; /* swallow newline or carriage return*/ case '\\': buf[o++]='\\'; buf[o++]='\\'; break; case '"': buf[o++]='\\'; buf[o++]='"'; break; case '\b': buf[o++]='\\'; buf[o++]='b'; break; case '\f': buf[o++]='\\'; buf[o++]='f'; break; case '\a': buf[o++]='\\'; buf[o++]='a'; break; case '\t': buf[o++]='\\'; buf[o++]='t'; break; case '\v': buf[o++]='\\'; buf[o++]='v'; break; default: if(!isprint(ch)) { buf[o++]='*'; /* TODO: octal encode */ } else { buf[o++]=ch; } } assert(onext) { printf(","); } printf("\n"); old=curr; curr=curr->next; free(old->data); free(old); } printf("};\n"); } return 0; }