/**************************************************************************/
/* GENERR - program for error messages generation */
/* (c) Petr Peringer 1991-1997 */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/**************************************************************************/
#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; i<t->NumErr; 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 */
}
/**************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1