429 lines
9.6 KiB
C
429 lines
9.6 KiB
C
/* $NetBSD: main.c,v 1.17 2009/03/18 10:22:44 cegger Exp $ */
|
|
|
|
/*
|
|
* TODO:
|
|
* rewrite the command line stuff altogether - it's kludged beyond
|
|
* belief (as is the rest of the code...)
|
|
*
|
|
* DISCLAIMER DISCLAIMER DISCLAIMER
|
|
* This code is such a kludge that I don't want to put my name on it.
|
|
* It was a ridiculously fast hack and needs rewriting.
|
|
* However it does work...
|
|
*/
|
|
|
|
#include <sys/cdefs.h>
|
|
__KERNEL_RCSID(0, "$NetBSD: main.c,v 1.17 2009/03/18 10:22:44 cegger Exp $");
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <strings.h>
|
|
#include <time.h>
|
|
#include "malloc.h"
|
|
#include "debug.h"
|
|
#include "main.h"
|
|
#include "procs.h"
|
|
|
|
int debug[128];
|
|
|
|
int lineno = 1;
|
|
|
|
FILE *statefile, *actfile, *eventfile_h, *statevalfile;
|
|
FILE *infile, *astringfile;
|
|
char *Transfilename;
|
|
char *astringfile_name = DEBUGFILE;
|
|
char *actfile_name = ACTFILE;
|
|
char *statefile_name = STATEFILE;
|
|
char *statevalfile_name = STATEVALFILE;
|
|
char *eventfile_h_name = EVENTFILE_H;
|
|
int print_trans = 0;
|
|
int print_protoerrs = 0;
|
|
int pgoption = 0;
|
|
char kerneldirname[50] = "\0";
|
|
|
|
char protocol[50];
|
|
|
|
char *synonyms[] = {
|
|
"EVENT",
|
|
"PCB",
|
|
0
|
|
};
|
|
|
|
void FakeFilename();
|
|
extern void llparse();
|
|
extern void initsets();
|
|
extern void init_alloc();
|
|
extern void dump_predtable();
|
|
extern void printprotoerrs();
|
|
|
|
void
|
|
usage(char *a)
|
|
{
|
|
fprintf(stderr,
|
|
"usage: %s <transition file> {-D<debug options>} <other options>\n",
|
|
a);
|
|
fprintf(stderr, "\t<other options> is any combination of:\n");
|
|
fprintf(stderr, "\t\t-A<action file name>\n");
|
|
fprintf(stderr, "\t\t-E<event file name>\n");
|
|
fprintf(stderr, "\t\t-S<state file name>\n");
|
|
fprintf(stderr, "\t\t-I<initial values file name>\n");
|
|
fprintf(stderr, "\t\t-X<debugging file name>\n");
|
|
fprintf(stderr, "\t\t-K<directory name>\n");
|
|
fprintf(stderr,
|
|
"\tThese names do NOT include the suffixes (.c, .h)\n");
|
|
fprintf(stderr,
|
|
"\t\t-D<options> to turn on debug options for xebec itself\n");
|
|
fprintf(stderr, "\t-<nn> for levels of debugging output\n");
|
|
fprintf(stderr, "\t\t<nn> ranges from 1 to 3, 1 is default(everything)\n");
|
|
fprintf(stderr, "\t\t-T to print transitions\n");
|
|
fprintf(stderr, "\t\t-e to print list of combinations of\n");
|
|
fprintf(stderr, "\t\t\t [event,old_state] that produce protocol errors\n");
|
|
fprintf(stderr, "\t\t-g include profiling code in driver\n");
|
|
Exit(-1);
|
|
}
|
|
|
|
void
|
|
openfiles(register char *proto)
|
|
{
|
|
register char *junk;
|
|
register int lenp = strlen(proto);
|
|
|
|
IFDEBUG(b)
|
|
fprintf(OUT, "openfiles %s\n",proto);
|
|
ENDDEBUG
|
|
|
|
#define DOIT(X)\
|
|
/* GAG */\
|
|
junk = Malloc( 2 + lenp + strlen(X ## _name) );\
|
|
(void) sprintf(junk, "%s_", proto);\
|
|
X ## _name = strcat(junk, X ## _name);\
|
|
X = fopen(X ## _name, "w");\
|
|
if((X)==(FILE *)0)\
|
|
{ fprintf(stderr,"Open failed: %s\n", "X"); Exit(-1); }\
|
|
fprintf(X, "/* %cHeader%c */\n",'$', '$' );\
|
|
fprintf(X, "/* %cSource%c */\n",'$', '$' );
|
|
|
|
DOIT(eventfile_h);
|
|
|
|
IFDEBUG(X)
|
|
#ifdef DEBUG
|
|
DOIT(astringfile);
|
|
#endif /* DEBUG */
|
|
fprintf(astringfile,
|
|
"#ifndef _NFILE\n#include <stdio.h>\n#endif /* _NFILE */\n" );
|
|
ENDDEBUG
|
|
|
|
DOIT(statevalfile);
|
|
DOIT(statefile);
|
|
DOIT(actfile);
|
|
fprintf(actfile,
|
|
"#ifndef lint\nstatic char *rcsid = \"%cHeader%c\";\n#endif /* lint */\n",
|
|
'$', '$');
|
|
|
|
if(pgoption)
|
|
putdriver(actfile, 15);
|
|
else
|
|
putdriver(actfile, 14);
|
|
|
|
FakeFilename(actfile, Transfilename, lineno);
|
|
putdriver(actfile, 1);
|
|
FakeFilename(actfile, Transfilename, lineno);
|
|
putdriver(actfile, 12);
|
|
fprintf(actfile, "#include \"%s%s\"\n", kerneldirname, statevalfile_name);
|
|
FakeFilename(actfile, Transfilename, lineno);
|
|
putdriver(actfile, 2);
|
|
|
|
initsets(eventfile_h, statefile);
|
|
}
|
|
|
|
void
|
|
includecode(FILE *file, register char *f)
|
|
{
|
|
register int count=1;
|
|
static char o='{';
|
|
static char c='}';
|
|
register char *g;
|
|
|
|
IFDEBUG(a)
|
|
fprintf(stdout, "including: %s, f=%p", f,f);
|
|
ENDDEBUG
|
|
g = ++f;
|
|
while(count>0) {
|
|
if(*g == o) count++;
|
|
if(*g == c) count--;
|
|
g++;
|
|
}
|
|
*(--g) = '\0';
|
|
IFDEBUG(a)
|
|
fprintf(stdout, "derived: %s", f);
|
|
ENDDEBUG
|
|
fprintf(file, "%s", f);
|
|
FakeFilename(file, Transfilename, lineno);
|
|
}
|
|
|
|
void
|
|
putincludes(void)
|
|
{
|
|
FakeFilename(actfile, Transfilename, lineno);
|
|
fprintf(actfile, "\n#include \"%s%s\"\n", kerneldirname, eventfile_h_name);
|
|
IFDEBUG(X)
|
|
if( !debug['K'] )
|
|
fprintf(actfile, "\n#include \"%s\"\n", astringfile_name);
|
|
/* not in kernel mode */
|
|
ENDDEBUG
|
|
FakeFilename(actfile, Transfilename, lineno);
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
register int i = 2;
|
|
extern char *strcpy();
|
|
int start, finish;
|
|
extern int FirstEventAttribute;
|
|
extern int Nevents, Nstates;
|
|
|
|
start = time(0);
|
|
if(argc < 2) {
|
|
usage(argv[0]);
|
|
}
|
|
IFDEBUG(a)
|
|
fprintf(stdout, "infile = %s\n",argv[1]);
|
|
ENDDEBUG
|
|
Transfilename = argv[1];
|
|
infile = fopen(argv[1], "r");
|
|
|
|
if(argc > 2) while(i < argc) {
|
|
register int j=0;
|
|
char c;
|
|
char *name;
|
|
|
|
if(argv[i][j] == '-') j++;
|
|
switch(c = argv[i][j]) {
|
|
|
|
/* GROT */
|
|
case 'A':
|
|
name = &argv[i][++j];
|
|
actfile_name = Malloc( strlen(name)+4);
|
|
actfile_name = (char *)strcpy(actfile_name,name);
|
|
#ifdef LINT
|
|
name =
|
|
#endif /* LINT */
|
|
strcat(actfile_name, ".c");
|
|
fprintf(stdout, "debugging file is %s\n",actfile_name);
|
|
break;
|
|
case 'K':
|
|
debug[(unsigned char) c]=1;
|
|
fprintf(OUT, "option %c file %s\n",c, &argv[i][j+1]);
|
|
(void) strcpy(kerneldirname,&argv[i][++j]);
|
|
break;
|
|
case 'X':
|
|
debug[(unsigned char) c]=1;
|
|
name = &argv[i][++j];
|
|
astringfile_name = Malloc( strlen(name)+4);
|
|
astringfile_name = (char *)strcpy(astringfile_name,name);
|
|
#ifdef LINT
|
|
name =
|
|
#endif /* LINT */
|
|
strcat(astringfile_name, ".c");
|
|
fprintf(OUT, "option %c, astringfile name %s\n",c, name);
|
|
break;
|
|
case 'E':
|
|
name = &argv[i][++j];
|
|
eventfile_h_name = Malloc( strlen(name)+4);
|
|
eventfile_h_name = (char *)strcpy(eventfile_h_name,name);
|
|
#ifdef LINT
|
|
name =
|
|
#endif /* LINT */
|
|
strcat(eventfile_h_name, ".h");
|
|
fprintf(stdout, "event files is %s\n",eventfile_h_name);
|
|
break;
|
|
case 'I':
|
|
name = &argv[i][++j];
|
|
statevalfile_name = Malloc( strlen(name)+4 );
|
|
statevalfile_name = (char *)strcpy(statevalfile_name,name);
|
|
#ifdef LINT
|
|
name =
|
|
#endif /* LINT */
|
|
strcat(statevalfile_name, ".init");
|
|
fprintf(stdout, "state table initial values file is %s\n",statevalfile_name);
|
|
break;
|
|
case 'S':
|
|
name = &argv[i][++j];
|
|
statefile_name = Malloc( strlen(name)+4);
|
|
statefile_name = (char *)strcpy(statefile_name,name);
|
|
#ifdef LINT
|
|
name =
|
|
#endif /* LINT */
|
|
strcat(statefile_name, ".h");
|
|
fprintf(stdout, "state file is %s\n",statefile_name);
|
|
break;
|
|
/* END GROT */
|
|
case '1':
|
|
case '2':
|
|
case '3':
|
|
debug['X']= (int)argv[i][j] - (int) '0';
|
|
fprintf(OUT, "value of debug['X'] is 0x%x,%d\n", debug['X'],
|
|
debug['X']);
|
|
break;
|
|
case 'D':
|
|
while((c = argv[i][++j])) {
|
|
if(c == 'X') {
|
|
fprintf(OUT, "debugging on");
|
|
if(debug['X']) fprintf(OUT,
|
|
" - overrides any -%d flags used\n", debug['X']);
|
|
}
|
|
debug[(unsigned char) c]=1;
|
|
fprintf(OUT, "debug %c\n",c);
|
|
}
|
|
break;
|
|
case 'g':
|
|
pgoption = 1;
|
|
fprintf(stdout, "Profiling\n");
|
|
break;
|
|
case 'e':
|
|
print_protoerrs = 1;
|
|
fprintf(stdout, "Protocol error table:\n");
|
|
break;
|
|
|
|
case 'T':
|
|
print_trans = 1;
|
|
fprintf(stdout, "Transitions:\n");
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
break;
|
|
}
|
|
i++;
|
|
}
|
|
if(kerneldirname[0]) {
|
|
char *c;
|
|
#ifdef notdef
|
|
if(debug['X']) {
|
|
fprintf(OUT, "Option K overrides option X\n");
|
|
debug['X'] = 0;
|
|
}
|
|
#endif /* notdef */
|
|
if(strlen(kerneldirname)<1) {
|
|
fprintf(OUT, "K option: dir name too short!\n");
|
|
exit(1);
|
|
}
|
|
/* add ../name/ */
|
|
c = (char *) Malloc(strlen(kerneldirname)+6) ;
|
|
if(c <= (char *)0) {
|
|
fprintf(OUT, "Cannot allocate %d bytes for kerneldirname\n",
|
|
strlen(kerneldirname + 6) );
|
|
fprintf(OUT, "kerneldirname is %s\n", kerneldirname );
|
|
exit(1);
|
|
}
|
|
*c = '.';
|
|
*(c+1) = '.';
|
|
*(c+2) = '/';
|
|
(void) strcat(c, kerneldirname);
|
|
(void) strcat(c, "/\0");
|
|
strcpy(kerneldirname, c);
|
|
}
|
|
|
|
init_alloc();
|
|
|
|
(void) llparse();
|
|
|
|
/* {{ */
|
|
if( !FirstEventAttribute )
|
|
fprintf(eventfile_h, "\t}ev_union;\n");
|
|
fprintf(eventfile_h, "};/* end struct event */\n");
|
|
fprintf(eventfile_h, "\n#define %s_NEVENTS 0x%x\n", protocol, Nevents);
|
|
fprintf(eventfile_h,
|
|
"\n#define ATTR(X)ev_union.%s ## X ## \n",EV_PREFIX);
|
|
(void) fclose(eventfile_h);
|
|
|
|
/* {{ */ fprintf(actfile, "\t}\nreturn 0;\n}\n"); /* end switch; end action() */
|
|
dump_predtable(actfile);
|
|
|
|
putdriver(actfile, 3);
|
|
IFDEBUG(X)
|
|
if(!debug['K'])
|
|
putdriver(actfile, 4);
|
|
ENDDEBUG
|
|
putdriver(actfile, 6);
|
|
IFDEBUG(X)
|
|
/*
|
|
putdriver(actfile, 10);
|
|
*/
|
|
if(debug['K']) {
|
|
putdriver(actfile, 11);
|
|
} else {
|
|
switch(debug['X']) {
|
|
case 1:
|
|
default:
|
|
putdriver(actfile, 7);
|
|
break;
|
|
case 2:
|
|
putdriver(actfile, 13);
|
|
break;
|
|
case 3:
|
|
break;
|
|
}
|
|
}
|
|
ENDDEBUG
|
|
putdriver(actfile, 8);
|
|
(void) fclose(actfile);
|
|
IFDEBUG(X)
|
|
/* { */
|
|
fprintf(astringfile, "};\n");
|
|
(void) fclose(astringfile);
|
|
ENDDEBUG
|
|
|
|
(void) fclose(statevalfile);
|
|
|
|
fprintf(statefile, "\n#define %s_NSTATES 0x%x\n", protocol, Nstates);
|
|
(void) fclose(statefile);
|
|
|
|
finish = time(0);
|
|
fprintf(stdout, "%d seconds\n", finish - start);
|
|
if( print_protoerrs )
|
|
printprotoerrs();
|
|
|
|
exit(0);
|
|
}
|
|
|
|
int transno = 0;
|
|
|
|
void
|
|
Exit(int n)
|
|
{
|
|
fprintf(stderr, "Error at line %d\n",lineno);
|
|
if(transno) fprintf(stderr, "Transition number %d\n",transno);
|
|
(void) fflush(stdout);
|
|
(void) fflush(statefile);
|
|
(void) fflush(eventfile_h);
|
|
(void) fflush(actfile);
|
|
exit(n);
|
|
}
|
|
|
|
#if 0
|
|
syntax(void)
|
|
{
|
|
static char *synt[] = {
|
|
"*PROTOCOL <string>\n",
|
|
"*PCB <string> <optional: SYNONYM synonymstring>\n",
|
|
"<optional: *INCLUDE {\n<C source>\n} >\n",
|
|
"*STATES <string>\n",
|
|
"*EVENTS <string>\n",
|
|
"*TRANSITIONS <string>\n",
|
|
};
|
|
}
|
|
#endif
|
|
|
|
void
|
|
FakeFilename(FILE *outfile, char *name, int l)
|
|
{
|
|
#if 0
|
|
doesn't work
|
|
fprintf(outfile, "\n\n\n\n# line %d \"%s\"\n", l, name);
|
|
#else
|
|
(void)outfile;
|
|
(void)name;
|
|
(void)l;
|
|
#endif
|
|
}
|