xref: /plan9-contrib/sys/src/cmd/spin/tl_buchi.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
17dd7cddfSDavid du Colombier /***** tl_spin: tl_buchi.c *****/
27dd7cddfSDavid du Colombier 
3*de2caf28SDavid du Colombier /*
4*de2caf28SDavid du Colombier  * This file is part of the public release of Spin. It is subject to the
5*de2caf28SDavid du Colombier  * terms in the LICENSE file that is included in this source directory.
6*de2caf28SDavid du Colombier  * Tool documentation is available at http://spinroot.com
7*de2caf28SDavid du Colombier  *
8*de2caf28SDavid du Colombier  * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
9*de2caf28SDavid du Colombier  * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
10*de2caf28SDavid du Colombier  */
117dd7cddfSDavid du Colombier 
127dd7cddfSDavid du Colombier #include "tl.h"
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier extern int tl_verbose, tl_clutter, Total, Max_Red;
1500d97012SDavid du Colombier extern char *claim_name;
16*de2caf28SDavid du Colombier extern void  put_uform(void);
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier FILE	*tl_out;	/* if standalone: = stdout; */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier typedef struct Transition {
217dd7cddfSDavid du Colombier 	Symbol *name;
227dd7cddfSDavid du Colombier 	Node *cond;
237dd7cddfSDavid du Colombier 	int redundant, merged, marked;
247dd7cddfSDavid du Colombier 	struct Transition *nxt;
257dd7cddfSDavid du Colombier } Transition;
267dd7cddfSDavid du Colombier 
277dd7cddfSDavid du Colombier typedef struct State {
287dd7cddfSDavid du Colombier 	Symbol	*name;
297dd7cddfSDavid du Colombier 	Transition *trans;
307dd7cddfSDavid du Colombier 	Graph	*colors;
317dd7cddfSDavid du Colombier 	unsigned char redundant;
327dd7cddfSDavid du Colombier 	unsigned char accepting;
337dd7cddfSDavid du Colombier 	unsigned char reachable;
347dd7cddfSDavid du Colombier 	struct State *nxt;
357dd7cddfSDavid du Colombier } State;
367dd7cddfSDavid du Colombier 
377dd7cddfSDavid du Colombier static State *never = (State *) 0;
387dd7cddfSDavid du Colombier static int hitsall;
397dd7cddfSDavid du Colombier 
4000d97012SDavid du Colombier void
ini_buchi(void)4100d97012SDavid du Colombier ini_buchi(void)
4200d97012SDavid du Colombier {
4300d97012SDavid du Colombier 	never = (State *) 0;
4400d97012SDavid du Colombier 	hitsall = 0;
4500d97012SDavid du Colombier }
4600d97012SDavid du Colombier 
477dd7cddfSDavid du Colombier static int
sametrans(Transition * s,Transition * t)487dd7cddfSDavid du Colombier sametrans(Transition *s, Transition *t)
497dd7cddfSDavid du Colombier {
507dd7cddfSDavid du Colombier 	if (strcmp(s->name->name, t->name->name) != 0)
517dd7cddfSDavid du Colombier 		return 0;
527dd7cddfSDavid du Colombier 	return isequal(s->cond, t->cond);
537dd7cddfSDavid du Colombier }
547dd7cddfSDavid du Colombier 
557dd7cddfSDavid du Colombier static Node *
Prune(Node * p)567dd7cddfSDavid du Colombier Prune(Node *p)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier 	if (p)
597dd7cddfSDavid du Colombier 	switch (p->ntyp) {
607dd7cddfSDavid du Colombier 	case PREDICATE:
617dd7cddfSDavid du Colombier 	case NOT:
627dd7cddfSDavid du Colombier 	case FALSE:
637dd7cddfSDavid du Colombier 	case TRUE:
647dd7cddfSDavid du Colombier #ifdef NXT
657dd7cddfSDavid du Colombier 	case NEXT:
667dd7cddfSDavid du Colombier #endif
67*de2caf28SDavid du Colombier 	case CEXPR:
687dd7cddfSDavid du Colombier 		return p;
697dd7cddfSDavid du Colombier 	case OR:
707dd7cddfSDavid du Colombier 		p->lft = Prune(p->lft);
717dd7cddfSDavid du Colombier 		if (!p->lft)
727dd7cddfSDavid du Colombier 		{	releasenode(1, p->rgt);
737dd7cddfSDavid du Colombier 			return ZN;
747dd7cddfSDavid du Colombier 		}
757dd7cddfSDavid du Colombier 		p->rgt = Prune(p->rgt);
767dd7cddfSDavid du Colombier 		if (!p->rgt)
777dd7cddfSDavid du Colombier 		{	releasenode(1, p->lft);
787dd7cddfSDavid du Colombier 			return ZN;
797dd7cddfSDavid du Colombier 		}
807dd7cddfSDavid du Colombier 		return p;
817dd7cddfSDavid du Colombier 	case AND:
827dd7cddfSDavid du Colombier 		p->lft = Prune(p->lft);
837dd7cddfSDavid du Colombier 		if (!p->lft)
847dd7cddfSDavid du Colombier 			return Prune(p->rgt);
857dd7cddfSDavid du Colombier 		p->rgt = Prune(p->rgt);
867dd7cddfSDavid du Colombier 		if (!p->rgt)
877dd7cddfSDavid du Colombier 			return p->lft;
887dd7cddfSDavid du Colombier 		return p;
897dd7cddfSDavid du Colombier 	}
907dd7cddfSDavid du Colombier 	releasenode(1, p);
917dd7cddfSDavid du Colombier 	return ZN;
927dd7cddfSDavid du Colombier }
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier static State *
findstate(char * nm)957dd7cddfSDavid du Colombier findstate(char *nm)
967dd7cddfSDavid du Colombier {	State *b;
977dd7cddfSDavid du Colombier 	for (b = never; b; b = b->nxt)
987dd7cddfSDavid du Colombier 		if (!strcmp(b->name->name, nm))
997dd7cddfSDavid du Colombier 			return b;
1007dd7cddfSDavid du Colombier 	if (strcmp(nm, "accept_all"))
1017dd7cddfSDavid du Colombier 	{	if (strncmp(nm, "accept", 6))
1027dd7cddfSDavid du Colombier 		{	int i; char altnm[64];
1037dd7cddfSDavid du Colombier 			for (i = 0; i < 64; i++)
1047dd7cddfSDavid du Colombier 				if (nm[i] == '_')
1057dd7cddfSDavid du Colombier 					break;
1067dd7cddfSDavid du Colombier 			if (i >= 64)
1077dd7cddfSDavid du Colombier 				Fatal("name too long %s", nm);
1087dd7cddfSDavid du Colombier 			sprintf(altnm, "accept%s", &nm[i]);
1097dd7cddfSDavid du Colombier 			return findstate(altnm);
1107dd7cddfSDavid du Colombier 		}
1117dd7cddfSDavid du Colombier 	/*	Fatal("buchi: no state %s", nm); */
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 	return (State *) 0;
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier static void
Dfs(State * b)1177dd7cddfSDavid du Colombier Dfs(State *b)
1187dd7cddfSDavid du Colombier {	Transition *t;
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier 	if (!b || b->reachable) return;
1217dd7cddfSDavid du Colombier 	b->reachable = 1;
1227dd7cddfSDavid du Colombier 
1237dd7cddfSDavid du Colombier 	if (b->redundant)
124312a1df1SDavid du Colombier 		printf("/* redundant state %s */\n",
1257dd7cddfSDavid du Colombier 			b->name->name);
1267dd7cddfSDavid du Colombier 	for (t = b->trans; t; t = t->nxt)
1277dd7cddfSDavid du Colombier 	{	if (!t->redundant)
1287dd7cddfSDavid du Colombier 		{	Dfs(findstate(t->name->name));
1297dd7cddfSDavid du Colombier 			if (!hitsall
1307dd7cddfSDavid du Colombier 			&&  strcmp(t->name->name, "accept_all") == 0)
1317dd7cddfSDavid du Colombier 				hitsall = 1;
1327dd7cddfSDavid du Colombier 		}
1337dd7cddfSDavid du Colombier 	}
1347dd7cddfSDavid du Colombier }
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier void
retarget(char * from,char * to)1377dd7cddfSDavid du Colombier retarget(char *from, char *to)
1387dd7cddfSDavid du Colombier {	State *b;
1397dd7cddfSDavid du Colombier 	Transition *t;
1407dd7cddfSDavid du Colombier 	Symbol *To = tl_lookup(to);
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier 	if (tl_verbose) printf("replace %s with %s\n", from, to);
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier 	for (b = never; b; b = b->nxt)
1457dd7cddfSDavid du Colombier 	{	if (!strcmp(b->name->name, from))
146312a1df1SDavid du Colombier 			b->redundant = 1;
147312a1df1SDavid du Colombier 		else
1487dd7cddfSDavid du Colombier 		for (t = b->trans; t; t = t->nxt)
1497dd7cddfSDavid du Colombier 		{	if (!strcmp(t->name->name, from))
1507dd7cddfSDavid du Colombier 				t->name = To;
1517dd7cddfSDavid du Colombier 	}	}
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier #ifdef NXT
1557dd7cddfSDavid du Colombier static Node *
nonxt(Node * n)1567dd7cddfSDavid du Colombier nonxt(Node *n)
1577dd7cddfSDavid du Colombier {
1587dd7cddfSDavid du Colombier 	switch (n->ntyp) {
1597dd7cddfSDavid du Colombier 	case U_OPER:
1607dd7cddfSDavid du Colombier 	case V_OPER:
1617dd7cddfSDavid du Colombier 	case NEXT:
1627dd7cddfSDavid du Colombier 		return ZN;
1637dd7cddfSDavid du Colombier 	case OR:
1647dd7cddfSDavid du Colombier 		n->lft = nonxt(n->lft);
1657dd7cddfSDavid du Colombier 		n->rgt = nonxt(n->rgt);
1667dd7cddfSDavid du Colombier 		if (!n->lft || !n->rgt)
1677dd7cddfSDavid du Colombier 			return True;
1687dd7cddfSDavid du Colombier 		return n;
1697dd7cddfSDavid du Colombier 	case AND:
1707dd7cddfSDavid du Colombier 		n->lft = nonxt(n->lft);
1717dd7cddfSDavid du Colombier 		n->rgt = nonxt(n->rgt);
1727dd7cddfSDavid du Colombier 		if (!n->lft)
1737dd7cddfSDavid du Colombier 		{	if (!n->rgt)
1747dd7cddfSDavid du Colombier 				n = ZN;
1757dd7cddfSDavid du Colombier 			else
1767dd7cddfSDavid du Colombier 				n = n->rgt;
1777dd7cddfSDavid du Colombier 		} else if (!n->rgt)
1787dd7cddfSDavid du Colombier 			n = n->lft;
1797dd7cddfSDavid du Colombier 		return n;
1807dd7cddfSDavid du Colombier 	}
1817dd7cddfSDavid du Colombier 	return n;
1827dd7cddfSDavid du Colombier }
1837dd7cddfSDavid du Colombier #endif
1847dd7cddfSDavid du Colombier 
1857dd7cddfSDavid du Colombier static Node *
combination(Node * s,Node * t)1867dd7cddfSDavid du Colombier combination(Node *s, Node *t)
1877dd7cddfSDavid du Colombier {	Node *nc;
1887dd7cddfSDavid du Colombier #ifdef NXT
1897dd7cddfSDavid du Colombier 	Node *a = nonxt(s);
1907dd7cddfSDavid du Colombier 	Node *b = nonxt(t);
191312a1df1SDavid du Colombier 
1927dd7cddfSDavid du Colombier 	if (tl_verbose)
1937dd7cddfSDavid du Colombier 	{	printf("\tnonxtA: "); dump(a);
1947dd7cddfSDavid du Colombier 		printf("\n\tnonxtB: "); dump(b);
1957dd7cddfSDavid du Colombier 		printf("\n");
1967dd7cddfSDavid du Colombier 	}
1977dd7cddfSDavid du Colombier 	/* if there's only a X(f), its equivalent to true */
1987dd7cddfSDavid du Colombier 	if (!a || !b)
1997dd7cddfSDavid du Colombier 		nc = True;
2007dd7cddfSDavid du Colombier 	else
2017dd7cddfSDavid du Colombier 		nc = tl_nn(OR, a, b);
2027dd7cddfSDavid du Colombier #else
2037dd7cddfSDavid du Colombier 	nc = tl_nn(OR, s, t);
2047dd7cddfSDavid du Colombier #endif
2057dd7cddfSDavid du Colombier 	if (tl_verbose)
2067dd7cddfSDavid du Colombier 	{	printf("\tcombo: "); dump(nc);
2077dd7cddfSDavid du Colombier 		printf("\n");
2087dd7cddfSDavid du Colombier 	}
2097dd7cddfSDavid du Colombier 	return nc;
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier 
2127dd7cddfSDavid du Colombier Node *
unclutter(Node * n,char * snm)2137dd7cddfSDavid du Colombier unclutter(Node *n, char *snm)
2147dd7cddfSDavid du Colombier {	Node *t, *s, *v, *u;
2157dd7cddfSDavid du Colombier 	Symbol *w;
2167dd7cddfSDavid du Colombier 
2177dd7cddfSDavid du Colombier 	/* check only simple cases like !q && q */
2187dd7cddfSDavid du Colombier 	for (t = n; t; t = t->rgt)
2197dd7cddfSDavid du Colombier 	{	if (t->rgt)
2207dd7cddfSDavid du Colombier 		{	if (t->ntyp != AND || !t->lft)
2217dd7cddfSDavid du Colombier 				return n;
2227dd7cddfSDavid du Colombier 			if (t->lft->ntyp != PREDICATE
2237dd7cddfSDavid du Colombier #ifdef NXT
2247dd7cddfSDavid du Colombier 			&&  t->lft->ntyp != NEXT
2257dd7cddfSDavid du Colombier #endif
2267dd7cddfSDavid du Colombier 			&&  t->lft->ntyp != NOT)
2277dd7cddfSDavid du Colombier 				return n;
2287dd7cddfSDavid du Colombier 		} else
2297dd7cddfSDavid du Colombier 		{	if (t->ntyp != PREDICATE
2307dd7cddfSDavid du Colombier #ifdef NXT
2317dd7cddfSDavid du Colombier 			&&  t->ntyp != NEXT
2327dd7cddfSDavid du Colombier #endif
2337dd7cddfSDavid du Colombier 			&&  t->ntyp != NOT)
2347dd7cddfSDavid du Colombier 				return n;
2357dd7cddfSDavid du Colombier 		}
2367dd7cddfSDavid du Colombier 	}
2377dd7cddfSDavid du Colombier 
2387dd7cddfSDavid du Colombier 	for (t = n; t; t = t->rgt)
2397dd7cddfSDavid du Colombier 	{	if (t->rgt)
2407dd7cddfSDavid du Colombier 			v = t->lft;
2417dd7cddfSDavid du Colombier 		else
2427dd7cddfSDavid du Colombier 			v = t;
2437dd7cddfSDavid du Colombier 		if (v->ntyp == NOT
2447dd7cddfSDavid du Colombier 		&&  v->lft->ntyp == PREDICATE)
2457dd7cddfSDavid du Colombier 		{	w = v->lft->sym;
2467dd7cddfSDavid du Colombier 			for (s = n; s; s = s->rgt)
2477dd7cddfSDavid du Colombier 			{	if (s == t) continue;
2487dd7cddfSDavid du Colombier 				if (s->rgt)
2497dd7cddfSDavid du Colombier 					u = s->lft;
2507dd7cddfSDavid du Colombier 				else
2517dd7cddfSDavid du Colombier 					u = s;
2527dd7cddfSDavid du Colombier 				if (u->ntyp == PREDICATE
2537dd7cddfSDavid du Colombier 				&&  strcmp(u->sym->name, w->name) == 0)
2547dd7cddfSDavid du Colombier 				{	if (tl_verbose)
2557dd7cddfSDavid du Colombier 					{	printf("BINGO %s:\t", snm);
2567dd7cddfSDavid du Colombier 						dump(n);
2577dd7cddfSDavid du Colombier 						printf("\n");
2587dd7cddfSDavid du Colombier 					}
2597dd7cddfSDavid du Colombier 					return False;
2607dd7cddfSDavid du Colombier 				}
2617dd7cddfSDavid du Colombier 			}
2627dd7cddfSDavid du Colombier 	}	}
2637dd7cddfSDavid du Colombier 	return n;
2647dd7cddfSDavid du Colombier }
2657dd7cddfSDavid du Colombier 
2667dd7cddfSDavid du Colombier static void
clutter(void)2677dd7cddfSDavid du Colombier clutter(void)
2687dd7cddfSDavid du Colombier {	State *p;
2697dd7cddfSDavid du Colombier 	Transition *s;
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier 	for (p = never; p; p = p->nxt)
2727dd7cddfSDavid du Colombier 	for (s = p->trans; s; s = s->nxt)
2737dd7cddfSDavid du Colombier 	{	s->cond = unclutter(s->cond, p->name->name);
2747dd7cddfSDavid du Colombier 		if (s->cond
2757dd7cddfSDavid du Colombier 		&&  s->cond->ntyp == FALSE)
2767dd7cddfSDavid du Colombier 		{	if (s != p->trans
2777dd7cddfSDavid du Colombier 			||  s->nxt)
2787dd7cddfSDavid du Colombier 				s->redundant = 1;
2797dd7cddfSDavid du Colombier 		}
2807dd7cddfSDavid du Colombier 	}
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier 
2837dd7cddfSDavid du Colombier static void
showtrans(State * a)2847dd7cddfSDavid du Colombier showtrans(State *a)
2857dd7cddfSDavid du Colombier {	Transition *s;
2867dd7cddfSDavid du Colombier 
2877dd7cddfSDavid du Colombier 	for (s = a->trans; s; s = s->nxt)
2887dd7cddfSDavid du Colombier 	{	printf("%s ", s->name?s->name->name:"-");
2897dd7cddfSDavid du Colombier 		dump(s->cond);
2907dd7cddfSDavid du Colombier 		printf(" %d %d %d\n", s->redundant, s->merged, s->marked);
2917dd7cddfSDavid du Colombier 	}
2927dd7cddfSDavid du Colombier }
2937dd7cddfSDavid du Colombier 
2947dd7cddfSDavid du Colombier static int
mergetrans(void)295312a1df1SDavid du Colombier mergetrans(void)
2967dd7cddfSDavid du Colombier {	State *b;
2977dd7cddfSDavid du Colombier 	Transition *s, *t;
2987dd7cddfSDavid du Colombier 	Node *nc; int cnt = 0;
2997dd7cddfSDavid du Colombier 
3007dd7cddfSDavid du Colombier 	for (b = never; b; b = b->nxt)
3017dd7cddfSDavid du Colombier 	{	if (!b->reachable) continue;
3027dd7cddfSDavid du Colombier 
3037dd7cddfSDavid du Colombier 		for (s = b->trans; s; s = s->nxt)
3047dd7cddfSDavid du Colombier 		{	if (s->redundant) continue;
3057dd7cddfSDavid du Colombier 
3067dd7cddfSDavid du Colombier 			for (t = s->nxt; t; t = t->nxt)
3077dd7cddfSDavid du Colombier 			if (!t->redundant
3087dd7cddfSDavid du Colombier 			&&  !strcmp(s->name->name, t->name->name))
3097dd7cddfSDavid du Colombier 			{	if (tl_verbose)
3107dd7cddfSDavid du Colombier 				{	printf("===\nstate %s, trans to %s redundant\n",
3117dd7cddfSDavid du Colombier 					b->name->name, s->name->name);
3127dd7cddfSDavid du Colombier 					showtrans(b);
3137dd7cddfSDavid du Colombier 					printf(" conditions ");
3147dd7cddfSDavid du Colombier 					dump(s->cond); printf(" <-> ");
3157dd7cddfSDavid du Colombier 					dump(t->cond); printf("\n");
3167dd7cddfSDavid du Colombier 				}
3177dd7cddfSDavid du Colombier 
3187dd7cddfSDavid du Colombier 				if (!s->cond) /* same as T */
3197dd7cddfSDavid du Colombier 				{	releasenode(1, t->cond); /* T or t */
3207dd7cddfSDavid du Colombier 					nc = True;
3217dd7cddfSDavid du Colombier 				} else if (!t->cond)
3227dd7cddfSDavid du Colombier 				{	releasenode(1, s->cond);
3237dd7cddfSDavid du Colombier 					nc = True;
3247dd7cddfSDavid du Colombier 				} else
3257dd7cddfSDavid du Colombier 				{	nc = combination(s->cond, t->cond);
3267dd7cddfSDavid du Colombier 				}
3277dd7cddfSDavid du Colombier 				t->cond = rewrite(nc);
3287dd7cddfSDavid du Colombier 				t->merged = 1;
3297dd7cddfSDavid du Colombier 				s->redundant = 1;
3307dd7cddfSDavid du Colombier 				cnt++;
3317dd7cddfSDavid du Colombier 				break;
3327dd7cddfSDavid du Colombier 	}	}	}
3337dd7cddfSDavid du Colombier 	return cnt;
3347dd7cddfSDavid du Colombier }
3357dd7cddfSDavid du Colombier 
3367dd7cddfSDavid du Colombier static int
all_trans_match(State * a,State * b)3377dd7cddfSDavid du Colombier all_trans_match(State *a, State *b)
3387dd7cddfSDavid du Colombier {	Transition *s, *t;
3397dd7cddfSDavid du Colombier 	int found, result = 0;
3407dd7cddfSDavid du Colombier 
3417dd7cddfSDavid du Colombier 	if (a->accepting != b->accepting)
3427dd7cddfSDavid du Colombier 		goto done;
3437dd7cddfSDavid du Colombier 
3447dd7cddfSDavid du Colombier 	for (s = a->trans; s; s = s->nxt)
3457dd7cddfSDavid du Colombier 	{	if (s->redundant) continue;
3467dd7cddfSDavid du Colombier 		found = 0;
3477dd7cddfSDavid du Colombier 		for (t = b->trans; t; t = t->nxt)
3487dd7cddfSDavid du Colombier 		{	if (t->redundant) continue;
3497dd7cddfSDavid du Colombier 			if (sametrans(s, t))
3507dd7cddfSDavid du Colombier 			{	found = 1;
3517dd7cddfSDavid du Colombier 				t->marked = 1;
3527dd7cddfSDavid du Colombier 				break;
3537dd7cddfSDavid du Colombier 		}	}
3547dd7cddfSDavid du Colombier 		if (!found)
3557dd7cddfSDavid du Colombier 			goto done;
3567dd7cddfSDavid du Colombier 	}
3577dd7cddfSDavid du Colombier 	for (s = b->trans; s; s = s->nxt)
3587dd7cddfSDavid du Colombier 	{	if (s->redundant || s->marked) continue;
3597dd7cddfSDavid du Colombier 		found = 0;
3607dd7cddfSDavid du Colombier 		for (t = a->trans; t; t = t->nxt)
3617dd7cddfSDavid du Colombier 		{	if (t->redundant) continue;
3627dd7cddfSDavid du Colombier 			if (sametrans(s, t))
3637dd7cddfSDavid du Colombier 			{	found = 1;
3647dd7cddfSDavid du Colombier 				break;
3657dd7cddfSDavid du Colombier 		}	}
3667dd7cddfSDavid du Colombier 		if (!found)
3677dd7cddfSDavid du Colombier 			goto done;
3687dd7cddfSDavid du Colombier 	}
3697dd7cddfSDavid du Colombier 	result = 1;
3707dd7cddfSDavid du Colombier done:
3717dd7cddfSDavid du Colombier 	for (s = b->trans; s; s = s->nxt)
3727dd7cddfSDavid du Colombier 		s->marked = 0;
3737dd7cddfSDavid du Colombier 	return result;
3747dd7cddfSDavid du Colombier }
375312a1df1SDavid du Colombier 
376312a1df1SDavid du Colombier #ifndef NO_OPT
3777dd7cddfSDavid du Colombier #define BUCKY
378312a1df1SDavid du Colombier #endif
379312a1df1SDavid du Colombier 
3807dd7cddfSDavid du Colombier #ifdef BUCKY
3817dd7cddfSDavid du Colombier static int
all_bucky(State * a,State * b)3827dd7cddfSDavid du Colombier all_bucky(State *a, State *b)
3837dd7cddfSDavid du Colombier {	Transition *s, *t;
3847dd7cddfSDavid du Colombier 	int found, result = 0;
3857dd7cddfSDavid du Colombier 
3867dd7cddfSDavid du Colombier 	for (s = a->trans; s; s = s->nxt)
3877dd7cddfSDavid du Colombier 	{	if (s->redundant) continue;
3887dd7cddfSDavid du Colombier 		found = 0;
3897dd7cddfSDavid du Colombier 		for (t = b->trans; t; t = t->nxt)
3907dd7cddfSDavid du Colombier 		{	if (t->redundant) continue;
3917dd7cddfSDavid du Colombier 
3927dd7cddfSDavid du Colombier 			if (isequal(s->cond, t->cond))
3937dd7cddfSDavid du Colombier 			{	if (strcmp(s->name->name, b->name->name) == 0
3947dd7cddfSDavid du Colombier 				&&  strcmp(t->name->name, a->name->name) == 0)
3957dd7cddfSDavid du Colombier 				{	found = 1;	/* they point to each other */
3967dd7cddfSDavid du Colombier 					t->marked = 1;
3977dd7cddfSDavid du Colombier 					break;
3987dd7cddfSDavid du Colombier 				}
3997dd7cddfSDavid du Colombier 				if (strcmp(s->name->name, t->name->name) == 0
4007dd7cddfSDavid du Colombier 				&&  strcmp(s->name->name, "accept_all") == 0)
4017dd7cddfSDavid du Colombier 				{	found = 1;
4027dd7cddfSDavid du Colombier 					t->marked = 1;
4037dd7cddfSDavid du Colombier 					break;
4047dd7cddfSDavid du Colombier 				/* same exit from which there is no return */
4057dd7cddfSDavid du Colombier 				}
4067dd7cddfSDavid du Colombier 			}
4077dd7cddfSDavid du Colombier 		}
4087dd7cddfSDavid du Colombier 		if (!found)
4097dd7cddfSDavid du Colombier 			goto done;
4107dd7cddfSDavid du Colombier 	}
4117dd7cddfSDavid du Colombier 	for (s = b->trans; s; s = s->nxt)
4127dd7cddfSDavid du Colombier 	{	if (s->redundant || s->marked) continue;
4137dd7cddfSDavid du Colombier 		found = 0;
4147dd7cddfSDavid du Colombier 		for (t = a->trans; t; t = t->nxt)
4157dd7cddfSDavid du Colombier 		{	if (t->redundant) continue;
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier 			if (isequal(s->cond, t->cond))
4187dd7cddfSDavid du Colombier 			{	if (strcmp(s->name->name, a->name->name) == 0
4197dd7cddfSDavid du Colombier 				&&  strcmp(t->name->name, b->name->name) == 0)
4207dd7cddfSDavid du Colombier 				{	found = 1;
4217dd7cddfSDavid du Colombier 					t->marked = 1;
4227dd7cddfSDavid du Colombier 					break;
4237dd7cddfSDavid du Colombier 				}
4247dd7cddfSDavid du Colombier 				if (strcmp(s->name->name, t->name->name) == 0
4257dd7cddfSDavid du Colombier 				&&  strcmp(s->name->name, "accept_all") == 0)
4267dd7cddfSDavid du Colombier 				{	found = 1;
4277dd7cddfSDavid du Colombier 					t->marked = 1;
4287dd7cddfSDavid du Colombier 					break;
4297dd7cddfSDavid du Colombier 				}
4307dd7cddfSDavid du Colombier 			}
4317dd7cddfSDavid du Colombier 		}
4327dd7cddfSDavid du Colombier 		if (!found)
4337dd7cddfSDavid du Colombier 			goto done;
4347dd7cddfSDavid du Colombier 	}
4357dd7cddfSDavid du Colombier 	result = 1;
4367dd7cddfSDavid du Colombier done:
4377dd7cddfSDavid du Colombier 	for (s = b->trans; s; s = s->nxt)
4387dd7cddfSDavid du Colombier 		s->marked = 0;
4397dd7cddfSDavid du Colombier 	return result;
4407dd7cddfSDavid du Colombier }
4417dd7cddfSDavid du Colombier 
4427dd7cddfSDavid du Colombier static int
buckyballs(void)4437dd7cddfSDavid du Colombier buckyballs(void)
4447dd7cddfSDavid du Colombier {	State *a, *b, *c, *d;
4457dd7cddfSDavid du Colombier 	int m, cnt=0;
4467dd7cddfSDavid du Colombier 
4477dd7cddfSDavid du Colombier 	do {
4487dd7cddfSDavid du Colombier 		m = 0; cnt++;
4497dd7cddfSDavid du Colombier 		for (a = never; a; a = a->nxt)
4507dd7cddfSDavid du Colombier 		{	if (!a->reachable) continue;
4517dd7cddfSDavid du Colombier 
4527dd7cddfSDavid du Colombier 			if (a->redundant) continue;
4537dd7cddfSDavid du Colombier 
4547dd7cddfSDavid du Colombier 			for (b = a->nxt; b; b = b->nxt)
4557dd7cddfSDavid du Colombier 			{	if (!b->reachable) continue;
4567dd7cddfSDavid du Colombier 
4577dd7cddfSDavid du Colombier 				if (b->redundant) continue;
4587dd7cddfSDavid du Colombier 
4597dd7cddfSDavid du Colombier 				if (all_bucky(a, b))
4607dd7cddfSDavid du Colombier 				{	m++;
4617dd7cddfSDavid du Colombier 					if (tl_verbose)
4627dd7cddfSDavid du Colombier 					{	printf("%s bucky match %s\n",
4637dd7cddfSDavid du Colombier 						a->name->name, b->name->name);
4647dd7cddfSDavid du Colombier 					}
4657dd7cddfSDavid du Colombier 
4667dd7cddfSDavid du Colombier 					if (a->accepting && !b->accepting)
467312a1df1SDavid du Colombier 					{	if (strcmp(b->name->name, "T0_init") == 0)
468312a1df1SDavid du Colombier 						{	c = a; d = b;
469312a1df1SDavid du Colombier 							b->accepting = 1;
470312a1df1SDavid du Colombier 						} else
4717dd7cddfSDavid du Colombier 						{	c = b; d = a;
472312a1df1SDavid du Colombier 						}
4737dd7cddfSDavid du Colombier 					} else
4747dd7cddfSDavid du Colombier 					{	c = a; d = b;
4757dd7cddfSDavid du Colombier 					}
4767dd7cddfSDavid du Colombier 
4777dd7cddfSDavid du Colombier 					retarget(c->name->name, d->name->name);
4787dd7cddfSDavid du Colombier 					if (!strncmp(c->name->name, "accept", 6)
4797dd7cddfSDavid du Colombier 					&&  Max_Red == 0)
4807dd7cddfSDavid du Colombier 					{	char buf[64];
4817dd7cddfSDavid du Colombier 						sprintf(buf, "T0%s", &(c->name->name[6]));
4827dd7cddfSDavid du Colombier 						retarget(buf, d->name->name);
4837dd7cddfSDavid du Colombier 					}
4847dd7cddfSDavid du Colombier 					break;
4857dd7cddfSDavid du Colombier 				}
4867dd7cddfSDavid du Colombier 		}	}
4877dd7cddfSDavid du Colombier 	} while (m && cnt < 10);
4887dd7cddfSDavid du Colombier 	return cnt-1;
4897dd7cddfSDavid du Colombier }
4907dd7cddfSDavid du Colombier #endif
4917dd7cddfSDavid du Colombier 
4927dd7cddfSDavid du Colombier static int
mergestates(int v)4937dd7cddfSDavid du Colombier mergestates(int v)
4947dd7cddfSDavid du Colombier {	State *a, *b;
4957dd7cddfSDavid du Colombier 	int m, cnt=0;
496312a1df1SDavid du Colombier 
4977dd7cddfSDavid du Colombier 	if (tl_verbose)
4987dd7cddfSDavid du Colombier 		return 0;
499312a1df1SDavid du Colombier 
5007dd7cddfSDavid du Colombier 	do {
5017dd7cddfSDavid du Colombier 		m = 0; cnt++;
5027dd7cddfSDavid du Colombier 		for (a = never; a; a = a->nxt)
5037dd7cddfSDavid du Colombier 		{	if (v && !a->reachable) continue;
5047dd7cddfSDavid du Colombier 
5057dd7cddfSDavid du Colombier 			if (a->redundant) continue; /* 3.3.10 */
5067dd7cddfSDavid du Colombier 
5077dd7cddfSDavid du Colombier 			for (b = a->nxt; b; b = b->nxt)
5087dd7cddfSDavid du Colombier 			{	if (v && !b->reachable) continue;
5097dd7cddfSDavid du Colombier 
5107dd7cddfSDavid du Colombier 				if (b->redundant) continue; /* 3.3.10 */
5117dd7cddfSDavid du Colombier 
5127dd7cddfSDavid du Colombier 				if (all_trans_match(a, b))
5137dd7cddfSDavid du Colombier 				{	m++;
5147dd7cddfSDavid du Colombier 					if (tl_verbose)
5157dd7cddfSDavid du Colombier 					{	printf("%d: state %s equals state %s\n",
5167dd7cddfSDavid du Colombier 						cnt, a->name->name, b->name->name);
5177dd7cddfSDavid du Colombier 						showtrans(a);
5187dd7cddfSDavid du Colombier 						printf("==\n");
5197dd7cddfSDavid du Colombier 						showtrans(b);
5207dd7cddfSDavid du Colombier 					}
5217dd7cddfSDavid du Colombier 					retarget(a->name->name, b->name->name);
5227dd7cddfSDavid du Colombier 					if (!strncmp(a->name->name, "accept", 6)
5237dd7cddfSDavid du Colombier 					&&  Max_Red == 0)
5247dd7cddfSDavid du Colombier 					{	char buf[64];
5257dd7cddfSDavid du Colombier 						sprintf(buf, "T0%s", &(a->name->name[6]));
5267dd7cddfSDavid du Colombier 						retarget(buf, b->name->name);
5277dd7cddfSDavid du Colombier 					}
5287dd7cddfSDavid du Colombier 					break;
5297dd7cddfSDavid du Colombier 				}
5307dd7cddfSDavid du Colombier #if 0
5317dd7cddfSDavid du Colombier 				else if (tl_verbose)
5327dd7cddfSDavid du Colombier 				{	printf("\n%d: state %s differs from state %s [%d,%d]\n",
533312a1df1SDavid du Colombier 						cnt, a->name->name, b->name->name,
534312a1df1SDavid du Colombier 						a->accepting, b->accepting);
5357dd7cddfSDavid du Colombier 					showtrans(a);
5367dd7cddfSDavid du Colombier 					printf("==\n");
5377dd7cddfSDavid du Colombier 					showtrans(b);
5387dd7cddfSDavid du Colombier 					printf("\n");
5397dd7cddfSDavid du Colombier 				}
5407dd7cddfSDavid du Colombier #endif
5417dd7cddfSDavid du Colombier 		}	}
5427dd7cddfSDavid du Colombier 	} while (m && cnt < 10);
5437dd7cddfSDavid du Colombier 	return cnt-1;
5447dd7cddfSDavid du Colombier }
5457dd7cddfSDavid du Colombier 
5467dd7cddfSDavid du Colombier static int tcnt;
5477dd7cddfSDavid du Colombier 
5487dd7cddfSDavid du Colombier static void
rev_trans(Transition * t)5497dd7cddfSDavid du Colombier rev_trans(Transition *t) /* print transitions  in reverse order... */
5507dd7cddfSDavid du Colombier {
5517dd7cddfSDavid du Colombier 	if (!t) return;
5527dd7cddfSDavid du Colombier 	rev_trans(t->nxt);
5537dd7cddfSDavid du Colombier 
5547dd7cddfSDavid du Colombier 	if (t->redundant && !tl_verbose) return;
555*de2caf28SDavid du Colombier 
556*de2caf28SDavid du Colombier 	if (strcmp(t->name->name, "accept_all") == 0)	/* 6.2.4 */
557*de2caf28SDavid du Colombier 	{	/* not d_step because there may be remote refs */
558*de2caf28SDavid du Colombier 		fprintf(tl_out, "\t:: atomic { (");
559*de2caf28SDavid du Colombier 		if (dump_cond(t->cond, t->cond, 1))
560*de2caf28SDavid du Colombier 			fprintf(tl_out, "1");
561*de2caf28SDavid du Colombier 		fprintf(tl_out, ") -> assert(!(");
562*de2caf28SDavid du Colombier 		if (dump_cond(t->cond, t->cond, 1))
563*de2caf28SDavid du Colombier 			fprintf(tl_out, "1");
564*de2caf28SDavid du Colombier 		fprintf(tl_out, ")) }\n");
565*de2caf28SDavid du Colombier 	} else
566*de2caf28SDavid du Colombier 	{	fprintf(tl_out, "\t:: (");
5677dd7cddfSDavid du Colombier 		if (dump_cond(t->cond, t->cond, 1))
5687dd7cddfSDavid du Colombier 			fprintf(tl_out, "1");
5697dd7cddfSDavid du Colombier 		fprintf(tl_out, ") -> goto %s\n", t->name->name);
570*de2caf28SDavid du Colombier 	}
5717dd7cddfSDavid du Colombier 	tcnt++;
5727dd7cddfSDavid du Colombier }
5737dd7cddfSDavid du Colombier 
5747dd7cddfSDavid du Colombier static void
printstate(State * b)5757dd7cddfSDavid du Colombier printstate(State *b)
5767dd7cddfSDavid du Colombier {
5777dd7cddfSDavid du Colombier 	if (!b || (!tl_verbose && !b->reachable)) return;
5787dd7cddfSDavid du Colombier 
5797dd7cddfSDavid du Colombier 	b->reachable = 0;	/* print only once */
5807dd7cddfSDavid du Colombier 	fprintf(tl_out, "%s:\n", b->name->name);
5817dd7cddfSDavid du Colombier 
582312a1df1SDavid du Colombier 	if (tl_verbose)
583312a1df1SDavid du Colombier 	{	fprintf(tl_out, "	/* ");
584312a1df1SDavid du Colombier 		dump(b->colors->Other);
585312a1df1SDavid du Colombier 		fprintf(tl_out, " */\n");
586312a1df1SDavid du Colombier 	}
587312a1df1SDavid du Colombier 
5887dd7cddfSDavid du Colombier 	if (strncmp(b->name->name, "accept", 6) == 0
5897dd7cddfSDavid du Colombier 	&&  Max_Red == 0)
5907dd7cddfSDavid du Colombier 		fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
5917dd7cddfSDavid du Colombier 
592*de2caf28SDavid du Colombier 	fprintf(tl_out, "\tdo\n");
5937dd7cddfSDavid du Colombier 	tcnt = 0;
5947dd7cddfSDavid du Colombier 	rev_trans(b->trans);
5957dd7cddfSDavid du Colombier 	if (!tcnt) fprintf(tl_out, "\t:: false\n");
596*de2caf28SDavid du Colombier 	fprintf(tl_out, "\tod;\n");
5977dd7cddfSDavid du Colombier 	Total++;
5987dd7cddfSDavid du Colombier }
5997dd7cddfSDavid du Colombier 
6007dd7cddfSDavid du Colombier void
addtrans(Graph * col,char * from,Node * op,char * to)6017dd7cddfSDavid du Colombier addtrans(Graph *col, char *from, Node *op, char *to)
6027dd7cddfSDavid du Colombier {	State *b;
6037dd7cddfSDavid du Colombier 	Transition *t;
6047dd7cddfSDavid du Colombier 
6057dd7cddfSDavid du Colombier 	t = (Transition *) tl_emalloc(sizeof(Transition));
6067dd7cddfSDavid du Colombier 	t->name = tl_lookup(to);
6077dd7cddfSDavid du Colombier 	t->cond = Prune(dupnode(op));
6087dd7cddfSDavid du Colombier 
6097dd7cddfSDavid du Colombier 	if (tl_verbose)
610312a1df1SDavid du Colombier 	{	printf("\n%s <<\t", from); dump(op);
6117dd7cddfSDavid du Colombier 		printf("\n\t"); dump(t->cond);
6127dd7cddfSDavid du Colombier 		printf(">> %s\n", t->name->name);
6137dd7cddfSDavid du Colombier 	}
6147dd7cddfSDavid du Colombier 	if (t->cond) t->cond = rewrite(t->cond);
6157dd7cddfSDavid du Colombier 
6167dd7cddfSDavid du Colombier 	for (b = never; b; b = b->nxt)
6177dd7cddfSDavid du Colombier 		if (!strcmp(b->name->name, from))
6187dd7cddfSDavid du Colombier 		{	t->nxt = b->trans;
6197dd7cddfSDavid du Colombier 			b->trans = t;
6207dd7cddfSDavid du Colombier 			return;
6217dd7cddfSDavid du Colombier 		}
6227dd7cddfSDavid du Colombier 	b = (State *) tl_emalloc(sizeof(State));
6237dd7cddfSDavid du Colombier 	b->name   = tl_lookup(from);
6247dd7cddfSDavid du Colombier 	b->colors = col;
6257dd7cddfSDavid du Colombier 	b->trans  = t;
6267dd7cddfSDavid du Colombier 	if (!strncmp(from, "accept", 6))
6277dd7cddfSDavid du Colombier 		b->accepting = 1;
6287dd7cddfSDavid du Colombier 	b->nxt = never;
6297dd7cddfSDavid du Colombier 	never  = b;
6307dd7cddfSDavid du Colombier }
6317dd7cddfSDavid du Colombier 
6327dd7cddfSDavid du Colombier static void
clr_reach(void)6337dd7cddfSDavid du Colombier clr_reach(void)
6347dd7cddfSDavid du Colombier {	State *p;
6357dd7cddfSDavid du Colombier 	for (p = never; p; p = p->nxt)
6367dd7cddfSDavid du Colombier 		p->reachable = 0;
6377dd7cddfSDavid du Colombier 	hitsall = 0;
6387dd7cddfSDavid du Colombier }
6397dd7cddfSDavid du Colombier 
6407dd7cddfSDavid du Colombier void
fsm_print(void)6417dd7cddfSDavid du Colombier fsm_print(void)
6427dd7cddfSDavid du Colombier {	State *b; int cnt1, cnt2=0;
6437dd7cddfSDavid du Colombier 
6447dd7cddfSDavid du Colombier 	if (tl_clutter) clutter();
6457dd7cddfSDavid du Colombier 
6467dd7cddfSDavid du Colombier 	b = findstate("T0_init");
64700d97012SDavid du Colombier 	if (b && (Max_Red == 0))
6487dd7cddfSDavid du Colombier 		b->accepting = 1;
6497dd7cddfSDavid du Colombier 
6507dd7cddfSDavid du Colombier 	mergestates(0);
6517dd7cddfSDavid du Colombier 	b = findstate("T0_init");
6527dd7cddfSDavid du Colombier 
65300d97012SDavid du Colombier 	fprintf(tl_out, "never %s {    /* ", claim_name?claim_name:"");
6547dd7cddfSDavid du Colombier 		put_uform();
6557dd7cddfSDavid du Colombier 	fprintf(tl_out, " */\n");
6567dd7cddfSDavid du Colombier 
6577dd7cddfSDavid du Colombier 	do {
6587dd7cddfSDavid du Colombier 		clr_reach();
6597dd7cddfSDavid du Colombier 		Dfs(b);
660312a1df1SDavid du Colombier 		cnt1 = mergetrans();
6617dd7cddfSDavid du Colombier 		cnt2 = mergestates(1);
6627dd7cddfSDavid du Colombier 		if (tl_verbose)
6637dd7cddfSDavid du Colombier 			printf("/* >>%d,%d<< */\n", cnt1, cnt2);
6647dd7cddfSDavid du Colombier 	} while (cnt2 > 0);
6657dd7cddfSDavid du Colombier 
6667dd7cddfSDavid du Colombier #ifdef BUCKY
6677dd7cddfSDavid du Colombier 	buckyballs();
6687dd7cddfSDavid du Colombier 	clr_reach();
6697dd7cddfSDavid du Colombier 	Dfs(b);
6707dd7cddfSDavid du Colombier #endif
671312a1df1SDavid du Colombier 	if (b && b->accepting)
6727dd7cddfSDavid du Colombier 		fprintf(tl_out, "accept_init:\n");
6737dd7cddfSDavid du Colombier 
6747dd7cddfSDavid du Colombier 	if (!b && !never)
6757dd7cddfSDavid du Colombier 	{	fprintf(tl_out, "	0 /* false */;\n");
6767dd7cddfSDavid du Colombier 	} else
6777dd7cddfSDavid du Colombier 	{	printstate(b);	/* init state must be first */
6787dd7cddfSDavid du Colombier 		for (b = never; b; b = b->nxt)
6797dd7cddfSDavid du Colombier 			printstate(b);
6807dd7cddfSDavid du Colombier 	}
6817dd7cddfSDavid du Colombier 	if (hitsall)
6827dd7cddfSDavid du Colombier 	fprintf(tl_out, "accept_all:\n	skip\n");
6837dd7cddfSDavid du Colombier 	fprintf(tl_out, "}\n");
6847dd7cddfSDavid du Colombier }
685