1/*	$NetBSD: procs.c,v 1.15 2009/03/18 10:22:44 cegger Exp $	*/
2
3/*
4 * This code is such a kludge that I don't want to put my name on it.
5 * It was a ridiculously fast hack and needs rewriting.
6 * However it does work...
7 */
8
9#include <sys/cdefs.h>
10__KERNEL_RCSID(0, "$NetBSD: procs.c,v 1.15 2009/03/18 10:22:44 cegger Exp $");
11
12#include <stdio.h>
13#include <strings.h>
14#include <unistd.h>
15#include "malloc.h"
16#include "main.h"
17#include "debug.h"
18#include "sets.h"
19#include "procs.h"
20
21struct Predicate {
22	int p_index;
23	int p_transno;
24	char *p_str;
25	struct Predicate *p_next;
26};
27
28struct Stateent {
29	int s_index;
30	int s_newstate;
31	int s_action;
32	struct Stateent *s_next;
33};
34
35struct Object *SameState = (struct Object *)-1;
36int Index = 0;
37int Nstates = 0;
38int Nevents = 0;
39struct Predicate **Predlist;
40struct Stateent **Statelist;
41extern FILE *astringfile;
42
43int predtable();
44
45void
46end_events(void)
47{
48	int size, part;
49	char *addr;
50
51	IFDEBUG(X)
52		/* finish estring[], start astring[] */
53	if(debug['X'] < 2 )
54		fprintf(astringfile, "};\n\nchar *%s_astring[] = {\n\"NULLACTION\",\n",
55			protocol);
56	ENDDEBUG
57	/* NOSTRICT */
58	Statelist =
59	  (struct Stateent **) Malloc((Nstates+1) * sizeof(struct Statent *));
60	/* NOSTRICT */
61	Predlist =
62	  (struct Predicate **)
63	  Malloc ( (((Nevents)<<Eventshift)+Nstates)*sizeof(struct Predicate *) );
64
65	size = (((Nevents)<<Eventshift)+Nstates)*sizeof(struct Predicate *) ;
66	addr = (char *)Predlist;
67	IFDEBUG(N)
68		fprintf(OUT, "Predlist at %p, sbrk %p bzero size %d at addr %p\n",
69		Predlist, sbrk(0), size, addr);
70	ENDDEBUG
71#define BZSIZE 8192
72	while(size) {
73		part = size>BZSIZE?BZSIZE:size;
74	IFDEBUG(N)
75		fprintf(OUT, "bzero addr %p part %d size %d\n",addr, part, size);
76	ENDDEBUG
77		memset(addr, 0, part);
78	IFDEBUG(N)
79		fprintf(OUT, "after bzero addr %p part %d size %d\n",addr, part, size);
80	ENDDEBUG
81		addr += part;
82		size -= part;
83
84	}
85	IFDEBUG(N)
86		fprintf(OUT, "endevents..done \n");
87	ENDDEBUG
88}
89
90int
91acttable(FILE *f,char *actstring)
92{
93	static int Actindex = 0;
94	extern FILE *astringfile;
95	extern int pgoption;
96
97	IFDEBUG(a)
98		fprintf(OUT,"acttable()\n");
99	ENDDEBUG
100	fprintf(f, "case 0x%x: \n", ++Actindex);
101
102	if(pgoption) {
103		fprintf(f, "asm(\" # dummy statement\");\n");
104		fprintf(f, "asm(\"_Xebec_action_%x: \");\n", Actindex );
105		fprintf(f, "asm(\".data\");\n");
106		fprintf(f, "asm(\".globl _Xebec_action_%x# X profiling\");\n",
107			Actindex );
108		fprintf(f, "asm(\".long 0 # X profiling\");\n");
109		fprintf(f, "asm(\".text # X profiling\");\n");
110		fprintf(f, "asm(\"cas r0,r15,r0 # X profiling\");\n");
111		fprintf(f, "asm(\"bali r15,mcount   # X profiling\");\n");
112	}
113
114	fprintf(f, "\t\t%s\n\t\t break;\n", actstring);
115	IFDEBUG(X)
116		if(debug['X']<2) {
117			register int len = 0;
118			fputc('"',astringfile);
119			while(*actstring) {
120				if( *actstring == '\n' ) {
121					fputc('\\', astringfile);
122					len++;
123					fputc('n', astringfile);
124				} else if (*actstring == '\\') {
125					fputc('\\', astringfile);
126					len++;
127					fputc('\\', astringfile);
128				} else if (*actstring == '\"') {
129					fputc('\\', astringfile);
130					len++;
131					fputc('\"', astringfile);
132				} else fputc(*actstring, astringfile);
133				actstring++;
134				len++;
135			}
136			fprintf(astringfile,"\",\n");
137			if (len > LINELEN) {
138				fprintf(stderr, "Action too long: %d\n",len); Exit(-1);
139			}
140		}
141	ENDDEBUG
142
143	return(Actindex);
144}
145
146static int Npred=0, Ndefpred=0, Ntrans=0, Ndefevent=0, Nnulla=0;
147
148void
149statetable(char *string, struct Object *oldstate, struct Object *newstate, int action, struct Object *event)
150{
151	register int different;
152
153	IFDEBUG(a)
154		fprintf(OUT,"statetable(%p, %p,%p, 0x%x)\n",
155			string, oldstate, newstate, action);
156		fprintf(OUT,"statetable(%s, %s,%s, 0x%x)\n",
157			string, oldstate->obj_name, newstate->obj_name, action);
158	ENDDEBUG
159
160	if( !action) Nnulla++;
161	if( newstate->obj_kind == OBJ_SET) {
162		fprintf(stderr, "Newstate cannot be a set\n");
163		Exit(-1);
164	}
165	different = (newstate != SameState);
166
167	(void) predtable( oldstate, event, string,
168				action, (newstate->obj_number) * different );
169	IFDEBUG(a)
170		fprintf(OUT,"EXIT statetable\n");
171	ENDDEBUG
172}
173
174void
175stateentry(int idx, int oldstate, int newstate, int action)
176{
177	extern FILE *statevalfile;
178
179	IFDEBUG(a)
180		fprintf(OUT,"stateentry(0x%x,0x%x,0x%x,0x%x) Statelist@%p, val %p\n",
181			idx, oldstate, newstate,action, &Statelist, Statelist);
182	ENDDEBUG
183
184
185	fprintf(statevalfile, "{0x%x,0x%x},\n", newstate, action);
186}
187
188int
189predtable(struct Object *os, struct Object *oe, char *str, int action, int newstate)
190{
191	register struct Predicate *p, **q;
192	register int event, state;
193	register struct Object *e, *s;
194	struct Object *firste;
195	extern FILE *statevalfile;
196
197	if (oe == (struct Object *)0 ) {
198		Ndefevent++;
199		fprintf(stderr, "DEFAULT EVENTS aren't implemented; trans ignored\n");
200		return (-1);
201	}
202	Ntrans++;
203	IFDEBUG(g)
204		fprintf(stdout,
205		"PREDTAB: s %5s;  e %5s\n", os->obj_kind==OBJ_SET?"SET":"item",
206			oe->obj_kind==OBJ_SET?"SET":"item");
207	ENDDEBUG
208	if (os->obj_kind == OBJ_SET) s = os->obj_members;
209	else s = os;
210	if (oe->obj_kind == OBJ_SET) firste = oe->obj_members;
211	else firste = oe;
212	if(newstate) {
213		fprintf(statevalfile, "{0x%x,0x%x},\n",newstate, action);
214		Index++;
215	}
216	while (s) {
217		if( !newstate ) { /* !newstate --> SAME */
218			/* i.e., use old obj_number */
219			fprintf(statevalfile, "{0x%x,0x%x},\n",s->obj_number, action);
220			Index++;
221		}
222		e = firste;
223		while (e) {
224			event = e->obj_number; state = s->obj_number;
225			IFDEBUG(g)
226				fprintf(stdout,"pred table event=0x%x, state 0x%x\n",
227				event, state);
228				fflush(stdout);
229			ENDDEBUG
230			if( !str /* DEFAULT PREDICATE */) {
231				Ndefpred++;
232				IFDEBUG(g)
233					fprintf(stdout,
234					"DEFAULT pred state 0x%x, event 0x%x, Index 0x%x\n",
235					state, event, Index);
236					fflush(stdout);
237				ENDDEBUG
238			} else
239				Npred++;
240			/* put at END of list */
241#ifndef LINT
242			IFDEBUG(g)
243				fprintf(stdout,
244				"predicate for event 0x%x, state 0x%x is 0x%x, %s\n",
245				event, state, Index, str);
246				fflush(stdout);
247			ENDDEBUG
248#endif /* LINT */
249			for( ((q = &Predlist[(event<<Eventshift)+state]),
250					 (p = Predlist[(event<<Eventshift)+state]));
251							p ; p = p->p_next ) {
252				q = &p->p_next;
253			}
254
255			p = (struct Predicate *)Malloc(sizeof(struct Predicate));
256			p->p_next = (struct Predicate *)0;
257			p->p_str = str;
258			p->p_index = Index;
259			p->p_transno = transno;
260			*q = p;
261
262			IFDEBUG(g)
263				fprintf(stdout,
264			  	  "predtable index 0x%x, transno %d, E %p, S %p\n",
265					 Index, transno, e, s);
266			ENDDEBUG
267
268			e = e->obj_members;
269		}
270		s = s->obj_members;
271	}
272	return Index ;
273}
274
275void
276printprotoerrs(void)
277{
278	register int e,s;
279
280	fprintf(stderr, "[ Event, State ] without any transitions :\n");
281	for(e = 0; e < Nevents; e++) {
282		fprintf(stderr, "Event 0x%x: states ", e);
283		for(s = 0; s < Nstates; s++) {
284			if( Predlist[(e<<Eventshift)+s] == 0 )
285				fprintf(stderr, "0x%x ", s);
286		}
287		fprintf(stderr, "\n");
288	}
289}
290
291#ifndef LINT
292void
293dump_predtable(FILE *f)
294{
295	struct Predicate *p;
296	register int e,s, hadapred;
297	int defaultindex;
298	int defaultItrans;
299
300#ifdef notdef
301	extern int bytesmalloced;
302	extern int byteswasted;
303
304	fprintf(stdout,
305		" Xebec used %8d bytes of storage, wasted %8d bytes\n",
306		bytesmalloced, byteswasted);
307#endif /* notdef */
308	fprintf(stdout,
309		" %8d states\n %8d events\n %8d transitions\n",
310		Nstates, Nevents, Ntrans);
311	fprintf(stdout,
312		" %8d predicates\n %8d default predicates used\n",
313		Npred, Ndefpred);
314	fprintf(stdout,
315		" %8d null actions\n",
316		Nnulla);
317
318	putdriver(f, 5);
319	for(e = 0; e < Nevents; e++) { for(s = 0; s < Nstates; s++) {
320		p = Predlist[(e<<Eventshift)+s];
321		hadapred=0;
322		defaultindex=0;
323		defaultItrans=0;
324		if(p) {
325			IFDEBUG(d)
326				fflush(f);
327			ENDDEBUG
328			while(p) {
329				if(p->p_str) {
330					if(!hadapred)
331						fprintf(f, "case 0x%x:\n\t", (e<<Eventshift) + s);
332					hadapred = 1;
333					fprintf(f, "if %s return 0x%x;\n\t else ",
334					p->p_str, p->p_index);
335				} else {
336					if(defaultindex) {
337						fprintf(stderr,
338"\nConflict between transitions %d and %d: duplicate default \n",
339						p->p_transno, defaultItrans);
340						Exit(-1);
341					}
342					defaultindex = p->p_index;
343					defaultItrans = p->p_transno;
344				}
345				p = p->p_next;
346			}
347			if( hadapred)  {
348				fprintf(f, "return 0x%x;\n", defaultindex);
349			}
350			IFDEBUG(d)
351				fflush(f);
352			ENDDEBUG
353		}
354		IFDEBUG(g)
355		fprintf(stdout,
356		"loop: e 0x%x s 0x%x hadapred 0x%x dindex 0x%x for trans 0x%x\n",
357			e, s, hadapred, defaultindex, defaultItrans);
358		ENDDEBUG
359		if ( hadapred ) {
360			/* put a -1 in the array  - Predlist is temporary storage */
361			Predlist[(e<<Eventshift)+s] = (struct Predicate *)(-1);
362		} else {
363			/* put defaultindex in the array */
364			/* if defaultindex is zero, then the driver will
365			 * cause an erroraction (same as if no default
366			 * were given and none of the predicates were true;
367			 * also same as if no preds or defaults were given
368			 * for this combo)
369			 */
370			Predlist[(e<<Eventshift)+s] = (struct Predicate *)(defaultindex);
371		}
372	} }
373	fprintf(f, "default: return 0;\n} /* end switch */\n");
374#ifdef notdef
375	fprintf(f, "/*NOTREACHED*/return 0;\n} /* _Xebec_index() */\n");
376#else /* !notdef */
377	fprintf(f, "} /* _Xebec_index() */\n");
378#endif /* notdef */
379	fprintf(f, "static int inx[%d][%d] = { {", Nevents+1,Nstates);
380	for(s = 0; s< Nstates; s++) fprintf(f, "0,"); /* event 0 */
381	fprintf(f, "},\n");
382
383	for(e = 0; e < Nevents; e++) {
384		fprintf(f, " {");
385		for(s = 0; s < Nstates; s++) {
386			register struct Predicate *xyz = Predlist[(e<<Eventshift)+s];
387			/* this kludge is to avoid a lint msg. concerning
388			 * loss of bits
389			 */
390			if (xyz == (struct Predicate *)(-1))
391				fprintf(f, "-1,");
392			else
393				fprintf(f, "%p,", Predlist[(e<<Eventshift)+s]);
394		}
395		fprintf(f, " },\n");
396	}
397	fprintf(f, "};");
398}
399#endif /* LINT */
400
401char *
402stash(char *buf)
403{
404	register int len;
405	register char *c;
406
407	/* grot */
408	len = strlen(buf);
409	c = Malloc(len+1);
410#ifdef LINT
411	c =
412#endif /* LINT */
413	strcpy(c, buf);
414
415	IFDEBUG(z)
416		fprintf(stdout,"stash %s at %p\n", c,c);
417	ENDDEBUG
418	return(c);
419}
420
421#ifdef notdef
422dump_pentry(int event,int state)
423{
424	register struct Predicate *p, **q;
425
426	for(
427	((q = &Predlist[(event<<Eventshift) +state]),
428	 (p = Predlist[(event<<Eventshift) + state]));
429		p!= (struct Predicate *)0 ; p = p->p_next ) {
430#ifndef LINT
431		IFDEBUG(a)
432			fprintf(OUT,
433			"dump_pentry for event 0x%x, state 0x%x is 0x%x\n",
434			 event, state, p);
435		ENDDEBUG
436#endif /* LINT */
437		q = &p->p_next;
438	}
439}
440#endif /* notdef */
441