/**************************************************************************/ /* GENERR - program for error messages generation */ /* (c) Petr Peringer 1991-1997 */ /**************************************************************************/ #include #include #include #include /**************************************************************************/ #define MAXERR 1000 #define MAXIDLEN 32 #define MAXLINELEN 255 enum Boolean { FALSE, TRUE }; char tittle[] = "GENERR - error messages generator (c)PerPet 1991-1997 \n"; char help[] = "\n" " usage: GENERR InputFileName \n" "\n" " Input file format:\n" "\n" " ErrorFunctionName(ErrorEnumName)\n" " ErrorName0 Text of error message 0\n" " ErrorName1 Text of error message 1\n" " ...\n" "\n" " Comment line starts with nonletter character\n" " Name must be an C-identifier!\n" "\n" " Output files are:\n" " InputFileName.h\n" " InputFileName.cc\n" ; struct tabitem { char *ErrId; char *ErrMsg; }; typedef struct { struct tabitem Table[MAXERR]; unsigned NumErr; } TABLE; TABLE *tab; char funcname[MAXIDLEN+1]; char enumname[MAXIDLEN+1]; FILE *inf; char fname[512]; /* module file name */ char modfname[80]; /* module file name */ char headfname[80]; /* header file name */ char line[MAXLINELEN+2]; char *sp = line; int lineno=0; /**************************************************************************/ /**************************************************************************/ /* Generated by program GENERR */ enum ErrEnum { /* 0 */ NoError, /* 1 */ ErrBadArguments, /* 2 */ ErrBadFile, /* 3 */ ErrBadHeader, /* 4 */ ErrBadIdentifier, /* 5 */ ErrCantOpenIn, /* 6 */ ErrCantOpenOut, /* 7 */ ErrDuplicateId, /* 8 */ ErrIdTooLong, /* 9 */ ErrLineTooLong, /* 10 */ ErrNoIdentifier, /* 11 */ ErrNoMemory, /* 12 */ ErrTooManyMsg, }; static char _Errors[] = { /* 0 */ "\0" /* 1 */ "Bad arguments\0" /* 2 */ "File have not a header\0" /* 3 */ "Error in head line\0" /* 4 */ "Bad identifier\0" /* 5 */ "Can't open input file\0" /* 6 */ "Can't open output file\0" /* 7 */ "Duplicate identifier\0" /* 8 */ "Identifier too long\0" /* 9 */ "Line too long\0" /* 10 */ "Identifier expected\0" /* 11 */ "Out of memory\0" /* 12 */ "Too many messages in input file\0" }; char *ErrMsg(enum ErrEnum N) { char *p = _Errors; while( N-- > 0 ) while( *p++ != '\0' ); return p; }; /**************************************************************************/ /**************************************************************************/ void error( enum ErrEnum N ) { printf("Error#%d: %s\n",N,ErrMsg(N)); if (N==ErrBadArguments) printf(help); exit(N); } /**************************************************************************/ void InitTable(TABLE **t) { (*t) = malloc(sizeof(TABLE)); if( *t == NULL ) error(ErrNoMemory); (*t)->NumErr = 0; } FILE *OpenInputFile(char *name) { FILE *inf; char *s; strncpy(fname,name,500); /* save name for future use */ inf = fopen(name,"rt"); if (inf==NULL) error(ErrCantOpenIn); strcpy(modfname,name); for(s=modfname; *s!='\0'&& *s!='.'; s++); strcpy(s,".cc"); strcpy(headfname,name); for(s=headfname; *s!='\0'&& *s!='.'; s++); strcpy(s,".h"); return inf; } FILE *OpenOutputFile(char *name) { FILE *outf; outf = fopen(name,"wt"); if (outf==NULL) error(ErrCantOpenOut); return outf; } /**************************************************************************/ int GetLine(FILE *inf) /* read one input line to buffer */ { int l; do{ if (fgets(line,MAXLINELEN,inf) == NULL) return FALSE; ++lineno; #ifdef PRINT_LINE_NUMBERS if(lineno==1) printf("Line start "); printf("\b\b\b\b\b\b%-5d ",lineno); #endif l = strlen(line) - 1; if (line[l] != '\n') { if(!feof(inf)) error(ErrLineTooLong); //### } line[l] = '\0'; } while ( !(isalpha(line[0])||line[0]=='_') || line[0]=='\0'); sp = line; return TRUE; } /**************************************************************************/ void SkipBlanks(void) { while( *sp==' ' || *sp=='\t' ) sp++; } int GetChar(void) /***** get character *****/ { return (*sp=='\0')? *sp : *sp++ ; } void GetIdent(char *sptr) /***** get an identifier *****/ { int i=0; if (!(isalpha(*sp)||*sp=='_')) error(ErrBadIdentifier); while(i<=MAXIDLEN && (isalnum(*sp)||*sp=='_')) sptr[i++] = *sp++; if (i>MAXIDLEN) error(ErrIdTooLong); if (i==0) error(ErrBadIdentifier); sptr[i] = '\0'; } char *MyStrDup(char *sp) { char *s = strdup(sp); if (s==NULL) error(ErrNoMemory); /* with test */ return s; } char *GetErrId(void) { char s[MAXIDLEN+1]; GetIdent(s); return MyStrDup(s); } char *GetErrMsg(void) { SkipBlanks(); return MyStrDup(sp); } /**************************************************************************/ /* G E T */ /**************************************************************************/ void GetHeader(FILE *inf,char*funcname, char*enumname) { if (!GetLine(inf)) error(ErrBadFile); GetIdent(funcname); SkipBlanks(); if (GetChar()!='(') error(ErrBadHeader); SkipBlanks(); GetIdent(enumname); SkipBlanks(); if (GetChar()!=')') error(ErrBadHeader); } int CheckUniq(TABLE *t) { int i; char *s = t->Table[t->NumErr].ErrId; for( i=0; iNumErr; i++ ) if (strcmp(t->Table[i].ErrId,s)==0) return FALSE; return TRUE; /* unique identifier */ } void GetTable(FILE *inf, TABLE *t) { while (GetLine(inf)) { t->Table[t->NumErr].ErrId = GetErrId(); t->Table[t->NumErr].ErrMsg = GetErrMsg(); if (!CheckUniq(t)) error(ErrDuplicateId); if (++t->NumErr>MAXERR) error(ErrTooManyMsg); } } /**************************************************************************/ /* G E N E R */ /**************************************************************************/ void GenEnum(FILE *outf, TABLE *t) { int i; fprintf(outf,"enum %s {\n",enumname); for( i=0 ; i<(*t).NumErr ; i++ ) fprintf(outf,"/* %d */ %s,\n",i,(*t).Table[i].ErrId); fprintf(outf,"};\n\n"); } void GenMessages(FILE *outf, TABLE *t) { int i; fprintf(outf,"static char _Errors[] = {\n"); for( i=0 ; i<(*t).NumErr ; i++ ) fprintf(outf,"/* %d */ \"%s\\0\" \n",i,(*t).Table[i].ErrMsg); fprintf(outf,"};\n\n"); } void GenErrFun(FILE *outf) { fprintf(outf,"char *%s(enum %s N)\n",funcname,enumname); fprintf(outf,"{\n"); fprintf(outf," char *p = _Errors;\n"); fprintf(outf," int i = N;\n"); fprintf(outf," while( i-- > 0 )\n"); fprintf(outf," while( *p++ != '\\0' );\n"); fprintf(outf," return p;\n"); fprintf(outf,"};\n"); } /**************************************************************************/ void GenerModule(TABLE *t) { FILE *outf = OpenOutputFile(modfname); fprintf(outf,"//\n// %s\n", modfname); fprintf(outf,"//\n//\n//\n//\n"); fprintf(outf,"/* Generated from file '%s' by program GENERR */\n\n", fname); fprintf(outf,"#include \"%s\"\n\n",headfname); GenMessages(outf,t); GenErrFun(outf); fclose(outf); } /**************************************************************************/ void GenerHeader(TABLE *t) { FILE *outf = OpenOutputFile(headfname); fprintf(outf,"//\n// %s\n", headfname); fprintf(outf,"//\n//\n//\n//\n"); fprintf(outf,"/* Generated from file '%s' by program GENERR */\n\n", fname); GenEnum(outf,t); fprintf(outf,"extern char *%s(enum %s N);\n",funcname,enumname); fprintf(outf,"\n"); fclose(outf); } /**************************************************************************/ /* M A I N */ /**************************************************************************/ int main( int argc, char *argv[]) { printf(tittle); if (argc!=2) error(ErrBadArguments); inf = OpenInputFile(argv[1]); InitTable(&tab); GetHeader(inf,funcname,enumname); /* cte 1 radek - hlavicku */ GetTable(inf,tab); /* cte chybova hlaseni do tabulky */ GenerModule(tab); /* generuje vyst. soubor .C */ GenerHeader(tab); /* generuje vyst. soubor .H */ printf("\nNumber of messages = %d \n",tab->NumErr); return(0); /* OK */ } /**************************************************************************/