1/*	$NetBSD: main.c,v 1.16 2009/03/14 21:04:25 dsl Exp $	*/
2
3/*
4 * TODO:
5 * rewrite the command line stuff altogether - it's kludged beyond
6 * belief (as is the rest of the code...)
7 *
8 * DISCLAIMER DISCLAIMER DISCLAIMER
9 * This code is such a kludge that I don't want to put my name on it.
10 * It was a ridiculously fast hack and needs rewriting.
11 * However it does work...
12 */
13
14#include <sys/cdefs.h>
15__KERNEL_RCSID(0, "$NetBSD: main.c,v 1.16 2009/03/14 21:04:25 dsl Exp $");
16
17#include <stdlib.h>
18#include <stdio.h>
19#include <strings.h>
20#include <time.h>
21#include "malloc.h"
22#include "debug.h"
23#include "main.h"
24#include "procs.h"
25
26int	debug[128];
27
28int lineno = 1;
29
30FILE *statefile, *actfile, *eventfile_h, *statevalfile;
31FILE *infile, *astringfile;
32char *Transfilename;
33char *astringfile_name = DEBUGFILE;
34char *actfile_name = ACTFILE;
35char *statefile_name = STATEFILE;
36char *statevalfile_name = STATEVALFILE;
37char *eventfile_h_name = EVENTFILE_H;
38int print_trans = 0;
39int print_protoerrs = 0;
40int pgoption = 0;
41char kerneldirname[50] = "\0";
42
43char protocol[50];
44
45char *synonyms[] = {
46	"EVENT",
47	"PCB",
48	0
49};
50
51void FakeFilename();
52extern void llparse();
53extern void initsets();
54extern void init_alloc();
55extern void dump_predtable();
56extern void printprotoerrs();
57
58void
59usage(char *a)
60{
61	fprintf(stderr,
62	"usage: %s <transition file> {-D<debug options>} <other options>\n",
63		a);
64	fprintf(stderr, "\t<other options> is any combination of:\n");
65	fprintf(stderr, "\t\t-A<action file name>\n");
66	fprintf(stderr, "\t\t-E<event file name>\n");
67	fprintf(stderr, "\t\t-S<state file name>\n");
68	fprintf(stderr, "\t\t-I<initial values file name>\n");
69	fprintf(stderr, "\t\t-X<debugging file name>\n");
70	fprintf(stderr, "\t\t-K<directory name>\n");
71	fprintf(stderr,
72	"\tThese names do NOT include the suffixes (.c, .h)\n");
73	fprintf(stderr,
74	"\t\t-D<options> to turn on debug options for xebec itself\n");
75	fprintf(stderr, "\t-<nn> for levels of debugging output\n");
76	fprintf(stderr, "\t\t<nn> ranges from 1 to 3, 1 is default(everything)\n");
77	fprintf(stderr, "\t\t-T to print transitions\n");
78	fprintf(stderr, "\t\t-e to print list of combinations of\n");
79	fprintf(stderr, "\t\t\t [event,old_state] that produce protocol errors\n");
80	fprintf(stderr, "\t\t-g include profiling code in driver\n");
81	Exit(-1);
82}
83
84void
85openfiles(register char *proto)
86{
87	register char *junk;
88	register int lenp = strlen(proto);
89
90	IFDEBUG(b)
91		fprintf(OUT, "openfiles %s\n",proto);
92	ENDDEBUG
93
94#define DOIT(X)\
95	/* GAG */\
96	junk = Malloc( 2 + lenp + strlen(X ## _name) );\
97	(void) sprintf(junk, "%s_", proto);\
98	X ## _name = strcat(junk, X ## _name);\
99	X = fopen(X ## _name, "w");\
100	if((X)==(FILE *)0)\
101	{ fprintf(stderr,"Open failed: %s\n", "X"); Exit(-1); }\
102	fprintf(X, "/* %cHeader%c */\n",'$', '$' );\
103	fprintf(X, "/* %cSource%c */\n",'$', '$' );
104
105	DOIT(eventfile_h);
106
107	IFDEBUG(X)
108#ifdef DEBUG
109		DOIT(astringfile);
110#endif /* DEBUG */
111		fprintf(astringfile,
112				"#ifndef _NFILE\n#include <stdio.h>\n#endif /* _NFILE */\n" );
113	ENDDEBUG
114
115	DOIT(statevalfile);
116	DOIT(statefile);
117	DOIT(actfile);
118	fprintf(actfile,
119		"#ifndef lint\nstatic char *rcsid = \"%cHeader%c\";\n#endif /* lint */\n",
120		'$', '$');
121
122	if(pgoption)
123		putdriver(actfile, 15);
124	else
125		putdriver(actfile, 14);
126
127	FakeFilename(actfile, Transfilename, lineno);
128	putdriver(actfile, 1);
129	FakeFilename(actfile, Transfilename, lineno);
130	putdriver(actfile, 12);
131	fprintf(actfile, "#include \"%s%s\"\n", kerneldirname, statevalfile_name);
132	FakeFilename(actfile, Transfilename, lineno);
133	putdriver(actfile, 2);
134
135	initsets(eventfile_h, statefile);
136}
137
138void
139includecode(FILE *file, register char *f)
140{
141	register int count=1;
142	static char o='{';
143	static char c='}';
144	register char *g;
145
146	IFDEBUG(a)
147		fprintf(stdout, "including: %s, f=%p", f,f);
148	ENDDEBUG
149	g = ++f;
150	while(count>0) {
151		if(*g == o) count++;
152		if(*g == c) count--;
153		g++;
154	}
155	*(--g) = '\0';
156	IFDEBUG(a)
157		fprintf(stdout, "derived: %s", f);
158	ENDDEBUG
159	fprintf(file, "%s", f);
160	FakeFilename(file, Transfilename, lineno);
161}
162
163void
164putincludes(void)
165{
166	FakeFilename(actfile, Transfilename, lineno);
167	fprintf(actfile, "\n#include \"%s%s\"\n", kerneldirname, eventfile_h_name);
168	IFDEBUG(X)
169		if( !debug['K'] )
170			fprintf(actfile, "\n#include \"%s\"\n", astringfile_name);
171			/* not in kernel mode */
172	ENDDEBUG
173	FakeFilename(actfile, Transfilename, lineno);
174}
175
176int
177main(int argc, char *argv[])
178{
179	register int i = 2;
180	extern char *strcpy();
181	int start, finish;
182	extern int FirstEventAttribute;
183	extern int Nevents, Nstates;
184
185	start = time(0);
186	if(argc < 2) {
187		usage(argv[0]);
188	}
189	IFDEBUG(a)
190		fprintf(stdout, "infile = %s\n",argv[1]);
191	ENDDEBUG
192	Transfilename = argv[1];
193	infile = fopen(argv[1], "r");
194
195	if(argc > 2) while(i < argc) {
196		register int j=0;
197		char c;
198		char *name;
199
200		if(argv[i][j] == '-') j++;
201		switch(c = argv[i][j]) {
202
203		/* GROT */
204		case 'A':
205			name = &argv[i][++j];
206			actfile_name = Malloc( strlen(name)+4);
207			actfile_name =  (char *)strcpy(actfile_name,name);
208#ifdef LINT
209			name =
210#endif /* LINT */
211			strcat(actfile_name, ".c");
212			fprintf(stdout, "debugging file is %s\n",actfile_name);
213			break;
214		case 'K':
215			debug[(unsigned char) c]=1;
216			fprintf(OUT, "option %c file %s\n",c, &argv[i][j+1]);
217			(void) strcpy(kerneldirname,&argv[i][++j]);
218			break;
219		case 'X':
220			debug[(unsigned char) c]=1;
221			name = &argv[i][++j];
222			astringfile_name = Malloc( strlen(name)+4);
223			astringfile_name =  (char *)strcpy(astringfile_name,name);
224#ifdef LINT
225			name =
226#endif /* LINT */
227			strcat(astringfile_name, ".c");
228			fprintf(OUT, "option %c, astringfile name %s\n",c, name);
229			break;
230		case 'E':
231			name = &argv[i][++j];
232			eventfile_h_name = Malloc( strlen(name)+4);
233			eventfile_h_name =  (char *)strcpy(eventfile_h_name,name);
234#ifdef LINT
235			name =
236#endif /* LINT */
237			strcat(eventfile_h_name, ".h");
238			fprintf(stdout, "event files is %s\n",eventfile_h_name);
239			break;
240		case 'I':
241			name = &argv[i][++j];
242			statevalfile_name = Malloc( strlen(name)+4 );
243			statevalfile_name =  (char *)strcpy(statevalfile_name,name);
244#ifdef LINT
245			name =
246#endif /* LINT */
247			strcat(statevalfile_name, ".init");
248			fprintf(stdout, "state table initial values file is %s\n",statevalfile_name);
249			break;
250		case 'S':
251			name = &argv[i][++j];
252			statefile_name = Malloc( strlen(name)+4);
253			statefile_name =  (char *)strcpy(statefile_name,name);
254#ifdef LINT
255			name =
256#endif /* LINT */
257			strcat(statefile_name, ".h");
258			fprintf(stdout, "state file is %s\n",statefile_name);
259			break;
260		/* END GROT */
261		case '1':
262		case '2':
263		case '3':
264			debug['X']= (int)argv[i][j] - (int) '0';
265			fprintf(OUT, "value of debug['X'] is 0x%x,%d\n", debug['X'],
266				debug['X']);
267			break;
268		case 'D':
269			while((c = argv[i][++j])) {
270				if(c ==  'X') {
271					fprintf(OUT, "debugging on");
272					if(debug['X']) fprintf(OUT,
273						" - overrides any -%d flags used\n", debug['X']);
274				}
275				debug[(unsigned char) c]=1;
276				fprintf(OUT, "debug %c\n",c);
277			}
278			break;
279		case 'g':
280			pgoption = 1;
281			fprintf(stdout, "Profiling\n");
282			break;
283		case 'e':
284			print_protoerrs = 1;
285			fprintf(stdout, "Protocol error table:\n");
286			break;
287
288		case 'T':
289			print_trans = 1;
290			fprintf(stdout, "Transitions:\n");
291			break;
292		default:
293			usage(argv[0]);
294			break;
295		}
296		i++;
297	}
298	if(kerneldirname[0]) {
299		char *c;
300#ifdef notdef
301		if(debug['X']) {
302			fprintf(OUT, "Option K overrides option X\n");
303			debug['X'] = 0;
304		}
305#endif /* notdef */
306		if(strlen(kerneldirname)<1) {
307			fprintf(OUT, "K option: dir name too short!\n");
308			exit(1);
309		}
310		/* add ../name/ */
311		c = (char *) Malloc(strlen(kerneldirname)+6) ;
312		if(c <= (char *)0) {
313			fprintf(OUT, "Cannot allocate %d bytes for kerneldirname\n",
314				strlen(kerneldirname + 6) );
315			fprintf(OUT, "kerneldirname is %s\n", kerneldirname  );
316			exit(1);
317		}
318		*c = '.';
319		*(c+1) = '.';
320		*(c+2) = '/';
321		(void) strcat(c, kerneldirname);
322		(void) strcat(c, "/\0");
323		strcpy(kerneldirname, c);
324	}
325
326	init_alloc();
327
328	(void) llparse();
329
330	/* {{ */
331	if( !FirstEventAttribute )
332		fprintf(eventfile_h, "\t}ev_union;\n");
333	fprintf(eventfile_h, "};/* end struct event */\n");
334	fprintf(eventfile_h, "\n#define %s_NEVENTS 0x%x\n", protocol, Nevents);
335	fprintf(eventfile_h,
336		"\n#define ATTR(X)ev_union.%s ## X ## \n",EV_PREFIX);
337	(void) fclose(eventfile_h);
338
339	/* {{ */ fprintf(actfile, "\t}\nreturn 0;\n}\n"); /* end switch; end action() */
340	dump_predtable(actfile);
341
342	putdriver(actfile, 3);
343	IFDEBUG(X)
344		if(!debug['K'])
345			putdriver(actfile, 4);
346	ENDDEBUG
347	putdriver(actfile, 6);
348	IFDEBUG(X)
349		/*
350		putdriver(actfile, 10);
351		*/
352		if(debug['K']) {
353			putdriver(actfile, 11);
354		} else {
355			switch(debug['X']) {
356			case 1:
357			default:
358				putdriver(actfile, 7);
359				break;
360			case 2:
361				putdriver(actfile, 13);
362				break;
363			case 3:
364				break;
365			}
366		}
367	ENDDEBUG
368	putdriver(actfile, 8);
369	(void) fclose(actfile);
370	IFDEBUG(X)
371		/* { */
372		fprintf(astringfile, "};\n");
373		(void) fclose(astringfile);
374	ENDDEBUG
375
376	(void) fclose(statevalfile);
377
378	fprintf(statefile, "\n#define %s_NSTATES 0x%x\n", protocol, Nstates);
379	(void) fclose(statefile);
380
381	finish = time(0);
382	fprintf(stdout, "%d seconds\n", finish - start);
383	if( print_protoerrs )
384		printprotoerrs();
385
386	exit(0);
387}
388
389int transno = 0;
390
391void
392Exit(int n)
393{
394	fprintf(stderr, "Error at line %d\n",lineno);
395	if(transno) fprintf(stderr, "Transition number %d\n",transno);
396	(void) fflush(stdout);
397	(void) fflush(statefile);
398	(void) fflush(eventfile_h);
399	(void) fflush(actfile);
400	exit(n);
401}
402
403#if 0
404syntax(void)
405{
406	static char *synt[] = {
407		"*PROTOCOL <string>\n",
408		"*PCB <string> <optional: SYNONYM synonymstring>\n",
409		"<optional: *INCLUDE {\n<C source>\n} >\n",
410		"*STATES <string>\n",
411		"*EVENTS <string>\n",
412		"*TRANSITIONS <string>\n",
413	};
414}
415#endif
416
417void
418FakeFilename(FILE *outfile, char *name, int l)
419{
420#if 0
421	doesn't work
422	fprintf(outfile, "\n\n\n\n# line %d \"%s\"\n", l, name);
423#else
424	(void)outfile;
425	(void)name;
426	(void)l;
427#endif
428}
429