xref: /plan9/sys/src/cmd/spin/pangen7.c (revision 00d970127b9d44d2b22f4f656717a212dec1f1d2)
1*00d97012SDavid du Colombier /***** spin: pangen7.c *****/
2*00d97012SDavid du Colombier 
3*00d97012SDavid du Colombier /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories.     */
4*00d97012SDavid du Colombier /* All Rights Reserved.  This software is for educational purposes only.  */
5*00d97012SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */
6*00d97012SDavid du Colombier /* this code.  Permission is given to distribute this code provided that  */
7*00d97012SDavid du Colombier /* this introductory message is not removed and no monies are exchanged.  */
8*00d97012SDavid du Colombier /* Software written by Gerard J. Holzmann.  For tool documentation see:   */
9*00d97012SDavid du Colombier /*             http://spinroot.com/                                       */
10*00d97012SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com            */
11*00d97012SDavid du Colombier /* pangen7.c: Version 5.3.0 2010, synchronous product of never claims     */
12*00d97012SDavid du Colombier 
13*00d97012SDavid du Colombier #include <stdlib.h>
14*00d97012SDavid du Colombier #include "spin.h"
15*00d97012SDavid du Colombier #include "y.tab.h"
16*00d97012SDavid du Colombier #include <assert.h>
17*00d97012SDavid du Colombier #ifdef PC
18*00d97012SDavid du Colombier extern int unlink(const char *);
19*00d97012SDavid du Colombier #else
20*00d97012SDavid du Colombier #include <unistd.h>
21*00d97012SDavid du Colombier #endif
22*00d97012SDavid du Colombier 
23*00d97012SDavid du Colombier extern ProcList	*rdy;
24*00d97012SDavid du Colombier extern Element *Al_El;
25*00d97012SDavid du Colombier extern int nclaims, verbose, Strict;
26*00d97012SDavid du Colombier 
27*00d97012SDavid du Colombier typedef struct Succ_List Succ_List;
28*00d97012SDavid du Colombier typedef struct SQueue SQueue;
29*00d97012SDavid du Colombier typedef struct OneState OneState;
30*00d97012SDavid du Colombier typedef struct State_Stack State_Stack;
31*00d97012SDavid du Colombier typedef struct Guard Guard;
32*00d97012SDavid du Colombier 
33*00d97012SDavid du Colombier struct Succ_List {
34*00d97012SDavid du Colombier 	SQueue	*s;
35*00d97012SDavid du Colombier 	Succ_List *nxt;
36*00d97012SDavid du Colombier };
37*00d97012SDavid du Colombier 
38*00d97012SDavid du Colombier struct OneState {
39*00d97012SDavid du Colombier 	int	*combo;	/* the combination of claim states */
40*00d97012SDavid du Colombier 	Succ_List	*succ;	/* list of ptrs to immediate successor states */
41*00d97012SDavid du Colombier };
42*00d97012SDavid du Colombier 
43*00d97012SDavid du Colombier struct SQueue {
44*00d97012SDavid du Colombier 	OneState	state;
45*00d97012SDavid du Colombier 	SQueue	*nxt;
46*00d97012SDavid du Colombier };
47*00d97012SDavid du Colombier 
48*00d97012SDavid du Colombier struct State_Stack {
49*00d97012SDavid du Colombier 	int *n;
50*00d97012SDavid du Colombier 	State_Stack *nxt;
51*00d97012SDavid du Colombier };
52*00d97012SDavid du Colombier 
53*00d97012SDavid du Colombier struct Guard {
54*00d97012SDavid du Colombier 	Lextok *t;
55*00d97012SDavid du Colombier 	Guard *nxt;
56*00d97012SDavid du Colombier };
57*00d97012SDavid du Colombier 
58*00d97012SDavid du Colombier SQueue	*sq, *sd, *render;	/* states move from sq to sd to render to holding */
59*00d97012SDavid du Colombier SQueue	*holding, *lasthold;
60*00d97012SDavid du Colombier State_Stack *dsts;
61*00d97012SDavid du Colombier 
62*00d97012SDavid du Colombier int nst;		/* max nr of states in claims */
63*00d97012SDavid du Colombier int *Ist;		/* initial states */
64*00d97012SDavid du Colombier int *Nacc;		/* number of accept states in claim */
65*00d97012SDavid du Colombier int *Nst;		/* next states */
66*00d97012SDavid du Colombier int **reached;		/* n claims x states */
67*00d97012SDavid du Colombier int unfolding;		/* to make sure all accept states are reached */
68*00d97012SDavid du Colombier int is_accept;		/* remember if the current state is accepting in any claim */
69*00d97012SDavid du Colombier int not_printing;	/* set during explore_product */
70*00d97012SDavid du Colombier 
71*00d97012SDavid du Colombier Element ****matrix;	/* n x two-dimensional arrays state x state */
72*00d97012SDavid du Colombier Element **Selfs;	/* self-loop states at end of claims */
73*00d97012SDavid du Colombier 
74*00d97012SDavid du Colombier static void get_seq(int, Sequence *);
75*00d97012SDavid du Colombier static void set_el(int n, Element *e);
76*00d97012SDavid du Colombier static void gen_product(void);
77*00d97012SDavid du Colombier static void print_state_nm(char *, int *, char *);
78*00d97012SDavid du Colombier static SQueue *find_state(int *);
79*00d97012SDavid du Colombier static SQueue *retrieve_state(int *);
80*00d97012SDavid du Colombier 
81*00d97012SDavid du Colombier static int
same_state(int * a,int * b)82*00d97012SDavid du Colombier same_state(int *a, int *b)
83*00d97012SDavid du Colombier {	int i;
84*00d97012SDavid du Colombier 
85*00d97012SDavid du Colombier 	for (i = 0; i < nclaims; i++)
86*00d97012SDavid du Colombier 	{	if (a[i] != b[i])
87*00d97012SDavid du Colombier 		{	return 0;
88*00d97012SDavid du Colombier 	}	}
89*00d97012SDavid du Colombier 	return 1;
90*00d97012SDavid du Colombier }
91*00d97012SDavid du Colombier 
92*00d97012SDavid du Colombier static int
in_stack(SQueue * s,SQueue * in)93*00d97012SDavid du Colombier in_stack(SQueue *s, SQueue *in)
94*00d97012SDavid du Colombier {	SQueue *q;
95*00d97012SDavid du Colombier 
96*00d97012SDavid du Colombier 	for (q = in; q; q = q->nxt)
97*00d97012SDavid du Colombier 	{	if (same_state(q->state.combo, s->state.combo))
98*00d97012SDavid du Colombier 		{	return 1;
99*00d97012SDavid du Colombier 	}	}
100*00d97012SDavid du Colombier 	return 0;
101*00d97012SDavid du Colombier }
102*00d97012SDavid du Colombier 
103*00d97012SDavid du Colombier static void
to_render(SQueue * s)104*00d97012SDavid du Colombier to_render(SQueue *s)
105*00d97012SDavid du Colombier {	SQueue *a, *q, *last; /* find in sd/sq and move to render, if not already there */
106*00d97012SDavid du Colombier 	int n;
107*00d97012SDavid du Colombier 
108*00d97012SDavid du Colombier 	for (n = 0; n < nclaims; n++)
109*00d97012SDavid du Colombier 	{	reached[n][ s->state.combo[n] ] |= 2;
110*00d97012SDavid du Colombier 	}
111*00d97012SDavid du Colombier 
112*00d97012SDavid du Colombier 	for (q = render; q; q = q->nxt)
113*00d97012SDavid du Colombier 	{	if (same_state(q->state.combo, s->state.combo))
114*00d97012SDavid du Colombier 		{	return;
115*00d97012SDavid du Colombier 	}	}
116*00d97012SDavid du Colombier 	for (q = holding; q; q = q->nxt)
117*00d97012SDavid du Colombier 	{	if (same_state(q->state.combo, s->state.combo))
118*00d97012SDavid du Colombier 		{	return;
119*00d97012SDavid du Colombier 	}	}
120*00d97012SDavid du Colombier 
121*00d97012SDavid du Colombier 	a = sd;
122*00d97012SDavid du Colombier more:
123*00d97012SDavid du Colombier 	for (q = a, last = 0; q; last = q, q = q->nxt)
124*00d97012SDavid du Colombier 	{	if (same_state(q->state.combo, s->state.combo))
125*00d97012SDavid du Colombier 		{	if (!last)
126*00d97012SDavid du Colombier 			{	if (a == sd)
127*00d97012SDavid du Colombier 				{	sd = q->nxt;
128*00d97012SDavid du Colombier 				} else if (a == sq)
129*00d97012SDavid du Colombier 				{	sq = q->nxt;
130*00d97012SDavid du Colombier 				} else
131*00d97012SDavid du Colombier 				{	holding = q->nxt;
132*00d97012SDavid du Colombier 				}
133*00d97012SDavid du Colombier 			} else
134*00d97012SDavid du Colombier 			{	last->nxt = q->nxt;
135*00d97012SDavid du Colombier 			}
136*00d97012SDavid du Colombier 			q->nxt = render;
137*00d97012SDavid du Colombier 			render = q;
138*00d97012SDavid du Colombier 			return;
139*00d97012SDavid du Colombier 	}	}
140*00d97012SDavid du Colombier 	if (verbose)
141*00d97012SDavid du Colombier 	{	print_state_nm("looking for: ", s->state.combo, "\n");
142*00d97012SDavid du Colombier 	}
143*00d97012SDavid du Colombier 	(void) find_state(s->state.combo);	/* creates it in sq */
144*00d97012SDavid du Colombier 	if (a != sq)
145*00d97012SDavid du Colombier 	{	a = sq;
146*00d97012SDavid du Colombier 		goto more;
147*00d97012SDavid du Colombier 	}
148*00d97012SDavid du Colombier 	fatal("cannot happen, to_render", 0);
149*00d97012SDavid du Colombier }
150*00d97012SDavid du Colombier 
151*00d97012SDavid du Colombier static void
wrap_text(char * pre,Lextok * t,char * post)152*00d97012SDavid du Colombier wrap_text(char *pre, Lextok *t, char *post)
153*00d97012SDavid du Colombier {
154*00d97012SDavid du Colombier 	printf(pre);
155*00d97012SDavid du Colombier 	comment(stdout, t, 0);
156*00d97012SDavid du Colombier 	printf(post);
157*00d97012SDavid du Colombier }
158*00d97012SDavid du Colombier 
159*00d97012SDavid du Colombier static State_Stack *
push_dsts(int * n)160*00d97012SDavid du Colombier push_dsts(int *n)
161*00d97012SDavid du Colombier {	State_Stack *s;
162*00d97012SDavid du Colombier 	int i;
163*00d97012SDavid du Colombier 
164*00d97012SDavid du Colombier 	for (s = dsts; s; s = s->nxt)
165*00d97012SDavid du Colombier 	{	if (same_state(s->n, n))
166*00d97012SDavid du Colombier 		{	if (verbose&64)
167*00d97012SDavid du Colombier 			{	printf("\n");
168*00d97012SDavid du Colombier 				for (s = dsts; s; s = s->nxt)
169*00d97012SDavid du Colombier 				{	print_state_nm("\t", s->n, "\n");
170*00d97012SDavid du Colombier 				}
171*00d97012SDavid du Colombier 				print_state_nm("\t", n, "\n");
172*00d97012SDavid du Colombier 			}
173*00d97012SDavid du Colombier 			return s;
174*00d97012SDavid du Colombier 	}	}
175*00d97012SDavid du Colombier 
176*00d97012SDavid du Colombier 	s = (State_Stack *) emalloc(sizeof(State_Stack));
177*00d97012SDavid du Colombier 	s->n = (int *) emalloc(nclaims * sizeof(int));
178*00d97012SDavid du Colombier 	for (i = 0; i < nclaims; i++)
179*00d97012SDavid du Colombier 		s->n[i] = n[i];
180*00d97012SDavid du Colombier 	s->nxt = dsts;
181*00d97012SDavid du Colombier 	dsts = s;
182*00d97012SDavid du Colombier 	return 0;
183*00d97012SDavid du Colombier }
184*00d97012SDavid du Colombier 
185*00d97012SDavid du Colombier static void
pop_dsts(void)186*00d97012SDavid du Colombier pop_dsts(void)
187*00d97012SDavid du Colombier {
188*00d97012SDavid du Colombier 	assert(dsts);
189*00d97012SDavid du Colombier 	dsts = dsts->nxt;
190*00d97012SDavid du Colombier }
191*00d97012SDavid du Colombier 
192*00d97012SDavid du Colombier static void
complete_transition(Succ_List * sl,Guard * g)193*00d97012SDavid du Colombier complete_transition(Succ_List *sl, Guard *g)
194*00d97012SDavid du Colombier {	Guard *w;
195*00d97012SDavid du Colombier 	int cnt = 0;
196*00d97012SDavid du Colombier 
197*00d97012SDavid du Colombier 	printf("	:: ");
198*00d97012SDavid du Colombier 	for (w = g; w; w = w->nxt)
199*00d97012SDavid du Colombier 	{	if (w->t->ntyp == CONST
200*00d97012SDavid du Colombier 		&&  w->t->val == 1)
201*00d97012SDavid du Colombier 		{	continue;
202*00d97012SDavid du Colombier 		} else if (w->t->ntyp == 'c'
203*00d97012SDavid du Colombier 		&&  w->t->lft->ntyp == CONST
204*00d97012SDavid du Colombier 		&&  w->t->lft->val == 1)
205*00d97012SDavid du Colombier 		{	continue; /* 'true' */
206*00d97012SDavid du Colombier 		}
207*00d97012SDavid du Colombier 
208*00d97012SDavid du Colombier 		if (cnt > 0)
209*00d97012SDavid du Colombier 		{	printf(" && ");
210*00d97012SDavid du Colombier 		}
211*00d97012SDavid du Colombier 		wrap_text("", w->t, "");
212*00d97012SDavid du Colombier 		cnt++;
213*00d97012SDavid du Colombier 	}
214*00d97012SDavid du Colombier 	if (cnt == 0)
215*00d97012SDavid du Colombier 	{	printf("true");
216*00d97012SDavid du Colombier 	}
217*00d97012SDavid du Colombier 	print_state_nm(" -> goto ", sl->s->state.combo, "");
218*00d97012SDavid du Colombier 
219*00d97012SDavid du Colombier 	if (is_accept > 0)
220*00d97012SDavid du Colombier 	{	printf("_U%d\n", (unfolding+1)%nclaims);
221*00d97012SDavid du Colombier 	} else
222*00d97012SDavid du Colombier 	{	printf("_U%d\n", unfolding);
223*00d97012SDavid du Colombier 	}
224*00d97012SDavid du Colombier }
225*00d97012SDavid du Colombier 
226*00d97012SDavid du Colombier static void
state_body(OneState * s,Guard * guard)227*00d97012SDavid du Colombier state_body(OneState *s, Guard *guard)
228*00d97012SDavid du Colombier {	Succ_List *sl;
229*00d97012SDavid du Colombier 	State_Stack *y;
230*00d97012SDavid du Colombier 	Guard *g;
231*00d97012SDavid du Colombier 	int i, once;
232*00d97012SDavid du Colombier 
233*00d97012SDavid du Colombier 	for (sl = s->succ; sl; sl = sl->nxt)
234*00d97012SDavid du Colombier 	{	once = 0;
235*00d97012SDavid du Colombier 
236*00d97012SDavid du Colombier 		for (i = 0; i < nclaims; i++)
237*00d97012SDavid du Colombier 		{	Element *e;
238*00d97012SDavid du Colombier 			e = matrix[i][s->combo[i]][sl->s->state.combo[i]];
239*00d97012SDavid du Colombier 
240*00d97012SDavid du Colombier 			/* if one of the claims has a DO or IF move
241*00d97012SDavid du Colombier 			   then pull its target state forward, once
242*00d97012SDavid du Colombier 			 */
243*00d97012SDavid du Colombier 
244*00d97012SDavid du Colombier 			if (!e
245*00d97012SDavid du Colombier 			|| e->n->ntyp == NON_ATOMIC
246*00d97012SDavid du Colombier 			||  e->n->ntyp == DO
247*00d97012SDavid du Colombier 			||  e->n->ntyp == IF)
248*00d97012SDavid du Colombier 			{	s = &(sl->s->state);
249*00d97012SDavid du Colombier 				y = push_dsts(s->combo);
250*00d97012SDavid du Colombier 				if (!y)
251*00d97012SDavid du Colombier 				{	if (once++ == 0)
252*00d97012SDavid du Colombier 					{	assert(s->succ);
253*00d97012SDavid du Colombier 						state_body(s, guard);
254*00d97012SDavid du Colombier 					}
255*00d97012SDavid du Colombier 					pop_dsts();
256*00d97012SDavid du Colombier 				} else if (!y->nxt)	/* self-loop transition */
257*00d97012SDavid du Colombier 				{	if (!not_printing) printf(" /* self-loop */\n");
258*00d97012SDavid du Colombier 				} else
259*00d97012SDavid du Colombier 				{	/* non_fatal("loop in state body", 0); ** maybe ok */
260*00d97012SDavid du Colombier 				}
261*00d97012SDavid du Colombier 				continue;
262*00d97012SDavid du Colombier 			} else
263*00d97012SDavid du Colombier 			{	g = (Guard *) emalloc(sizeof(Guard));
264*00d97012SDavid du Colombier 				g->t = e->n;
265*00d97012SDavid du Colombier 				g->nxt = guard;
266*00d97012SDavid du Colombier 				guard = g;
267*00d97012SDavid du Colombier 		}	}
268*00d97012SDavid du Colombier 
269*00d97012SDavid du Colombier 		if (guard && !once)
270*00d97012SDavid du Colombier 		{	if (!not_printing) complete_transition(sl, guard);
271*00d97012SDavid du Colombier 			to_render(sl->s);
272*00d97012SDavid du Colombier 	}	}
273*00d97012SDavid du Colombier }
274*00d97012SDavid du Colombier 
275*00d97012SDavid du Colombier static struct X {
276*00d97012SDavid du Colombier 	char *s;	int n;
277*00d97012SDavid du Colombier } spl[] = {
278*00d97012SDavid du Colombier 	{"end",		3 },
279*00d97012SDavid du Colombier 	{"accept",	6 },
280*00d97012SDavid du Colombier 	{0,		0 },
281*00d97012SDavid du Colombier };
282*00d97012SDavid du Colombier 
283*00d97012SDavid du Colombier static int slcnt;
284*00d97012SDavid du Colombier extern Label *labtab;
285*00d97012SDavid du Colombier 
286*00d97012SDavid du Colombier static ProcList *
locate_claim(int n)287*00d97012SDavid du Colombier locate_claim(int n)
288*00d97012SDavid du Colombier {	ProcList *p;
289*00d97012SDavid du Colombier 	int i;
290*00d97012SDavid du Colombier 
291*00d97012SDavid du Colombier 	for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
292*00d97012SDavid du Colombier 	{	if (i == n)
293*00d97012SDavid du Colombier 		{	break;
294*00d97012SDavid du Colombier 	}	}
295*00d97012SDavid du Colombier 	assert(p && p->b == N_CLAIM);
296*00d97012SDavid du Colombier 
297*00d97012SDavid du Colombier 	return p;
298*00d97012SDavid du Colombier }
299*00d97012SDavid du Colombier 
300*00d97012SDavid du Colombier static void
elim_lab(Element * e)301*00d97012SDavid du Colombier elim_lab(Element *e)
302*00d97012SDavid du Colombier {	Label *l, *lst;
303*00d97012SDavid du Colombier 
304*00d97012SDavid du Colombier 	for (l = labtab, lst = NULL; l; lst = l, l = l->nxt)
305*00d97012SDavid du Colombier 	{	if (l->e == e)
306*00d97012SDavid du Colombier 		{	if (lst)
307*00d97012SDavid du Colombier 			{	lst->nxt = l->nxt;
308*00d97012SDavid du Colombier 			} else
309*00d97012SDavid du Colombier 			{	labtab = l->nxt;
310*00d97012SDavid du Colombier 			}
311*00d97012SDavid du Colombier 			break;
312*00d97012SDavid du Colombier 	}	}
313*00d97012SDavid du Colombier }
314*00d97012SDavid du Colombier 
315*00d97012SDavid du Colombier static int
claim_has_accept(ProcList * p)316*00d97012SDavid du Colombier claim_has_accept(ProcList *p)
317*00d97012SDavid du Colombier {	Label *l;
318*00d97012SDavid du Colombier 
319*00d97012SDavid du Colombier 	for (l = labtab; l; l = l->nxt)
320*00d97012SDavid du Colombier 	{	if (strcmp(l->c->name, p->n->name) == 0
321*00d97012SDavid du Colombier 		&&  strncmp(l->s->name, "accept", 6) == 0)
322*00d97012SDavid du Colombier 		{	return 1;
323*00d97012SDavid du Colombier 	}	}
324*00d97012SDavid du Colombier 	return 0;
325*00d97012SDavid du Colombier }
326*00d97012SDavid du Colombier 
327*00d97012SDavid du Colombier static void
prune_accept(void)328*00d97012SDavid du Colombier prune_accept(void)
329*00d97012SDavid du Colombier {	int n;
330*00d97012SDavid du Colombier 
331*00d97012SDavid du Colombier 	for (n = 0; n < nclaims; n++)
332*00d97012SDavid du Colombier 	{	if ((reached[n][Selfs[n]->seqno] & 2) == 0)
333*00d97012SDavid du Colombier 		{	if (verbose)
334*00d97012SDavid du Colombier 			{	printf("claim %d: selfloop not reachable\n", n);
335*00d97012SDavid du Colombier 			}
336*00d97012SDavid du Colombier 			elim_lab(Selfs[n]);
337*00d97012SDavid du Colombier 			Nacc[n] = claim_has_accept(locate_claim(n));
338*00d97012SDavid du Colombier 	}	}
339*00d97012SDavid du Colombier }
340*00d97012SDavid du Colombier 
341*00d97012SDavid du Colombier static void
mk_accepting(int n,Element * e)342*00d97012SDavid du Colombier mk_accepting(int n, Element *e)
343*00d97012SDavid du Colombier {	ProcList *p;
344*00d97012SDavid du Colombier 	Label *l;
345*00d97012SDavid du Colombier 	int i;
346*00d97012SDavid du Colombier 
347*00d97012SDavid du Colombier 	assert(!Selfs[n]);
348*00d97012SDavid du Colombier 	Selfs[n] = e;
349*00d97012SDavid du Colombier 
350*00d97012SDavid du Colombier 	l = (Label *) emalloc(sizeof(Label));
351*00d97012SDavid du Colombier 	l->s = (Symbol *) emalloc(sizeof(Symbol));
352*00d97012SDavid du Colombier 	l->s->name = "accept00";
353*00d97012SDavid du Colombier 	l->c = (Symbol *) emalloc(sizeof(Symbol));
354*00d97012SDavid du Colombier 	l->uiid = 0;	/* this is not in an inline */
355*00d97012SDavid du Colombier 
356*00d97012SDavid du Colombier 	for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
357*00d97012SDavid du Colombier 	{	if (i == n)
358*00d97012SDavid du Colombier 		{	l->c->name = p->n->name;
359*00d97012SDavid du Colombier 			break;
360*00d97012SDavid du Colombier 	}	}
361*00d97012SDavid du Colombier 	assert(p && p->b == N_CLAIM);
362*00d97012SDavid du Colombier 	Nacc[n] = 1;
363*00d97012SDavid du Colombier 
364*00d97012SDavid du Colombier 	l->e = e;
365*00d97012SDavid du Colombier 	l->nxt = labtab;
366*00d97012SDavid du Colombier 	labtab = l;
367*00d97012SDavid du Colombier }
368*00d97012SDavid du Colombier 
369*00d97012SDavid du Colombier static void
check_special(int * nrs)370*00d97012SDavid du Colombier check_special(int *nrs)
371*00d97012SDavid du Colombier {	ProcList *p;
372*00d97012SDavid du Colombier 	Label *l;
373*00d97012SDavid du Colombier 	int i, j, nmatches;
374*00d97012SDavid du Colombier 	int any_accepts = 0;
375*00d97012SDavid du Colombier 
376*00d97012SDavid du Colombier 	for (i = 0; i < nclaims; i++)
377*00d97012SDavid du Colombier 	{	any_accepts += Nacc[i];
378*00d97012SDavid du Colombier 	}
379*00d97012SDavid du Colombier 
380*00d97012SDavid du Colombier 	is_accept = 0;
381*00d97012SDavid du Colombier 	for (j = 0; spl[j].n; j++) /* 2 special label prefixes */
382*00d97012SDavid du Colombier 	{	nmatches = 0;
383*00d97012SDavid du Colombier 		for (p = rdy, i = 0; p; p = p->nxt, i++) /* check each claim */
384*00d97012SDavid du Colombier 		{	if (p->b != N_CLAIM)
385*00d97012SDavid du Colombier 			{	continue;
386*00d97012SDavid du Colombier 			}
387*00d97012SDavid du Colombier 			/* claim i in state nrs[i], type p->tn, name p->n->name
388*00d97012SDavid du Colombier 			 * either the state has an accept label, or the claim has none,
389*00d97012SDavid du Colombier 			 * so that all its states should be considered accepting
390*00d97012SDavid du Colombier 			 * --- but only if other claims do have accept states!
391*00d97012SDavid du Colombier 			 */
392*00d97012SDavid du Colombier 			if (Strict == 0 && j == 1 && Nacc[i] == 0 && any_accepts > 0)
393*00d97012SDavid du Colombier 			{	if ((verbose&32) && i == unfolding)
394*00d97012SDavid du Colombier 				{	printf("	/* claim %d pseudo-accept */\n", i);
395*00d97012SDavid du Colombier 				}
396*00d97012SDavid du Colombier 				goto is_accepting;
397*00d97012SDavid du Colombier 			}
398*00d97012SDavid du Colombier 			for (l = labtab; l; l = l->nxt)	/* check its labels */
399*00d97012SDavid du Colombier 			{	if (strcmp(l->c->name, p->n->name) == 0  /* right claim */
400*00d97012SDavid du Colombier 				&&  l->e->seqno == nrs[i]		 /* right state */
401*00d97012SDavid du Colombier 				&&  strncmp(l->s->name, spl[j].s, spl[j].n) == 0)
402*00d97012SDavid du Colombier 				{	if (j == 1)	/* accept state */
403*00d97012SDavid du Colombier 					{	char buf[32];
404*00d97012SDavid du Colombier is_accepting:					if (strchr(p->n->name, ':'))
405*00d97012SDavid du Colombier 						{	sprintf(buf, "N%d", i);
406*00d97012SDavid du Colombier 						} else
407*00d97012SDavid du Colombier 						{	strcpy(buf, p->n->name);
408*00d97012SDavid du Colombier 						}
409*00d97012SDavid du Colombier 						if (unfolding == 0 && i == 0)
410*00d97012SDavid du Colombier 						{	if (!not_printing)
411*00d97012SDavid du Colombier 							printf("%s_%s_%d:\n",	/* true accept */
412*00d97012SDavid du Colombier 								spl[j].s, buf, slcnt++);
413*00d97012SDavid du Colombier 						} else if (verbose&32)
414*00d97012SDavid du Colombier 						{	if (!not_printing)
415*00d97012SDavid du Colombier 							printf("%s_%s%d:\n",
416*00d97012SDavid du Colombier 								buf, spl[j].s, slcnt++);
417*00d97012SDavid du Colombier 						}
418*00d97012SDavid du Colombier 						if (i == unfolding)
419*00d97012SDavid du Colombier 						{	is_accept++; /* move to next unfolding */
420*00d97012SDavid du Colombier 						}
421*00d97012SDavid du Colombier 					} else
422*00d97012SDavid du Colombier 					{	nmatches++;
423*00d97012SDavid du Colombier 					}
424*00d97012SDavid du Colombier 					break;
425*00d97012SDavid du Colombier 		}	}	}
426*00d97012SDavid du Colombier 		if (j == 0 && nmatches == nclaims)	/* end-state */
427*00d97012SDavid du Colombier 		{	if (!not_printing)
428*00d97012SDavid du Colombier 			{	printf("%s%d:\n", spl[j].s, slcnt++);
429*00d97012SDavid du Colombier 	}	}	}
430*00d97012SDavid du Colombier }
431*00d97012SDavid du Colombier 
432*00d97012SDavid du Colombier static int
render_state(SQueue * q)433*00d97012SDavid du Colombier render_state(SQueue *q)
434*00d97012SDavid du Colombier {
435*00d97012SDavid du Colombier 	if (!q || !q->state.succ)
436*00d97012SDavid du Colombier 	{	if (verbose&64)
437*00d97012SDavid du Colombier 		{	printf("	no exit\n");
438*00d97012SDavid du Colombier 		}
439*00d97012SDavid du Colombier 		return 0;
440*00d97012SDavid du Colombier 	}
441*00d97012SDavid du Colombier 
442*00d97012SDavid du Colombier 	check_special(q->state.combo); /* accept or end-state labels */
443*00d97012SDavid du Colombier 
444*00d97012SDavid du Colombier 	dsts = (State_Stack *) 0;
445*00d97012SDavid du Colombier 	push_dsts(q->state.combo);	/* to detect loops */
446*00d97012SDavid du Colombier 
447*00d97012SDavid du Colombier 	if (!not_printing)
448*00d97012SDavid du Colombier 	{	print_state_nm("", q->state.combo, "");	/* the name */
449*00d97012SDavid du Colombier 		printf("_U%d:\n\tdo\n", unfolding);
450*00d97012SDavid du Colombier 	}
451*00d97012SDavid du Colombier 
452*00d97012SDavid du Colombier 	state_body(&(q->state), (Guard *) 0);
453*00d97012SDavid du Colombier 
454*00d97012SDavid du Colombier 	if (!not_printing)
455*00d97012SDavid du Colombier 	{	printf("\tod;\n");
456*00d97012SDavid du Colombier 	}
457*00d97012SDavid du Colombier 	pop_dsts();
458*00d97012SDavid du Colombier 	return 1;
459*00d97012SDavid du Colombier }
460*00d97012SDavid du Colombier 
461*00d97012SDavid du Colombier static void
explore_product(void)462*00d97012SDavid du Colombier explore_product(void)
463*00d97012SDavid du Colombier {	SQueue *q;
464*00d97012SDavid du Colombier 
465*00d97012SDavid du Colombier 	/* all states are in the sd queue */
466*00d97012SDavid du Colombier 
467*00d97012SDavid du Colombier 	q = retrieve_state(Ist);	/* retrieve from the sd q */
468*00d97012SDavid du Colombier 	q->nxt = render;		/* put in render q */
469*00d97012SDavid du Colombier 	render = q;
470*00d97012SDavid du Colombier 	do {
471*00d97012SDavid du Colombier 		q = render;
472*00d97012SDavid du Colombier 		render = render->nxt;
473*00d97012SDavid du Colombier 		q->nxt = 0;		/* remove from render q */
474*00d97012SDavid du Colombier 
475*00d97012SDavid du Colombier 		if (verbose&64)
476*00d97012SDavid du Colombier 		{	print_state_nm("explore: ", q->state.combo, "\n");
477*00d97012SDavid du Colombier 		}
478*00d97012SDavid du Colombier 
479*00d97012SDavid du Colombier 		not_printing = 1;
480*00d97012SDavid du Colombier 		render_state(q);	/* may add new states */
481*00d97012SDavid du Colombier 		not_printing = 0;
482*00d97012SDavid du Colombier 
483*00d97012SDavid du Colombier 		if (lasthold)
484*00d97012SDavid du Colombier 		{	lasthold->nxt = q;
485*00d97012SDavid du Colombier 			lasthold = q;
486*00d97012SDavid du Colombier 		} else
487*00d97012SDavid du Colombier 		{	holding = lasthold = q;
488*00d97012SDavid du Colombier 		}
489*00d97012SDavid du Colombier 	} while (render);
490*00d97012SDavid du Colombier 	assert(!dsts);
491*00d97012SDavid du Colombier 
492*00d97012SDavid du Colombier }
493*00d97012SDavid du Colombier 
494*00d97012SDavid du Colombier static void
print_product(void)495*00d97012SDavid du Colombier print_product(void)
496*00d97012SDavid du Colombier {	SQueue *q;
497*00d97012SDavid du Colombier 	int cnt;
498*00d97012SDavid du Colombier 
499*00d97012SDavid du Colombier 	if (unfolding == 0)
500*00d97012SDavid du Colombier 	{	printf("never Product {\n");	/* name expected by iSpin */
501*00d97012SDavid du Colombier 		q = find_state(Ist);	/* should find it in the holding q */
502*00d97012SDavid du Colombier 		assert(q);
503*00d97012SDavid du Colombier 		q->nxt = holding;	/* put it at the front */
504*00d97012SDavid du Colombier 		holding = q;
505*00d97012SDavid du Colombier 	}
506*00d97012SDavid du Colombier 	render = holding;
507*00d97012SDavid du Colombier 	holding = lasthold = 0;
508*00d97012SDavid du Colombier 
509*00d97012SDavid du Colombier 	printf("/* ============= U%d ============= */\n", unfolding);
510*00d97012SDavid du Colombier 	cnt = 0;
511*00d97012SDavid du Colombier 	do {
512*00d97012SDavid du Colombier 		q = render;
513*00d97012SDavid du Colombier 		render = render->nxt;
514*00d97012SDavid du Colombier 		q->nxt = 0;
515*00d97012SDavid du Colombier 		if (verbose&64)
516*00d97012SDavid du Colombier 		{	print_state_nm("print: ", q->state.combo, "\n");
517*00d97012SDavid du Colombier 		}
518*00d97012SDavid du Colombier 		cnt += render_state(q);
519*00d97012SDavid du Colombier 
520*00d97012SDavid du Colombier 		if (lasthold)
521*00d97012SDavid du Colombier 		{	lasthold->nxt = q;
522*00d97012SDavid du Colombier 			lasthold = q;
523*00d97012SDavid du Colombier 		} else
524*00d97012SDavid du Colombier 		{	holding = lasthold = q;
525*00d97012SDavid du Colombier 		}
526*00d97012SDavid du Colombier 	} while (render);
527*00d97012SDavid du Colombier 	assert(!dsts);
528*00d97012SDavid du Colombier 
529*00d97012SDavid du Colombier 	if (cnt == 0)
530*00d97012SDavid du Colombier 	{	printf("	0;\n");
531*00d97012SDavid du Colombier 	}
532*00d97012SDavid du Colombier 
533*00d97012SDavid du Colombier 	if (unfolding == nclaims-1)
534*00d97012SDavid du Colombier 	{	printf("}\n");
535*00d97012SDavid du Colombier 	}
536*00d97012SDavid du Colombier }
537*00d97012SDavid du Colombier 
538*00d97012SDavid du Colombier static void
prune_dead(void)539*00d97012SDavid du Colombier prune_dead(void)
540*00d97012SDavid du Colombier {	Succ_List *sl, *last;
541*00d97012SDavid du Colombier 	SQueue *q;
542*00d97012SDavid du Colombier 	int cnt;
543*00d97012SDavid du Colombier 
544*00d97012SDavid du Colombier 	do {	cnt = 0;
545*00d97012SDavid du Colombier 		for (q = sd; q; q = q->nxt)
546*00d97012SDavid du Colombier 		{	/* if successor is deadend, remove it
547*00d97012SDavid du Colombier 			 * unless it's a move to the end-state of the claim
548*00d97012SDavid du Colombier 			 */
549*00d97012SDavid du Colombier 			last = (Succ_List *) 0;
550*00d97012SDavid du Colombier 			for (sl = q->state.succ; sl; last = sl, sl = sl->nxt)
551*00d97012SDavid du Colombier 			{	if (!sl->s->state.succ)	/* no successor */
552*00d97012SDavid du Colombier 				{	if (!last)
553*00d97012SDavid du Colombier 					{	q->state.succ = sl->nxt;
554*00d97012SDavid du Colombier 					} else
555*00d97012SDavid du Colombier 					{	last->nxt = sl->nxt;
556*00d97012SDavid du Colombier 					}
557*00d97012SDavid du Colombier 					cnt++;
558*00d97012SDavid du Colombier 		}	}	}
559*00d97012SDavid du Colombier 	} while (cnt > 0);
560*00d97012SDavid du Colombier }
561*00d97012SDavid du Colombier 
562*00d97012SDavid du Colombier static void
print_raw(void)563*00d97012SDavid du Colombier print_raw(void)
564*00d97012SDavid du Colombier {	int i, j, n;
565*00d97012SDavid du Colombier 
566*00d97012SDavid du Colombier 	printf("#if 0\n");
567*00d97012SDavid du Colombier 	for (n = 0; n < nclaims; n++)
568*00d97012SDavid du Colombier 	{	printf("C%d:\n", n);
569*00d97012SDavid du Colombier 		for (i = 0; i < nst; i++)
570*00d97012SDavid du Colombier 		{	if (reached[n][i])
571*00d97012SDavid du Colombier 			for (j = 0; j < nst; j++)
572*00d97012SDavid du Colombier 			{	if (matrix[n][i][j])
573*00d97012SDavid du Colombier 				{	if (reached[n][i] & 2) printf("+");
574*00d97012SDavid du Colombier 					if (i == Ist[n]) printf("*");
575*00d97012SDavid du Colombier 					printf("\t%d", i);
576*00d97012SDavid du Colombier 					wrap_text(" -[", matrix[n][i][j]->n, "]->\t");
577*00d97012SDavid du Colombier 					printf("%d\n", j);
578*00d97012SDavid du Colombier 	}	}	}	}
579*00d97012SDavid du Colombier 	printf("#endif\n\n");
580*00d97012SDavid du Colombier 	fflush(stdout);
581*00d97012SDavid du Colombier }
582*00d97012SDavid du Colombier 
583*00d97012SDavid du Colombier void
sync_product(void)584*00d97012SDavid du Colombier sync_product(void)
585*00d97012SDavid du Colombier {	ProcList *p;
586*00d97012SDavid du Colombier 	Element *e;
587*00d97012SDavid du Colombier 	int n, i;
588*00d97012SDavid du Colombier 
589*00d97012SDavid du Colombier 	if (nclaims <= 1) return;
590*00d97012SDavid du Colombier 
591*00d97012SDavid du Colombier 	(void) unlink("pan.pre");
592*00d97012SDavid du Colombier 
593*00d97012SDavid du Colombier 	Ist  = (int *) emalloc(sizeof(int) * nclaims);
594*00d97012SDavid du Colombier 	Nacc = (int *) emalloc(sizeof(int) * nclaims);
595*00d97012SDavid du Colombier 	Nst  = (int *) emalloc(sizeof(int) * nclaims);
596*00d97012SDavid du Colombier 	reached = (int **) emalloc(sizeof(int *) * nclaims);
597*00d97012SDavid du Colombier 	Selfs   = (Element **) emalloc(sizeof(Element *) * nclaims);
598*00d97012SDavid du Colombier 	matrix  = (Element ****) emalloc(sizeof(Element ***) * nclaims); /* claims */
599*00d97012SDavid du Colombier 
600*00d97012SDavid du Colombier 	for (p = rdy, i = 0; p; p = p->nxt, i++)
601*00d97012SDavid du Colombier 	{	if (p->b == N_CLAIM)
602*00d97012SDavid du Colombier 		{	nst = max(p->s->maxel, nst);
603*00d97012SDavid du Colombier 			Nacc[i] = claim_has_accept(p);
604*00d97012SDavid du Colombier 	}	}
605*00d97012SDavid du Colombier 
606*00d97012SDavid du Colombier 	for (n = 0; n < nclaims; n++)
607*00d97012SDavid du Colombier 	{	reached[n] = (int *) emalloc(sizeof(int) * nst);
608*00d97012SDavid du Colombier 		matrix[n] = (Element ***) emalloc(sizeof(Element **) * nst);	/* rows */
609*00d97012SDavid du Colombier 		for (i = 0; i < nst; i++)					/* cols */
610*00d97012SDavid du Colombier 		{	matrix[n][i] = (Element **) emalloc(sizeof(Element *) * nst);
611*00d97012SDavid du Colombier 	}	}
612*00d97012SDavid du Colombier 
613*00d97012SDavid du Colombier 	for (e = Al_El; e; e = e->Nxt)
614*00d97012SDavid du Colombier 	{	e->status &= ~DONE;
615*00d97012SDavid du Colombier 	}
616*00d97012SDavid du Colombier 
617*00d97012SDavid du Colombier 	for (p = rdy, n=0; p; p = p->nxt, n++)
618*00d97012SDavid du Colombier 	{	if (p->b == N_CLAIM)
619*00d97012SDavid du Colombier 		{	/* fill in matrix[n] */
620*00d97012SDavid du Colombier 			e = p->s->frst;
621*00d97012SDavid du Colombier 			Ist[n] = huntele(e, e->status, -1)->seqno;
622*00d97012SDavid du Colombier 
623*00d97012SDavid du Colombier 			reached[n][Ist[n]] = 1|2;
624*00d97012SDavid du Colombier 			get_seq(n, p->s);
625*00d97012SDavid du Colombier 	}	}
626*00d97012SDavid du Colombier 
627*00d97012SDavid du Colombier 	if (verbose)	/* show only the input automata */
628*00d97012SDavid du Colombier 	{	print_raw();
629*00d97012SDavid du Colombier 	}
630*00d97012SDavid du Colombier 
631*00d97012SDavid du Colombier 	gen_product();	/* create product automaton */
632*00d97012SDavid du Colombier }
633*00d97012SDavid du Colombier 
634*00d97012SDavid du Colombier static int
nxt_trans(int n,int cs,int frst)635*00d97012SDavid du Colombier nxt_trans(int n, int cs, int frst)
636*00d97012SDavid du Colombier {	int j;
637*00d97012SDavid du Colombier 
638*00d97012SDavid du Colombier 	for (j = frst; j < nst; j++)
639*00d97012SDavid du Colombier 	{	if (reached[n][cs]
640*00d97012SDavid du Colombier 		&&  matrix[n][cs][j])
641*00d97012SDavid du Colombier 		{	return j;
642*00d97012SDavid du Colombier 	}	}
643*00d97012SDavid du Colombier 	return -1;
644*00d97012SDavid du Colombier }
645*00d97012SDavid du Colombier 
646*00d97012SDavid du Colombier static void
print_state_nm(char * p,int * s,char * a)647*00d97012SDavid du Colombier print_state_nm(char *p, int *s, char *a)
648*00d97012SDavid du Colombier {	int i;
649*00d97012SDavid du Colombier 	printf("%sP", p);
650*00d97012SDavid du Colombier 	for (i = 0; i < nclaims; i++)
651*00d97012SDavid du Colombier 	{	printf("_%d", s[i]);
652*00d97012SDavid du Colombier 	}
653*00d97012SDavid du Colombier 	printf("%s", a);
654*00d97012SDavid du Colombier }
655*00d97012SDavid du Colombier 
656*00d97012SDavid du Colombier static void
create_transition(OneState * s,SQueue * it)657*00d97012SDavid du Colombier create_transition(OneState *s, SQueue *it)
658*00d97012SDavid du Colombier {	int n, from, upto;
659*00d97012SDavid du Colombier 	int *F = s->combo;
660*00d97012SDavid du Colombier 	int *T = it->state.combo;
661*00d97012SDavid du Colombier 	Succ_List *sl;
662*00d97012SDavid du Colombier 	Lextok *t;
663*00d97012SDavid du Colombier 
664*00d97012SDavid du Colombier 	if (verbose&64)
665*00d97012SDavid du Colombier 	{	print_state_nm("", F, " ");
666*00d97012SDavid du Colombier 		print_state_nm("-> ", T, "\t");
667*00d97012SDavid du Colombier 	}
668*00d97012SDavid du Colombier 
669*00d97012SDavid du Colombier 	/* check if any of the claims is blocked */
670*00d97012SDavid du Colombier 	/* which makes the state a dead-end */
671*00d97012SDavid du Colombier 	for (n = 0; n < nclaims; n++)
672*00d97012SDavid du Colombier 	{	from = F[n];
673*00d97012SDavid du Colombier 		upto = T[n];
674*00d97012SDavid du Colombier 		t = matrix[n][from][upto]->n;
675*00d97012SDavid du Colombier 		if (verbose&64)
676*00d97012SDavid du Colombier 		{	wrap_text("", t, " ");
677*00d97012SDavid du Colombier 		}
678*00d97012SDavid du Colombier 		if (t->ntyp == 'c'
679*00d97012SDavid du Colombier 		&&  t->lft->ntyp == CONST)
680*00d97012SDavid du Colombier 		{	if (t->lft->val == 0)	/* i.e., false */
681*00d97012SDavid du Colombier 			{	goto done;
682*00d97012SDavid du Colombier 	}	}	}
683*00d97012SDavid du Colombier 
684*00d97012SDavid du Colombier 	sl = (Succ_List *) emalloc(sizeof(Succ_List));
685*00d97012SDavid du Colombier 	sl->s = it;
686*00d97012SDavid du Colombier 	sl->nxt = s->succ;
687*00d97012SDavid du Colombier 	s->succ = sl;
688*00d97012SDavid du Colombier done:
689*00d97012SDavid du Colombier 	if (verbose&64)
690*00d97012SDavid du Colombier 	{	printf("\n");
691*00d97012SDavid du Colombier 	}
692*00d97012SDavid du Colombier }
693*00d97012SDavid du Colombier 
694*00d97012SDavid du Colombier static SQueue *
find_state(int * cs)695*00d97012SDavid du Colombier find_state(int *cs)
696*00d97012SDavid du Colombier {	SQueue *nq, *a = sq;
697*00d97012SDavid du Colombier 	int i;
698*00d97012SDavid du Colombier 
699*00d97012SDavid du Colombier again:	/* check in nq, sq, and then in the render q */
700*00d97012SDavid du Colombier 	for (nq = a; nq; nq = nq->nxt)
701*00d97012SDavid du Colombier 	{	if (same_state(nq->state.combo, cs))
702*00d97012SDavid du Colombier 		{	return nq;	/* found */
703*00d97012SDavid du Colombier 	}	}
704*00d97012SDavid du Colombier 	if (a == sq && sd)
705*00d97012SDavid du Colombier 	{	a = sd;
706*00d97012SDavid du Colombier 		goto again; /* check the other stack too */
707*00d97012SDavid du Colombier 	} else if (a == sd && render)
708*00d97012SDavid du Colombier 	{	a = render;
709*00d97012SDavid du Colombier 		goto again;
710*00d97012SDavid du Colombier 	}
711*00d97012SDavid du Colombier 
712*00d97012SDavid du Colombier 	nq = (SQueue *) emalloc(sizeof(SQueue));
713*00d97012SDavid du Colombier 	nq->state.combo = (int *) emalloc(nclaims * sizeof(int));
714*00d97012SDavid du Colombier 	for (i = 0; i < nclaims; i++)
715*00d97012SDavid du Colombier 	{	nq->state.combo[i] = cs[i];
716*00d97012SDavid du Colombier 	}
717*00d97012SDavid du Colombier 	nq->nxt = sq;	/* add to sq stack */
718*00d97012SDavid du Colombier 	sq = nq;
719*00d97012SDavid du Colombier 
720*00d97012SDavid du Colombier 	return nq;
721*00d97012SDavid du Colombier }
722*00d97012SDavid du Colombier 
723*00d97012SDavid du Colombier static SQueue *
retrieve_state(int * s)724*00d97012SDavid du Colombier retrieve_state(int *s)
725*00d97012SDavid du Colombier {	SQueue *nq, *last = NULL;
726*00d97012SDavid du Colombier 
727*00d97012SDavid du Colombier 	for (nq = sd; nq; last = nq, nq = nq->nxt)
728*00d97012SDavid du Colombier 	{	if (same_state(nq->state.combo, s))
729*00d97012SDavid du Colombier 		{	if (last)
730*00d97012SDavid du Colombier 			{	last->nxt = nq->nxt;
731*00d97012SDavid du Colombier 			} else
732*00d97012SDavid du Colombier 			{	sd = nq;
733*00d97012SDavid du Colombier 			}
734*00d97012SDavid du Colombier 			return nq;	/* found */
735*00d97012SDavid du Colombier 	}	}
736*00d97012SDavid du Colombier 
737*00d97012SDavid du Colombier 	fatal("cannot happen: retrieve_state", 0);
738*00d97012SDavid du Colombier 	return (SQueue *) 0;
739*00d97012SDavid du Colombier }
740*00d97012SDavid du Colombier 
741*00d97012SDavid du Colombier static void
all_successors(int n,OneState * cur)742*00d97012SDavid du Colombier all_successors(int n, OneState *cur)
743*00d97012SDavid du Colombier {	int i, j = 0;
744*00d97012SDavid du Colombier 
745*00d97012SDavid du Colombier 	if (n >= nclaims)
746*00d97012SDavid du Colombier 	{	create_transition(cur, find_state(Nst));
747*00d97012SDavid du Colombier 	} else
748*00d97012SDavid du Colombier 	{	i = cur->combo[n];
749*00d97012SDavid du Colombier 		for (;;)
750*00d97012SDavid du Colombier 		{	j = nxt_trans(n, i, j);
751*00d97012SDavid du Colombier 			if (j < 0) break;
752*00d97012SDavid du Colombier 			Nst[n] = j;
753*00d97012SDavid du Colombier 			all_successors(n+1, cur);
754*00d97012SDavid du Colombier 			j++;
755*00d97012SDavid du Colombier 	}	}
756*00d97012SDavid du Colombier }
757*00d97012SDavid du Colombier 
758*00d97012SDavid du Colombier static void
gen_product(void)759*00d97012SDavid du Colombier gen_product(void)
760*00d97012SDavid du Colombier {	OneState *cur_st;
761*00d97012SDavid du Colombier 	SQueue *q;
762*00d97012SDavid du Colombier 
763*00d97012SDavid du Colombier 	find_state(Ist);	/* create initial state */
764*00d97012SDavid du Colombier 
765*00d97012SDavid du Colombier 	while (sq)
766*00d97012SDavid du Colombier 	{	if (in_stack(sq, sd))
767*00d97012SDavid du Colombier 		{	sq = sq->nxt;
768*00d97012SDavid du Colombier 			continue;
769*00d97012SDavid du Colombier 		}
770*00d97012SDavid du Colombier 		cur_st = &(sq->state);
771*00d97012SDavid du Colombier 
772*00d97012SDavid du Colombier 		q = sq;
773*00d97012SDavid du Colombier 		sq = sq->nxt;	/* delete from sq stack */
774*00d97012SDavid du Colombier 		q->nxt = sd;	/* and move to done stack */
775*00d97012SDavid du Colombier 		sd = q;
776*00d97012SDavid du Colombier 
777*00d97012SDavid du Colombier 		all_successors(0, cur_st);
778*00d97012SDavid du Colombier 	}
779*00d97012SDavid du Colombier 	/* all states are in the sd queue now */
780*00d97012SDavid du Colombier 	prune_dead();
781*00d97012SDavid du Colombier 	explore_product();	/* check if added accept-self-loops are reachable */
782*00d97012SDavid du Colombier 	prune_accept();
783*00d97012SDavid du Colombier 
784*00d97012SDavid du Colombier 	if (verbose)
785*00d97012SDavid du Colombier 	{	print_raw();
786*00d97012SDavid du Colombier 	}
787*00d97012SDavid du Colombier 
788*00d97012SDavid du Colombier 	/* PM: merge states with identical successor lists */
789*00d97012SDavid du Colombier 
790*00d97012SDavid du Colombier 	/* all outgoing transitions from accept-states
791*00d97012SDavid du Colombier 	   from claim n in copy n connect to states in copy (n+1)%nclaims
792*00d97012SDavid du Colombier 	   only accept states from claim 0 in copy 0 are true accept states
793*00d97012SDavid du Colombier 	   in the product
794*00d97012SDavid du Colombier 
795*00d97012SDavid du Colombier 	   PM: what about claims that have no accept states (e.g., restrictions)
796*00d97012SDavid du Colombier 	*/
797*00d97012SDavid du Colombier 
798*00d97012SDavid du Colombier 	for (unfolding = 0; unfolding < nclaims; unfolding++)
799*00d97012SDavid du Colombier 	{	print_product();
800*00d97012SDavid du Colombier 	}
801*00d97012SDavid du Colombier }
802*00d97012SDavid du Colombier 
803*00d97012SDavid du Colombier static void
t_record(int n,Element * e,Element * g)804*00d97012SDavid du Colombier t_record(int n, Element *e, Element *g)
805*00d97012SDavid du Colombier {	int from = e->seqno, upto = g?g->seqno:0;
806*00d97012SDavid du Colombier 
807*00d97012SDavid du Colombier 	assert(from >= 0 && from < nst);
808*00d97012SDavid du Colombier 	assert(upto >= 0 && upto < nst);
809*00d97012SDavid du Colombier 
810*00d97012SDavid du Colombier 	matrix[n][from][upto] = e;
811*00d97012SDavid du Colombier 	reached[n][upto] |= 1;
812*00d97012SDavid du Colombier }
813*00d97012SDavid du Colombier 
814*00d97012SDavid du Colombier static void
get_sub(int n,Element * e)815*00d97012SDavid du Colombier get_sub(int n, Element *e)
816*00d97012SDavid du Colombier {
817*00d97012SDavid du Colombier 	if (e->n->ntyp == D_STEP
818*00d97012SDavid du Colombier 	||  e->n->ntyp == ATOMIC)
819*00d97012SDavid du Colombier 	{	fatal("atomic or d_step in never claim product", 0);
820*00d97012SDavid du Colombier 	}
821*00d97012SDavid du Colombier 	/* NON_ATOMIC */
822*00d97012SDavid du Colombier 	e->n->sl->this->last->nxt = e->nxt;
823*00d97012SDavid du Colombier 	get_seq(n, e->n->sl->this);
824*00d97012SDavid du Colombier 
825*00d97012SDavid du Colombier 	t_record(n, e, e->n->sl->this->frst);
826*00d97012SDavid du Colombier 
827*00d97012SDavid du Colombier }
828*00d97012SDavid du Colombier 
829*00d97012SDavid du Colombier static void
set_el(int n,Element * e)830*00d97012SDavid du Colombier set_el(int n, Element *e)
831*00d97012SDavid du Colombier {	Element *g;
832*00d97012SDavid du Colombier 
833*00d97012SDavid du Colombier 	if (e->n->ntyp == '@')	/* change to self-loop */
834*00d97012SDavid du Colombier 	{	e->n->ntyp = CONST;
835*00d97012SDavid du Colombier 		e->n->val = 1;	/* true */
836*00d97012SDavid du Colombier 		e->nxt = e;
837*00d97012SDavid du Colombier 		g = e;
838*00d97012SDavid du Colombier 		mk_accepting(n, e);
839*00d97012SDavid du Colombier 	} else
840*00d97012SDavid du Colombier 
841*00d97012SDavid du Colombier 	if (e->n->ntyp == GOTO)
842*00d97012SDavid du Colombier 	{	g = get_lab(e->n, 1);
843*00d97012SDavid du Colombier 		g = huntele(g, e->status, -1);
844*00d97012SDavid du Colombier 	} else if (e->nxt)
845*00d97012SDavid du Colombier 	{	g = huntele(e->nxt, e->status, -1);
846*00d97012SDavid du Colombier 	} else
847*00d97012SDavid du Colombier 	{	g = NULL;
848*00d97012SDavid du Colombier 	}
849*00d97012SDavid du Colombier 
850*00d97012SDavid du Colombier 	t_record(n, e, g);
851*00d97012SDavid du Colombier }
852*00d97012SDavid du Colombier 
853*00d97012SDavid du Colombier static void
get_seq(int n,Sequence * s)854*00d97012SDavid du Colombier get_seq(int n, Sequence *s)
855*00d97012SDavid du Colombier {	SeqList *h;
856*00d97012SDavid du Colombier 	Element *e;
857*00d97012SDavid du Colombier 
858*00d97012SDavid du Colombier 	e = huntele(s->frst, s->frst->status, -1);
859*00d97012SDavid du Colombier 	for ( ; e; e = e->nxt)
860*00d97012SDavid du Colombier 	{	if (e->status & DONE)
861*00d97012SDavid du Colombier 		{	goto checklast;
862*00d97012SDavid du Colombier 		}
863*00d97012SDavid du Colombier 		e->status |= DONE;
864*00d97012SDavid du Colombier 
865*00d97012SDavid du Colombier 		if (e->n->ntyp == UNLESS)
866*00d97012SDavid du Colombier 		{	fatal("unless stmnt in never claim product", 0);
867*00d97012SDavid du Colombier 		}
868*00d97012SDavid du Colombier 
869*00d97012SDavid du Colombier 		if (e->sub)	/* IF or DO */
870*00d97012SDavid du Colombier 		{	Lextok *x = NULL;
871*00d97012SDavid du Colombier 			Lextok *y = NULL;
872*00d97012SDavid du Colombier 			Lextok *haselse = NULL;
873*00d97012SDavid du Colombier 
874*00d97012SDavid du Colombier 			for (h = e->sub; h; h = h->nxt)
875*00d97012SDavid du Colombier 			{	Lextok *t = h->this->frst->n;
876*00d97012SDavid du Colombier 				if (t->ntyp == ELSE)
877*00d97012SDavid du Colombier 				{	if (verbose&64) printf("else at line %d\n", t->ln);
878*00d97012SDavid du Colombier 					haselse = t;
879*00d97012SDavid du Colombier 					continue;
880*00d97012SDavid du Colombier 				}
881*00d97012SDavid du Colombier 				if (t->ntyp != 'c')
882*00d97012SDavid du Colombier 				{	fatal("product, 'else' combined with non-condition", 0);
883*00d97012SDavid du Colombier 				}
884*00d97012SDavid du Colombier 
885*00d97012SDavid du Colombier 				if (t->lft->ntyp == CONST	/* true */
886*00d97012SDavid du Colombier 				&&  t->lft->val == 1
887*00d97012SDavid du Colombier 				&&  y == NULL)
888*00d97012SDavid du Colombier 				{	y = nn(ZN, CONST, ZN, ZN);
889*00d97012SDavid du Colombier 					y->val = 0;
890*00d97012SDavid du Colombier 				} else
891*00d97012SDavid du Colombier 				{	if (!x)
892*00d97012SDavid du Colombier 						x = t;
893*00d97012SDavid du Colombier 					else
894*00d97012SDavid du Colombier 						x = nn(ZN, OR, x, t);
895*00d97012SDavid du Colombier 					if (verbose&64)
896*00d97012SDavid du Colombier 					{	wrap_text(" [", x, "]\n");
897*00d97012SDavid du Colombier 			}	}	}
898*00d97012SDavid du Colombier 			if (haselse)
899*00d97012SDavid du Colombier 			{	if (!y)
900*00d97012SDavid du Colombier 				{	y = nn(ZN, '!', x, ZN);
901*00d97012SDavid du Colombier 				}
902*00d97012SDavid du Colombier 				if (verbose&64)
903*00d97012SDavid du Colombier 				{	wrap_text(" [else: ", y, "]\n");
904*00d97012SDavid du Colombier 				}
905*00d97012SDavid du Colombier 				haselse->ntyp = 'c';	/* replace else */
906*00d97012SDavid du Colombier 				haselse->lft = y;
907*00d97012SDavid du Colombier 			}
908*00d97012SDavid du Colombier 
909*00d97012SDavid du Colombier 			for (h = e->sub; h; h = h->nxt)
910*00d97012SDavid du Colombier 			{	t_record(n, e, h->this->frst);
911*00d97012SDavid du Colombier 				get_seq(n, h->this);
912*00d97012SDavid du Colombier 			}
913*00d97012SDavid du Colombier 		} else
914*00d97012SDavid du Colombier 		{	if (e->n->ntyp == ATOMIC
915*00d97012SDavid du Colombier 			||  e->n->ntyp == D_STEP
916*00d97012SDavid du Colombier 			||  e->n->ntyp == NON_ATOMIC)
917*00d97012SDavid du Colombier 			{	get_sub(n, e);
918*00d97012SDavid du Colombier 			} else
919*00d97012SDavid du Colombier 			{	set_el(n, e);
920*00d97012SDavid du Colombier 			}
921*00d97012SDavid du Colombier 		}
922*00d97012SDavid du Colombier checklast:	if (e == s->last)
923*00d97012SDavid du Colombier 			break;
924*00d97012SDavid du Colombier 	}
925*00d97012SDavid du Colombier }
926