xref: /plan9-contrib/sys/src/cmd/spin/tl_trans.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
17dd7cddfSDavid du Colombier /***** tl_spin: tl_trans.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 FILE	*tl_out;
1500d97012SDavid du Colombier extern int	tl_errs, tl_verbose, tl_terse, newstates, state_cnt;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier int	Stack_mx=0, Max_Red=0, Total=0;
187dd7cddfSDavid du Colombier 
197dd7cddfSDavid du Colombier static Mapping	*Mapped = (Mapping *) 0;
207dd7cddfSDavid du Colombier static Graph	*Nodes_Set = (Graph *) 0;
217dd7cddfSDavid du Colombier static Graph	*Nodes_Stack = (Graph *) 0;
227dd7cddfSDavid du Colombier 
23*de2caf28SDavid du Colombier static char	*dumpbuf = NULL;
24*de2caf28SDavid du Colombier static size_t dumpbuf_size = 0;
25*de2caf28SDavid du Colombier static size_t dumpbuf_capacity = 0;
26*de2caf28SDavid du Colombier 
277dd7cddfSDavid du Colombier static int	Red_cnt  = 0;
287dd7cddfSDavid du Colombier static int	Lab_cnt  = 0;
297dd7cddfSDavid du Colombier static int	Base     = 0;
307dd7cddfSDavid du Colombier static int	Stack_sz = 0;
317dd7cddfSDavid du Colombier 
327dd7cddfSDavid du Colombier static Graph	*findgraph(char *);
337dd7cddfSDavid du Colombier static Graph	*pop_stack(void);
347dd7cddfSDavid du Colombier static Node	*Duplicate(Node *);
357dd7cddfSDavid du Colombier static Node	*flatten(Node *);
367dd7cddfSDavid du Colombier static Symbol	*catSlist(Symbol *, Symbol *);
377dd7cddfSDavid du Colombier static Symbol	*dupSlist(Symbol *);
387dd7cddfSDavid du Colombier static char	*newname(void);
397dd7cddfSDavid du Colombier static int	choueka(Graph *, int);
407dd7cddfSDavid du Colombier static int	not_new(Graph *);
417dd7cddfSDavid du Colombier static int	set_prefix(char *, int, Graph *);
427dd7cddfSDavid du Colombier static void	Addout(char *, char *);
437dd7cddfSDavid du Colombier static void	fsm_trans(Graph *, int, char *);
447dd7cddfSDavid du Colombier static void	mkbuchi(void);
45312a1df1SDavid du Colombier static void	expand_g(Graph *);
467dd7cddfSDavid du Colombier static void	fixinit(Node *);
477dd7cddfSDavid du Colombier static void	liveness(Node *);
487dd7cddfSDavid du Colombier static void	mk_grn(Node *);
497dd7cddfSDavid du Colombier static void	mk_red(Node *);
507dd7cddfSDavid du Colombier static void	ng(Symbol *, Symbol *, Node *, Node *, Node *);
517dd7cddfSDavid du Colombier static void	push_stack(Graph *);
527dd7cddfSDavid du Colombier static void	sdump(Node *);
537dd7cddfSDavid du Colombier 
5400d97012SDavid du Colombier void
append_to_dumpbuf(char * s)55*de2caf28SDavid du Colombier append_to_dumpbuf(char* s)
56*de2caf28SDavid du Colombier {
57*de2caf28SDavid du Colombier     size_t len = strlen(s);
58*de2caf28SDavid du Colombier     size_t size_needed = dumpbuf_size + len + 1;
59*de2caf28SDavid du Colombier     if (size_needed > dumpbuf_capacity) {
60*de2caf28SDavid du Colombier         dumpbuf = tl_erealloc(dumpbuf, size_needed, dumpbuf_capacity);
61*de2caf28SDavid du Colombier         dumpbuf_capacity = size_needed;
62*de2caf28SDavid du Colombier     }
63*de2caf28SDavid du Colombier 
64*de2caf28SDavid du Colombier     strncpy(&(dumpbuf[dumpbuf_size]), s, len + 1);
65*de2caf28SDavid du Colombier     dumpbuf_size += len;
66*de2caf28SDavid du Colombier }
67*de2caf28SDavid du Colombier 
68*de2caf28SDavid du Colombier void
ini_trans(void)6900d97012SDavid du Colombier ini_trans(void)
7000d97012SDavid du Colombier {
7100d97012SDavid du Colombier 	Stack_mx = 0;
7200d97012SDavid du Colombier 	Max_Red = 0;
7300d97012SDavid du Colombier 	Total = 0;
7400d97012SDavid du Colombier 
7500d97012SDavid du Colombier 	Mapped = (Mapping *) 0;
7600d97012SDavid du Colombier 	Nodes_Set = (Graph *) 0;
7700d97012SDavid du Colombier 	Nodes_Stack = (Graph *) 0;
7800d97012SDavid du Colombier 
79*de2caf28SDavid du Colombier 	dumpbuf_capacity = 4096;
80*de2caf28SDavid du Colombier 	dumpbuf = tl_emalloc(dumpbuf_capacity);
81*de2caf28SDavid du Colombier 	dumpbuf_size = 0;
82*de2caf28SDavid du Colombier 	memset(dumpbuf, 0, dumpbuf_capacity);
8300d97012SDavid du Colombier 	Red_cnt  = 0;
8400d97012SDavid du Colombier 	Lab_cnt  = 0;
8500d97012SDavid du Colombier 	Base     = 0;
8600d97012SDavid du Colombier 	Stack_sz = 0;
8700d97012SDavid du Colombier }
8800d97012SDavid du Colombier 
897dd7cddfSDavid du Colombier static void
dump_graph(Graph * g)907dd7cddfSDavid du Colombier dump_graph(Graph *g)
917dd7cddfSDavid du Colombier {	Node *n1;
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier 	printf("\n\tnew:\t");
947dd7cddfSDavid du Colombier 	for (n1 = g->New; n1; n1 = n1->nxt)
957dd7cddfSDavid du Colombier 	{ dump(n1); printf(", "); }
967dd7cddfSDavid du Colombier 	printf("\n\told:\t");
977dd7cddfSDavid du Colombier 	for (n1 = g->Old; n1; n1 = n1->nxt)
987dd7cddfSDavid du Colombier 	{ dump(n1); printf(", "); }
997dd7cddfSDavid du Colombier 	printf("\n\tnxt:\t");
1007dd7cddfSDavid du Colombier 	for (n1 = g->Next; n1; n1 = n1->nxt)
1017dd7cddfSDavid du Colombier 	{ dump(n1); printf(", "); }
1027dd7cddfSDavid du Colombier 	printf("\n\tother:\t");
1037dd7cddfSDavid du Colombier 	for (n1 = g->Other; n1; n1 = n1->nxt)
1047dd7cddfSDavid du Colombier 	{ dump(n1); printf(", "); }
1057dd7cddfSDavid du Colombier 	printf("\n");
1067dd7cddfSDavid du Colombier }
1077dd7cddfSDavid du Colombier 
1087dd7cddfSDavid du Colombier static void
push_stack(Graph * g)1097dd7cddfSDavid du Colombier push_stack(Graph *g)
1107dd7cddfSDavid du Colombier {
1117dd7cddfSDavid du Colombier 	if (!g) return;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	g->nxt = Nodes_Stack;
1147dd7cddfSDavid du Colombier 	Nodes_Stack = g;
1157dd7cddfSDavid du Colombier 	if (tl_verbose)
1167dd7cddfSDavid du Colombier 	{	Symbol *z;
1177dd7cddfSDavid du Colombier 		printf("\nPush %s, from ", g->name->name);
1187dd7cddfSDavid du Colombier 		for (z = g->incoming; z; z = z->next)
1197dd7cddfSDavid du Colombier 			printf("%s, ", z->name);
1207dd7cddfSDavid du Colombier 		dump_graph(g);
1217dd7cddfSDavid du Colombier 	}
1227dd7cddfSDavid du Colombier 	Stack_sz++;
1237dd7cddfSDavid du Colombier 	if (Stack_sz > Stack_mx) Stack_mx = Stack_sz;
1247dd7cddfSDavid du Colombier }
1257dd7cddfSDavid du Colombier 
1267dd7cddfSDavid du Colombier static Graph *
pop_stack(void)1277dd7cddfSDavid du Colombier pop_stack(void)
1287dd7cddfSDavid du Colombier {	Graph *g = Nodes_Stack;
1297dd7cddfSDavid du Colombier 
1307dd7cddfSDavid du Colombier 	if (g) Nodes_Stack = g->nxt;
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier 	Stack_sz--;
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier 	return g;
1357dd7cddfSDavid du Colombier }
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier static char *
newname(void)1387dd7cddfSDavid du Colombier newname(void)
13900d97012SDavid du Colombier {	static char buf[32];
14000d97012SDavid du Colombier 	sprintf(buf, "S%d", state_cnt++);
1417dd7cddfSDavid du Colombier 	return buf;
1427dd7cddfSDavid du Colombier }
1437dd7cddfSDavid du Colombier 
1447dd7cddfSDavid du Colombier static int
has_clause(int tok,Graph * p,Node * n)1457dd7cddfSDavid du Colombier has_clause(int tok, Graph *p, Node *n)
1467dd7cddfSDavid du Colombier {	Node *q, *qq;
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier 	switch (n->ntyp) {
1497dd7cddfSDavid du Colombier 	case AND:
1507dd7cddfSDavid du Colombier 		return	has_clause(tok, p, n->lft) &&
1517dd7cddfSDavid du Colombier 			has_clause(tok, p, n->rgt);
1527dd7cddfSDavid du Colombier 	case OR:
1537dd7cddfSDavid du Colombier 		return	has_clause(tok, p, n->lft) ||
1547dd7cddfSDavid du Colombier 			has_clause(tok, p, n->rgt);
1557dd7cddfSDavid du Colombier 	}
1567dd7cddfSDavid du Colombier 
1577dd7cddfSDavid du Colombier 	for (q = p->Other; q; q = q->nxt)
1587dd7cddfSDavid du Colombier 	{	qq = right_linked(q);
1597dd7cddfSDavid du Colombier 		if (anywhere(tok, n, qq))
1607dd7cddfSDavid du Colombier 			return 1;
1617dd7cddfSDavid du Colombier 	}
1627dd7cddfSDavid du Colombier 	return 0;
1637dd7cddfSDavid du Colombier }
1647dd7cddfSDavid du Colombier 
1657dd7cddfSDavid du Colombier static void
mk_grn(Node * n)1667dd7cddfSDavid du Colombier mk_grn(Node *n)
1677dd7cddfSDavid du Colombier {	Graph *p;
1687dd7cddfSDavid du Colombier 
169*de2caf28SDavid du Colombier 	if (!n) return;
170*de2caf28SDavid du Colombier 
1717dd7cddfSDavid du Colombier 	n = right_linked(n);
172312a1df1SDavid du Colombier more:
1737dd7cddfSDavid du Colombier 	for (p = Nodes_Set; p; p = p->nxt)
1747dd7cddfSDavid du Colombier 		if (p->outgoing
1757dd7cddfSDavid du Colombier 		&&  has_clause(AND, p, n))
1767dd7cddfSDavid du Colombier 		{	p->isgrn[p->grncnt++] =
1777dd7cddfSDavid du Colombier 				(unsigned char) Red_cnt;
1787dd7cddfSDavid du Colombier 			Lab_cnt++;
1797dd7cddfSDavid du Colombier 		}
180312a1df1SDavid du Colombier 
181312a1df1SDavid du Colombier 	if (n->ntyp == U_OPER)	/* 3.4.0 */
182312a1df1SDavid du Colombier 	{	n = n->rgt;
183312a1df1SDavid du Colombier 		goto more;
184312a1df1SDavid du Colombier 	}
1857dd7cddfSDavid du Colombier }
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier static void
mk_red(Node * n)1887dd7cddfSDavid du Colombier mk_red(Node *n)
1897dd7cddfSDavid du Colombier {	Graph *p;
1907dd7cddfSDavid du Colombier 
191*de2caf28SDavid du Colombier 	if (!n) return;
192*de2caf28SDavid du Colombier 
1937dd7cddfSDavid du Colombier 	n = right_linked(n);
1947dd7cddfSDavid du Colombier 	for (p = Nodes_Set; p; p = p->nxt)
1957dd7cddfSDavid du Colombier 	{	if (p->outgoing
1967dd7cddfSDavid du Colombier 		&&  has_clause(0, p, n))
1977dd7cddfSDavid du Colombier 		{	if (p->redcnt >= 63)
1987dd7cddfSDavid du Colombier 				Fatal("too many Untils", (char *)0);
1997dd7cddfSDavid du Colombier 			p->isred[p->redcnt++] =
2007dd7cddfSDavid du Colombier 				(unsigned char) Red_cnt;
2017dd7cddfSDavid du Colombier 			Lab_cnt++; Max_Red = Red_cnt;
2027dd7cddfSDavid du Colombier 	}	}
2037dd7cddfSDavid du Colombier }
2047dd7cddfSDavid du Colombier 
2057dd7cddfSDavid du Colombier static void
liveness(Node * n)2067dd7cddfSDavid du Colombier liveness(Node *n)
2077dd7cddfSDavid du Colombier {
2087dd7cddfSDavid du Colombier 	if (n)
2097dd7cddfSDavid du Colombier 	switch (n->ntyp) {
2107dd7cddfSDavid du Colombier #ifdef NXT
2117dd7cddfSDavid du Colombier 	case NEXT:
2127dd7cddfSDavid du Colombier 		liveness(n->lft);
2137dd7cddfSDavid du Colombier 		break;
2147dd7cddfSDavid du Colombier #endif
2157dd7cddfSDavid du Colombier 	case U_OPER:
2167dd7cddfSDavid du Colombier 		Red_cnt++;
2177dd7cddfSDavid du Colombier 		mk_red(n);
2187dd7cddfSDavid du Colombier 		mk_grn(n->rgt);
2197dd7cddfSDavid du Colombier 		/* fall through */
2207dd7cddfSDavid du Colombier 	case V_OPER:
2217dd7cddfSDavid du Colombier 	case OR: case AND:
2227dd7cddfSDavid du Colombier 		liveness(n->lft);
2237dd7cddfSDavid du Colombier 		liveness(n->rgt);
2247dd7cddfSDavid du Colombier 		break;
2257dd7cddfSDavid du Colombier 	}
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier static Graph *
findgraph(char * nm)2297dd7cddfSDavid du Colombier findgraph(char *nm)
2307dd7cddfSDavid du Colombier {	Graph	*p;
2317dd7cddfSDavid du Colombier 	Mapping *m;
2327dd7cddfSDavid du Colombier 
2337dd7cddfSDavid du Colombier 	for (p = Nodes_Set; p; p = p->nxt)
2347dd7cddfSDavid du Colombier 		if (!strcmp(p->name->name, nm))
2357dd7cddfSDavid du Colombier 			return p;
2367dd7cddfSDavid du Colombier 	for (m = Mapped; m; m = m->nxt)
2377dd7cddfSDavid du Colombier 		if (strcmp(m->from, nm) == 0)
2387dd7cddfSDavid du Colombier 			return m->to;
2397dd7cddfSDavid du Colombier 
2407dd7cddfSDavid du Colombier 	printf("warning: node %s not found\n", nm);
2417dd7cddfSDavid du Colombier 	return (Graph *) 0;
2427dd7cddfSDavid du Colombier }
2437dd7cddfSDavid du Colombier 
2447dd7cddfSDavid du Colombier static void
Addout(char * to,char * from)2457dd7cddfSDavid du Colombier Addout(char *to, char *from)
2467dd7cddfSDavid du Colombier {	Graph	*p = findgraph(from);
2477dd7cddfSDavid du Colombier 	Symbol	*s;
2487dd7cddfSDavid du Colombier 
2497dd7cddfSDavid du Colombier 	if (!p) return;
2507dd7cddfSDavid du Colombier 	s = getsym(tl_lookup(to));
2517dd7cddfSDavid du Colombier 	s->next = p->outgoing;
2527dd7cddfSDavid du Colombier 	p->outgoing = s;
2537dd7cddfSDavid du Colombier }
2547dd7cddfSDavid du Colombier 
2557dd7cddfSDavid du Colombier #ifdef NXT
2567dd7cddfSDavid du Colombier int
only_nxt(Node * n)2577dd7cddfSDavid du Colombier only_nxt(Node *n)
2587dd7cddfSDavid du Colombier {
2597dd7cddfSDavid du Colombier 	switch (n->ntyp) {
2607dd7cddfSDavid du Colombier 	case NEXT:
2617dd7cddfSDavid du Colombier 		return 1;
2627dd7cddfSDavid du Colombier 	case OR:
2637dd7cddfSDavid du Colombier 	case AND:
2647dd7cddfSDavid du Colombier 		return only_nxt(n->rgt) && only_nxt(n->lft);
2657dd7cddfSDavid du Colombier 	default:
2667dd7cddfSDavid du Colombier 		return 0;
2677dd7cddfSDavid du Colombier 	}
2687dd7cddfSDavid du Colombier }
2697dd7cddfSDavid du Colombier #endif
2707dd7cddfSDavid du Colombier 
2717dd7cddfSDavid du Colombier int
dump_cond(Node * pp,Node * r,int first)2727dd7cddfSDavid du Colombier dump_cond(Node *pp, Node *r, int first)
2737dd7cddfSDavid du Colombier {	Node *q;
2747dd7cddfSDavid du Colombier 	int frst = first;
2757dd7cddfSDavid du Colombier 
2767dd7cddfSDavid du Colombier 	if (!pp) return frst;
2777dd7cddfSDavid du Colombier 
2787dd7cddfSDavid du Colombier 	q = dupnode(pp);
2797dd7cddfSDavid du Colombier 	q = rewrite(q);
2807dd7cddfSDavid du Colombier 
281*de2caf28SDavid du Colombier 	if (q->ntyp == CEXPR)
282*de2caf28SDavid du Colombier 	{	if (!frst) fprintf(tl_out, " && ");
283*de2caf28SDavid du Colombier 		fprintf(tl_out, "c_expr { ");
284*de2caf28SDavid du Colombier 		dump_cond(q->lft, r, 1);
285*de2caf28SDavid du Colombier 		fprintf(tl_out, " } ");
286*de2caf28SDavid du Colombier 		frst = 0;
287*de2caf28SDavid du Colombier 		return frst;
288*de2caf28SDavid du Colombier 	}
289*de2caf28SDavid du Colombier 
2907dd7cddfSDavid du Colombier 	if (q->ntyp == PREDICATE
2917dd7cddfSDavid du Colombier 	||  q->ntyp == NOT
2927dd7cddfSDavid du Colombier #ifndef NXT
2937dd7cddfSDavid du Colombier 	||  q->ntyp == OR
2947dd7cddfSDavid du Colombier #endif
2957dd7cddfSDavid du Colombier 	||  q->ntyp == FALSE)
2967dd7cddfSDavid du Colombier 	{	if (!frst) fprintf(tl_out, " && ");
2977dd7cddfSDavid du Colombier 		dump(q);
2987dd7cddfSDavid du Colombier 		frst = 0;
2997dd7cddfSDavid du Colombier #ifdef NXT
3007dd7cddfSDavid du Colombier 	} else if (q->ntyp == OR)
3017dd7cddfSDavid du Colombier 	{	if (!frst) fprintf(tl_out, " && ");
3027dd7cddfSDavid du Colombier 		fprintf(tl_out, "((");
3037dd7cddfSDavid du Colombier 		frst = dump_cond(q->lft, r, 1);
3047dd7cddfSDavid du Colombier 
3057dd7cddfSDavid du Colombier 		if (!frst)
3067dd7cddfSDavid du Colombier 			fprintf(tl_out, ") || (");
3077dd7cddfSDavid du Colombier 		else
3087dd7cddfSDavid du Colombier 		{	if (only_nxt(q->lft))
3097dd7cddfSDavid du Colombier 			{	fprintf(tl_out, "1))");
3107dd7cddfSDavid du Colombier 				return 0;
3117dd7cddfSDavid du Colombier 			}
3127dd7cddfSDavid du Colombier 		}
3137dd7cddfSDavid du Colombier 
3147dd7cddfSDavid du Colombier 		frst = dump_cond(q->rgt, r, 1);
3157dd7cddfSDavid du Colombier 
3167dd7cddfSDavid du Colombier 		if (frst)
3177dd7cddfSDavid du Colombier 		{	if (only_nxt(q->rgt))
3187dd7cddfSDavid du Colombier 				fprintf(tl_out, "1");
3197dd7cddfSDavid du Colombier 			else
3207dd7cddfSDavid du Colombier 				fprintf(tl_out, "0");
3217dd7cddfSDavid du Colombier 			frst = 0;
3227dd7cddfSDavid du Colombier 		}
3237dd7cddfSDavid du Colombier 
3247dd7cddfSDavid du Colombier 		fprintf(tl_out, "))");
3257dd7cddfSDavid du Colombier #endif
3267dd7cddfSDavid du Colombier 	} else  if (q->ntyp == V_OPER
3277dd7cddfSDavid du Colombier 		&& !anywhere(AND, q->rgt, r))
3287dd7cddfSDavid du Colombier 	{	frst = dump_cond(q->rgt, r, frst);
3297dd7cddfSDavid du Colombier 	} else  if (q->ntyp == AND)
3307dd7cddfSDavid du Colombier 	{
3317dd7cddfSDavid du Colombier 		frst = dump_cond(q->lft, r, frst);
3327dd7cddfSDavid du Colombier 		frst = dump_cond(q->rgt, r, frst);
3337dd7cddfSDavid du Colombier 	}
3347dd7cddfSDavid du Colombier 
3357dd7cddfSDavid du Colombier 	return frst;
3367dd7cddfSDavid du Colombier }
3377dd7cddfSDavid du Colombier 
3387dd7cddfSDavid du Colombier static int
choueka(Graph * p,int count)3397dd7cddfSDavid du Colombier choueka(Graph *p, int count)
3407dd7cddfSDavid du Colombier {	int j, k, incr_cnt = 0;
3417dd7cddfSDavid du Colombier 
3427dd7cddfSDavid du Colombier 	for (j = count; j <= Max_Red; j++) /* for each acceptance class */
3437dd7cddfSDavid du Colombier 	{	int delta = 0;
3447dd7cddfSDavid du Colombier 
3457dd7cddfSDavid du Colombier 		/* is state p labeled Grn-j OR not Red-j ? */
3467dd7cddfSDavid du Colombier 
3477dd7cddfSDavid du Colombier 		for (k = 0; k < (int) p->grncnt; k++)
3487dd7cddfSDavid du Colombier 			if (p->isgrn[k] == j)
3497dd7cddfSDavid du Colombier 			{	delta = 1;
3507dd7cddfSDavid du Colombier 				break;
3517dd7cddfSDavid du Colombier 			}
3527dd7cddfSDavid du Colombier 		if (delta)
3537dd7cddfSDavid du Colombier 		{	incr_cnt++;
3547dd7cddfSDavid du Colombier 			continue;
3557dd7cddfSDavid du Colombier 		}
3567dd7cddfSDavid du Colombier 		for (k = 0; k < (int) p->redcnt; k++)
3577dd7cddfSDavid du Colombier 			if (p->isred[k] == j)
3587dd7cddfSDavid du Colombier 			{	delta = 1;
3597dd7cddfSDavid du Colombier 				break;
3607dd7cddfSDavid du Colombier 			}
3617dd7cddfSDavid du Colombier 
3627dd7cddfSDavid du Colombier 		if (delta) break;
3637dd7cddfSDavid du Colombier 
3647dd7cddfSDavid du Colombier 		incr_cnt++;
3657dd7cddfSDavid du Colombier 	}
3667dd7cddfSDavid du Colombier 	return incr_cnt;
3677dd7cddfSDavid du Colombier }
3687dd7cddfSDavid du Colombier 
3697dd7cddfSDavid du Colombier static int
set_prefix(char * pref,int count,Graph * r2)3707dd7cddfSDavid du Colombier set_prefix(char *pref, int count, Graph *r2)
3717dd7cddfSDavid du Colombier {	int incr_cnt = 0;	/* acceptance class 'count' */
3727dd7cddfSDavid du Colombier 
3737dd7cddfSDavid du Colombier 	if (Lab_cnt == 0
3747dd7cddfSDavid du Colombier 	||  Max_Red == 0)
3757dd7cddfSDavid du Colombier 		sprintf(pref, "accept");	/* new */
3767dd7cddfSDavid du Colombier 	else if (count >= Max_Red)
3777dd7cddfSDavid du Colombier 		sprintf(pref, "T0");		/* cycle */
3787dd7cddfSDavid du Colombier 	else
3797dd7cddfSDavid du Colombier 	{	incr_cnt = choueka(r2, count+1);
3807dd7cddfSDavid du Colombier 		if (incr_cnt + count >= Max_Red)
3817dd7cddfSDavid du Colombier 			sprintf(pref, "accept"); /* last hop */
3827dd7cddfSDavid du Colombier 		else
3837dd7cddfSDavid du Colombier 			sprintf(pref, "T%d", count+incr_cnt);
3847dd7cddfSDavid du Colombier 	}
3857dd7cddfSDavid du Colombier 	return incr_cnt;
3867dd7cddfSDavid du Colombier }
3877dd7cddfSDavid du Colombier 
3887dd7cddfSDavid du Colombier static void
fsm_trans(Graph * p,int count,char * curnm)3897dd7cddfSDavid du Colombier fsm_trans(Graph *p, int count, char *curnm)
3907dd7cddfSDavid du Colombier {	Graph	*r;
3917dd7cddfSDavid du Colombier 	Symbol	*s;
39200d97012SDavid du Colombier 	char	prefix[128], nwnm[256];
3937dd7cddfSDavid du Colombier 
3947dd7cddfSDavid du Colombier 	if (!p->outgoing)
3957dd7cddfSDavid du Colombier 		addtrans(p, curnm, False, "accept_all");
3967dd7cddfSDavid du Colombier 
3977dd7cddfSDavid du Colombier 	for (s = p->outgoing; s; s = s->next)
3987dd7cddfSDavid du Colombier 	{	r = findgraph(s->name);
3997dd7cddfSDavid du Colombier 		if (!r) continue;
4007dd7cddfSDavid du Colombier 		if (r->outgoing)
4017dd7cddfSDavid du Colombier 		{	(void) set_prefix(prefix, count, r);
4027dd7cddfSDavid du Colombier 			sprintf(nwnm, "%s_%s", prefix, s->name);
4037dd7cddfSDavid du Colombier 		} else
4047dd7cddfSDavid du Colombier 			strcpy(nwnm, "accept_all");
405312a1df1SDavid du Colombier 
406312a1df1SDavid du Colombier 		if (tl_verbose)
407312a1df1SDavid du Colombier 		{	printf("maxred=%d, count=%d, curnm=%s, nwnm=%s ",
408312a1df1SDavid du Colombier 				Max_Red, count, curnm, nwnm);
409312a1df1SDavid du Colombier 			printf("(greencnt=%d,%d, redcnt=%d,%d)\n",
410312a1df1SDavid du Colombier 				r->grncnt, r->isgrn[0],
411312a1df1SDavid du Colombier 				r->redcnt, r->isred[0]);
412312a1df1SDavid du Colombier 		}
4137dd7cddfSDavid du Colombier 		addtrans(p, curnm, r->Old, nwnm);
4147dd7cddfSDavid du Colombier 	}
4157dd7cddfSDavid du Colombier }
4167dd7cddfSDavid du Colombier 
4177dd7cddfSDavid du Colombier static void
mkbuchi(void)4187dd7cddfSDavid du Colombier mkbuchi(void)
4197dd7cddfSDavid du Colombier {	Graph	*p;
4207dd7cddfSDavid du Colombier 	int	k;
4217dd7cddfSDavid du Colombier 	char	curnm[64];
4227dd7cddfSDavid du Colombier 
4237dd7cddfSDavid du Colombier 	for (k = 0; k <= Max_Red; k++)
4247dd7cddfSDavid du Colombier 	for (p = Nodes_Set; p; p = p->nxt)
4257dd7cddfSDavid du Colombier 	{	if (!p->outgoing)
4267dd7cddfSDavid du Colombier 			continue;
4277dd7cddfSDavid du Colombier 		if (k != 0
4287dd7cddfSDavid du Colombier 		&& !strcmp(p->name->name, "init")
4297dd7cddfSDavid du Colombier 		&&  Max_Red != 0)
4307dd7cddfSDavid du Colombier 			continue;
4317dd7cddfSDavid du Colombier 
4327dd7cddfSDavid du Colombier 		if (k == Max_Red
4337dd7cddfSDavid du Colombier 		&&  strcmp(p->name->name, "init") != 0)
4347dd7cddfSDavid du Colombier 			strcpy(curnm, "accept_");
4357dd7cddfSDavid du Colombier 		else
4367dd7cddfSDavid du Colombier 			sprintf(curnm, "T%d_", k);
4377dd7cddfSDavid du Colombier 
4387dd7cddfSDavid du Colombier 		strcat(curnm, p->name->name);
4397dd7cddfSDavid du Colombier 
4407dd7cddfSDavid du Colombier 		fsm_trans(p, k, curnm);
4417dd7cddfSDavid du Colombier 	}
4427dd7cddfSDavid du Colombier 	fsm_print();
4437dd7cddfSDavid du Colombier }
4447dd7cddfSDavid du Colombier 
4457dd7cddfSDavid du Colombier static Symbol *
dupSlist(Symbol * s)4467dd7cddfSDavid du Colombier dupSlist(Symbol *s)
4477dd7cddfSDavid du Colombier {	Symbol *p1, *p2, *p3, *d = ZS;
4487dd7cddfSDavid du Colombier 
4497dd7cddfSDavid du Colombier 	for (p1 = s; p1; p1 = p1->next)
4507dd7cddfSDavid du Colombier 	{	for (p3 = d; p3; p3 = p3->next)
4517dd7cddfSDavid du Colombier 		{	if (!strcmp(p3->name, p1->name))
4527dd7cddfSDavid du Colombier 				break;
4537dd7cddfSDavid du Colombier 		}
4547dd7cddfSDavid du Colombier 		if (p3) continue;	/* a duplicate */
4557dd7cddfSDavid du Colombier 
4567dd7cddfSDavid du Colombier 		p2 = getsym(p1);
4577dd7cddfSDavid du Colombier 		p2->next = d;
4587dd7cddfSDavid du Colombier 		d = p2;
4597dd7cddfSDavid du Colombier 	}
4607dd7cddfSDavid du Colombier 	return d;
4617dd7cddfSDavid du Colombier }
4627dd7cddfSDavid du Colombier 
4637dd7cddfSDavid du Colombier static Symbol *
catSlist(Symbol * a,Symbol * b)4647dd7cddfSDavid du Colombier catSlist(Symbol *a, Symbol *b)
4657dd7cddfSDavid du Colombier {	Symbol *p1, *p2, *p3, *tmp;
4667dd7cddfSDavid du Colombier 
4677dd7cddfSDavid du Colombier 	/* remove duplicates from b */
4687dd7cddfSDavid du Colombier 	for (p1 = a; p1; p1 = p1->next)
4697dd7cddfSDavid du Colombier 	{	p3 = ZS;
470*de2caf28SDavid du Colombier 		p2 = b;
471*de2caf28SDavid du Colombier 		while (p2)
4727dd7cddfSDavid du Colombier 		{ if (strcmp(p1->name, p2->name))
4737dd7cddfSDavid du Colombier 			{	p3 = p2;
474*de2caf28SDavid du Colombier 				p2 = p2->next;
4757dd7cddfSDavid du Colombier 				continue;
4767dd7cddfSDavid du Colombier 			}
4777dd7cddfSDavid du Colombier 			tmp = p2->next;
4787dd7cddfSDavid du Colombier 			tfree((void *) p2);
479*de2caf28SDavid du Colombier 			p2 = tmp;
4807dd7cddfSDavid du Colombier 			if (p3)
4817dd7cddfSDavid du Colombier 				p3->next = tmp;
4827dd7cddfSDavid du Colombier 			else
4837dd7cddfSDavid du Colombier 				b = tmp;
4847dd7cddfSDavid du Colombier 	}	}
4857dd7cddfSDavid du Colombier 	if (!a) return b;
4867dd7cddfSDavid du Colombier 	if (!b) return a;
4877dd7cddfSDavid du Colombier 	if (!b->next)
4887dd7cddfSDavid du Colombier 	{	b->next = a;
4897dd7cddfSDavid du Colombier 		return b;
4907dd7cddfSDavid du Colombier 	}
4917dd7cddfSDavid du Colombier 	/* find end of list */
4927dd7cddfSDavid du Colombier 	for (p1 = a; p1->next; p1 = p1->next)
4937dd7cddfSDavid du Colombier 		;
4947dd7cddfSDavid du Colombier 	p1->next = b;
4957dd7cddfSDavid du Colombier 	return a;
4967dd7cddfSDavid du Colombier }
4977dd7cddfSDavid du Colombier 
4987dd7cddfSDavid du Colombier static void
fixinit(Node * orig)4997dd7cddfSDavid du Colombier fixinit(Node *orig)
5007dd7cddfSDavid du Colombier {	Graph	*p1, *g;
5017dd7cddfSDavid du Colombier 	Symbol	*q1, *q2 = ZS;
5027dd7cddfSDavid du Colombier 
5037dd7cddfSDavid du Colombier 	ng(tl_lookup("init"), ZS, ZN, ZN, ZN);
5047dd7cddfSDavid du Colombier 	p1 = pop_stack();
505*de2caf28SDavid du Colombier 	if (p1)
506*de2caf28SDavid du Colombier 	{	p1->nxt = Nodes_Set;
5077dd7cddfSDavid du Colombier 		p1->Other = p1->Old = orig;
5087dd7cddfSDavid du Colombier 		Nodes_Set = p1;
509*de2caf28SDavid du Colombier 	}
5107dd7cddfSDavid du Colombier 
5117dd7cddfSDavid du Colombier 	for (g = Nodes_Set; g; g = g->nxt)
5127dd7cddfSDavid du Colombier 	{	for (q1 = g->incoming; q1; q1 = q2)
5137dd7cddfSDavid du Colombier 		{	q2 = q1->next;
5147dd7cddfSDavid du Colombier 			Addout(g->name->name, q1->name);
5157dd7cddfSDavid du Colombier 			tfree((void *) q1);
5167dd7cddfSDavid du Colombier 		}
5177dd7cddfSDavid du Colombier 		g->incoming = ZS;
5187dd7cddfSDavid du Colombier 	}
5197dd7cddfSDavid du Colombier }
5207dd7cddfSDavid du Colombier 
5217dd7cddfSDavid du Colombier static Node *
flatten(Node * p)5227dd7cddfSDavid du Colombier flatten(Node *p)
5237dd7cddfSDavid du Colombier {	Node *q, *r, *z = ZN;
5247dd7cddfSDavid du Colombier 
5257dd7cddfSDavid du Colombier 	for (q = p; q; q = q->nxt)
5267dd7cddfSDavid du Colombier 	{	r = dupnode(q);
5277dd7cddfSDavid du Colombier 		if (z)
5287dd7cddfSDavid du Colombier 			z = tl_nn(AND, r, z);
5297dd7cddfSDavid du Colombier 		else
5307dd7cddfSDavid du Colombier 			z = r;
5317dd7cddfSDavid du Colombier 	}
5327dd7cddfSDavid du Colombier 	if (!z) return z;
5337dd7cddfSDavid du Colombier 	z = rewrite(z);
5347dd7cddfSDavid du Colombier 	return z;
5357dd7cddfSDavid du Colombier }
5367dd7cddfSDavid du Colombier 
5377dd7cddfSDavid du Colombier static Node *
Duplicate(Node * n)5387dd7cddfSDavid du Colombier Duplicate(Node *n)
5397dd7cddfSDavid du Colombier {	Node *n1, *n2, *lst = ZN, *d = ZN;
5407dd7cddfSDavid du Colombier 
5417dd7cddfSDavid du Colombier 	for (n1 = n; n1; n1 = n1->nxt)
5427dd7cddfSDavid du Colombier 	{	n2 = dupnode(n1);
5437dd7cddfSDavid du Colombier 		if (lst)
5447dd7cddfSDavid du Colombier 		{	lst->nxt = n2;
5457dd7cddfSDavid du Colombier 			lst = n2;
5467dd7cddfSDavid du Colombier 		} else
5477dd7cddfSDavid du Colombier 			d = lst = n2;
5487dd7cddfSDavid du Colombier 	}
5497dd7cddfSDavid du Colombier 	return d;
5507dd7cddfSDavid du Colombier }
5517dd7cddfSDavid du Colombier 
5527dd7cddfSDavid du Colombier static void
ng(Symbol * s,Symbol * in,Node * isnew,Node * isold,Node * next)5537dd7cddfSDavid du Colombier ng(Symbol *s, Symbol *in, Node *isnew, Node *isold, Node *next)
5547dd7cddfSDavid du Colombier {	Graph *g = (Graph *) tl_emalloc(sizeof(Graph));
5557dd7cddfSDavid du Colombier 
5567dd7cddfSDavid du Colombier 	if (s)     g->name = s;
5577dd7cddfSDavid du Colombier 	else       g->name = tl_lookup(newname());
5587dd7cddfSDavid du Colombier 
5597dd7cddfSDavid du Colombier 	if (in)    g->incoming = dupSlist(in);
5607dd7cddfSDavid du Colombier 	if (isnew) g->New  = flatten(isnew);
5617dd7cddfSDavid du Colombier 	if (isold) g->Old  = Duplicate(isold);
5627dd7cddfSDavid du Colombier 	if (next)  g->Next = flatten(next);
5637dd7cddfSDavid du Colombier 
5647dd7cddfSDavid du Colombier 	push_stack(g);
5657dd7cddfSDavid du Colombier }
5667dd7cddfSDavid du Colombier 
5677dd7cddfSDavid du Colombier static void
sdump(Node * n)5687dd7cddfSDavid du Colombier sdump(Node *n)
5697dd7cddfSDavid du Colombier {
5707dd7cddfSDavid du Colombier 	switch (n->ntyp) {
571*de2caf28SDavid du Colombier 	case PREDICATE:	append_to_dumpbuf(n->sym->name);
5727dd7cddfSDavid du Colombier 			break;
573*de2caf28SDavid du Colombier 	case U_OPER:	append_to_dumpbuf("U");
5747dd7cddfSDavid du Colombier 			goto common2;
575*de2caf28SDavid du Colombier 	case V_OPER:	append_to_dumpbuf("V");
5767dd7cddfSDavid du Colombier 			goto common2;
577*de2caf28SDavid du Colombier 	case OR:	append_to_dumpbuf("|");
5787dd7cddfSDavid du Colombier 			goto common2;
579*de2caf28SDavid du Colombier 	case AND:	append_to_dumpbuf("&");
5807dd7cddfSDavid du Colombier common2:		sdump(n->rgt);
5817dd7cddfSDavid du Colombier common1:		sdump(n->lft);
5827dd7cddfSDavid du Colombier 			break;
5837dd7cddfSDavid du Colombier #ifdef NXT
584*de2caf28SDavid du Colombier 	case NEXT:	append_to_dumpbuf("X");
5857dd7cddfSDavid du Colombier 			goto common1;
5867dd7cddfSDavid du Colombier #endif
587*de2caf28SDavid du Colombier 	case CEXPR:	append_to_dumpbuf("c_expr {");
588*de2caf28SDavid du Colombier 			sdump(n->lft);
589*de2caf28SDavid du Colombier 			append_to_dumpbuf("}");
590*de2caf28SDavid du Colombier 			break;
591*de2caf28SDavid du Colombier 	case NOT:	append_to_dumpbuf("!");
5927dd7cddfSDavid du Colombier 			goto common1;
593*de2caf28SDavid du Colombier 	case TRUE:	append_to_dumpbuf("T");
5947dd7cddfSDavid du Colombier 			break;
595*de2caf28SDavid du Colombier 	case FALSE:	append_to_dumpbuf("F");
5967dd7cddfSDavid du Colombier 			break;
597*de2caf28SDavid du Colombier 	default:	append_to_dumpbuf("?");
5987dd7cddfSDavid du Colombier 			break;
5997dd7cddfSDavid du Colombier 	}
6007dd7cddfSDavid du Colombier }
6017dd7cddfSDavid du Colombier 
6027dd7cddfSDavid du Colombier Symbol *
DoDump(Node * n)6037dd7cddfSDavid du Colombier DoDump(Node *n)
6047dd7cddfSDavid du Colombier {
6057dd7cddfSDavid du Colombier 	if (!n) return ZS;
6067dd7cddfSDavid du Colombier 
6077dd7cddfSDavid du Colombier 	if (n->ntyp == PREDICATE)
6087dd7cddfSDavid du Colombier 		return n->sym;
6097dd7cddfSDavid du Colombier 
610*de2caf28SDavid du Colombier     if (dumpbuf) {
6117dd7cddfSDavid du Colombier         dumpbuf[0] = '\0';
612*de2caf28SDavid du Colombier         dumpbuf_size = 0;
6137dd7cddfSDavid du Colombier         sdump(n);
6147dd7cddfSDavid du Colombier         return tl_lookup(dumpbuf);
6157dd7cddfSDavid du Colombier     }
6167dd7cddfSDavid du Colombier 
617*de2caf28SDavid du Colombier     sdump(n);
618*de2caf28SDavid du Colombier     return tl_lookup("");
619*de2caf28SDavid du Colombier }
620*de2caf28SDavid du Colombier 
6217dd7cddfSDavid du Colombier static int
not_new(Graph * g)6227dd7cddfSDavid du Colombier not_new(Graph *g)
6237dd7cddfSDavid du Colombier {	Graph	*q1; Node *tmp, *n1, *n2;
6247dd7cddfSDavid du Colombier 	Mapping	*map;
6257dd7cddfSDavid du Colombier 
6267dd7cddfSDavid du Colombier 	tmp = flatten(g->Old);	/* duplicate, collapse, normalize */
6277dd7cddfSDavid du Colombier 	g->Other = g->Old;	/* non normalized full version */
6287dd7cddfSDavid du Colombier 	g->Old = tmp;
6297dd7cddfSDavid du Colombier 
6307dd7cddfSDavid du Colombier 	g->oldstring = DoDump(g->Old);
6317dd7cddfSDavid du Colombier 
6327dd7cddfSDavid du Colombier 	tmp = flatten(g->Next);
6337dd7cddfSDavid du Colombier 	g->nxtstring = DoDump(tmp);
6347dd7cddfSDavid du Colombier 
6357dd7cddfSDavid du Colombier 	if (tl_verbose) dump_graph(g);
6367dd7cddfSDavid du Colombier 
6377dd7cddfSDavid du Colombier 	Debug2("\tformula-old: [%s]\n", g->oldstring?g->oldstring->name:"true");
6387dd7cddfSDavid du Colombier 	Debug2("\tformula-nxt: [%s]\n", g->nxtstring?g->nxtstring->name:"true");
6397dd7cddfSDavid du Colombier 	for (q1 = Nodes_Set; q1; q1 = q1->nxt)
6407dd7cddfSDavid du Colombier 	{	Debug2("	compare old to: %s", q1->name->name);
6417dd7cddfSDavid du Colombier 		Debug2(" [%s]", q1->oldstring?q1->oldstring->name:"true");
6427dd7cddfSDavid du Colombier 
6437dd7cddfSDavid du Colombier 		Debug2("	compare nxt to: %s", q1->name->name);
6447dd7cddfSDavid du Colombier 		Debug2(" [%s]", q1->nxtstring?q1->nxtstring->name:"true");
6457dd7cddfSDavid du Colombier 
6467dd7cddfSDavid du Colombier 		if (q1->oldstring != g->oldstring
6477dd7cddfSDavid du Colombier 		||  q1->nxtstring != g->nxtstring)
6487dd7cddfSDavid du Colombier 		{	Debug(" => different\n");
6497dd7cddfSDavid du Colombier 			continue;
6507dd7cddfSDavid du Colombier 		}
6517dd7cddfSDavid du Colombier 		Debug(" => match\n");
6527dd7cddfSDavid du Colombier 
6537dd7cddfSDavid du Colombier 		if (g->incoming)
6547dd7cddfSDavid du Colombier 			q1->incoming = catSlist(g->incoming, q1->incoming);
6557dd7cddfSDavid du Colombier 
6567dd7cddfSDavid du Colombier 		/* check if there's anything in g->Other that needs
6577dd7cddfSDavid du Colombier 		   adding to q1->Other
6587dd7cddfSDavid du Colombier 		*/
6597dd7cddfSDavid du Colombier 		for (n2 = g->Other; n2; n2 = n2->nxt)
6607dd7cddfSDavid du Colombier 		{	for (n1 = q1->Other; n1; n1 = n1->nxt)
6617dd7cddfSDavid du Colombier 				if (isequal(n1, n2))
6627dd7cddfSDavid du Colombier 					break;
6637dd7cddfSDavid du Colombier 			if (!n1)
6647dd7cddfSDavid du Colombier 			{	Node *n3 = dupnode(n2);
6657dd7cddfSDavid du Colombier 				/* don't mess up n2->nxt */
6667dd7cddfSDavid du Colombier 				n3->nxt = q1->Other;
6677dd7cddfSDavid du Colombier 				q1->Other = n3;
6687dd7cddfSDavid du Colombier 		}	}
6697dd7cddfSDavid du Colombier 
6707dd7cddfSDavid du Colombier 		map = (Mapping *) tl_emalloc(sizeof(Mapping));
6717dd7cddfSDavid du Colombier 	  	map->from = g->name->name;
6727dd7cddfSDavid du Colombier 	  	map->to   = q1;
6737dd7cddfSDavid du Colombier 	  	map->nxt = Mapped;
6747dd7cddfSDavid du Colombier 	  	Mapped = map;
6757dd7cddfSDavid du Colombier 
6767dd7cddfSDavid du Colombier 		for (n1 = g->Other; n1; n1 = n2)
6777dd7cddfSDavid du Colombier 		{	n2 = n1->nxt;
6787dd7cddfSDavid du Colombier 			releasenode(1, n1);
6797dd7cddfSDavid du Colombier 		}
6807dd7cddfSDavid du Colombier 		for (n1 = g->Old; n1; n1 = n2)
6817dd7cddfSDavid du Colombier 		{	n2 = n1->nxt;
6827dd7cddfSDavid du Colombier 			releasenode(1, n1);
6837dd7cddfSDavid du Colombier 		}
6847dd7cddfSDavid du Colombier 		for (n1 = g->Next; n1; n1 = n2)
6857dd7cddfSDavid du Colombier 		{	n2 = n1->nxt;
6867dd7cddfSDavid du Colombier 			releasenode(1, n1);
6877dd7cddfSDavid du Colombier 		}
6887dd7cddfSDavid du Colombier 		return 1;
6897dd7cddfSDavid du Colombier 	}
6907dd7cddfSDavid du Colombier 
6917dd7cddfSDavid du Colombier 	if (newstates) tl_verbose=1;
6927dd7cddfSDavid du Colombier 	Debug2("	New Node %s [", g->name->name);
6937dd7cddfSDavid du Colombier 	for (n1 = g->Old; n1; n1 = n1->nxt)
6947dd7cddfSDavid du Colombier 	{ Dump(n1); Debug(", "); }
6957dd7cddfSDavid du Colombier 	Debug2("] nr %d\n", Base);
6967dd7cddfSDavid du Colombier 	if (newstates) tl_verbose=0;
6977dd7cddfSDavid du Colombier 
6987dd7cddfSDavid du Colombier 	Base++;
6997dd7cddfSDavid du Colombier 	g->nxt = Nodes_Set;
7007dd7cddfSDavid du Colombier 	Nodes_Set = g;
7017dd7cddfSDavid du Colombier 
7027dd7cddfSDavid du Colombier 	return 0;
7037dd7cddfSDavid du Colombier }
7047dd7cddfSDavid du Colombier 
7057dd7cddfSDavid du Colombier static void
expand_g(Graph * g)706312a1df1SDavid du Colombier expand_g(Graph *g)
7077dd7cddfSDavid du Colombier {	Node *now, *n1, *n2, *nx;
7087dd7cddfSDavid du Colombier 	int can_release;
7097dd7cddfSDavid du Colombier 
7107dd7cddfSDavid du Colombier 	if (!g->New)
7117dd7cddfSDavid du Colombier 	{	Debug2("\nDone with %s", g->name->name);
7127dd7cddfSDavid du Colombier 		if (tl_verbose) dump_graph(g);
7137dd7cddfSDavid du Colombier 		if (not_new(g))
7147dd7cddfSDavid du Colombier 		{	if (tl_verbose) printf("\tIs Not New\n");
7157dd7cddfSDavid du Colombier 			return;
7167dd7cddfSDavid du Colombier 		}
7177dd7cddfSDavid du Colombier 		if (g->Next)
7187dd7cddfSDavid du Colombier 		{	Debug("	Has Next [");
7197dd7cddfSDavid du Colombier 			for (n1 = g->Next; n1; n1 = n1->nxt)
7207dd7cddfSDavid du Colombier 			{ Dump(n1); Debug(", "); }
7217dd7cddfSDavid du Colombier 			Debug("]\n");
7227dd7cddfSDavid du Colombier 
7237dd7cddfSDavid du Colombier 			ng(ZS, getsym(g->name), g->Next, ZN, ZN);
7247dd7cddfSDavid du Colombier 		}
7257dd7cddfSDavid du Colombier 		return;
7267dd7cddfSDavid du Colombier 	}
7277dd7cddfSDavid du Colombier 
7287dd7cddfSDavid du Colombier 	if (tl_verbose)
7297dd7cddfSDavid du Colombier 	{	Symbol *z;
7307dd7cddfSDavid du Colombier 		printf("\nExpand %s, from ", g->name->name);
7317dd7cddfSDavid du Colombier 		for (z = g->incoming; z; z = z->next)
7327dd7cddfSDavid du Colombier 			printf("%s, ", z->name);
7337dd7cddfSDavid du Colombier 		printf("\n\thandle:\t"); Explain(g->New->ntyp);
7347dd7cddfSDavid du Colombier 		dump_graph(g);
7357dd7cddfSDavid du Colombier 	}
7367dd7cddfSDavid du Colombier 
7377dd7cddfSDavid du Colombier 	if (g->New->ntyp == AND)
7387dd7cddfSDavid du Colombier 	{	if (g->New->nxt)
7397dd7cddfSDavid du Colombier 		{	n2 = g->New->rgt;
7407dd7cddfSDavid du Colombier 			while (n2->nxt)
7417dd7cddfSDavid du Colombier 				n2 = n2->nxt;
7427dd7cddfSDavid du Colombier 			n2->nxt = g->New->nxt;
7437dd7cddfSDavid du Colombier 		}
7447dd7cddfSDavid du Colombier 		n1 = n2 = g->New->lft;
7457dd7cddfSDavid du Colombier 		while (n2->nxt)
7467dd7cddfSDavid du Colombier 			n2 = n2->nxt;
7477dd7cddfSDavid du Colombier 		n2->nxt = g->New->rgt;
7487dd7cddfSDavid du Colombier 
7497dd7cddfSDavid du Colombier 		releasenode(0, g->New);
7507dd7cddfSDavid du Colombier 
7517dd7cddfSDavid du Colombier 		g->New = n1;
7527dd7cddfSDavid du Colombier 		push_stack(g);
7537dd7cddfSDavid du Colombier 		return;
7547dd7cddfSDavid du Colombier 	}
7557dd7cddfSDavid du Colombier 
7567dd7cddfSDavid du Colombier 	can_release = 0;	/* unless it need not go into Old */
7577dd7cddfSDavid du Colombier 	now = g->New;
7587dd7cddfSDavid du Colombier 	g->New = g->New->nxt;
7597dd7cddfSDavid du Colombier 	now->nxt = ZN;
7607dd7cddfSDavid du Colombier 
761312a1df1SDavid du Colombier 	if (now->ntyp != TRUE)
7627dd7cddfSDavid du Colombier 	{	if (g->Old)
7637dd7cddfSDavid du Colombier 		{	for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
7647dd7cddfSDavid du Colombier 				if (isequal(now, n1))
7657dd7cddfSDavid du Colombier 				{	can_release = 1;
7667dd7cddfSDavid du Colombier 					goto out;
7677dd7cddfSDavid du Colombier 				}
7687dd7cddfSDavid du Colombier 			n1->nxt = now;
7697dd7cddfSDavid du Colombier 		} else
7707dd7cddfSDavid du Colombier 			g->Old = now;
7717dd7cddfSDavid du Colombier 	}
7727dd7cddfSDavid du Colombier out:
7737dd7cddfSDavid du Colombier 	switch (now->ntyp) {
7747dd7cddfSDavid du Colombier 	case FALSE:
7757dd7cddfSDavid du Colombier 		push_stack(g);
7767dd7cddfSDavid du Colombier 		break;
7777dd7cddfSDavid du Colombier 	case TRUE:
7787dd7cddfSDavid du Colombier 		releasenode(1, now);
7797dd7cddfSDavid du Colombier 		push_stack(g);
7807dd7cddfSDavid du Colombier 		break;
7817dd7cddfSDavid du Colombier 	case PREDICATE:
7827dd7cddfSDavid du Colombier 	case NOT:
783*de2caf28SDavid du Colombier 	case CEXPR:
7847dd7cddfSDavid du Colombier 		if (can_release) releasenode(1, now);
7857dd7cddfSDavid du Colombier 		push_stack(g);
7867dd7cddfSDavid du Colombier 		break;
7877dd7cddfSDavid du Colombier 	case V_OPER:
78800d97012SDavid du Colombier 		Assert(now->rgt != ZN, now->ntyp);
78900d97012SDavid du Colombier 		Assert(now->lft != ZN, now->ntyp);
7907dd7cddfSDavid du Colombier 		Assert(now->rgt->nxt == ZN, now->ntyp);
7917dd7cddfSDavid du Colombier 		Assert(now->lft->nxt == ZN, now->ntyp);
7927dd7cddfSDavid du Colombier 		n1 = now->rgt;
7937dd7cddfSDavid du Colombier 		n1->nxt = g->New;
7947dd7cddfSDavid du Colombier 
7957dd7cddfSDavid du Colombier 		if (can_release)
7967dd7cddfSDavid du Colombier 			nx = now;
7977dd7cddfSDavid du Colombier 		else
7987dd7cddfSDavid du Colombier 			nx = getnode(now); /* now also appears in Old */
7997dd7cddfSDavid du Colombier 		nx->nxt = g->Next;
8007dd7cddfSDavid du Colombier 
8017dd7cddfSDavid du Colombier 		n2 = now->lft;
8027dd7cddfSDavid du Colombier 		n2->nxt = getnode(now->rgt);
8037dd7cddfSDavid du Colombier 		n2->nxt->nxt = g->New;
8047dd7cddfSDavid du Colombier 		g->New = flatten(n2);
8057dd7cddfSDavid du Colombier 		push_stack(g);
8067dd7cddfSDavid du Colombier 		ng(ZS, g->incoming, n1, g->Old, nx);
8077dd7cddfSDavid du Colombier 		break;
8087dd7cddfSDavid du Colombier 
8097dd7cddfSDavid du Colombier 	case U_OPER:
8107dd7cddfSDavid du Colombier 		Assert(now->rgt->nxt == ZN, now->ntyp);
8117dd7cddfSDavid du Colombier 		Assert(now->lft->nxt == ZN, now->ntyp);
8127dd7cddfSDavid du Colombier 		n1 = now->lft;
8137dd7cddfSDavid du Colombier 
8147dd7cddfSDavid du Colombier 		if (can_release)
8157dd7cddfSDavid du Colombier 			nx = now;
8167dd7cddfSDavid du Colombier 		else
8177dd7cddfSDavid du Colombier 			nx = getnode(now); /* now also appears in Old */
8187dd7cddfSDavid du Colombier 		nx->nxt = g->Next;
8197dd7cddfSDavid du Colombier 
8207dd7cddfSDavid du Colombier 		n2 = now->rgt;
8217dd7cddfSDavid du Colombier 		n2->nxt = g->New;
8227dd7cddfSDavid du Colombier 
8237dd7cddfSDavid du Colombier 		goto common;
8247dd7cddfSDavid du Colombier 
8257dd7cddfSDavid du Colombier #ifdef NXT
8267dd7cddfSDavid du Colombier 	case NEXT:
82700d97012SDavid du Colombier 		Assert(now->lft != ZN, now->ntyp);
8287dd7cddfSDavid du Colombier 		nx = dupnode(now->lft);
8297dd7cddfSDavid du Colombier 		nx->nxt = g->Next;
8307dd7cddfSDavid du Colombier 		g->Next = nx;
8317dd7cddfSDavid du Colombier 		if (can_release) releasenode(0, now);
8327dd7cddfSDavid du Colombier 		push_stack(g);
8337dd7cddfSDavid du Colombier 		break;
8347dd7cddfSDavid du Colombier #endif
8357dd7cddfSDavid du Colombier 
8367dd7cddfSDavid du Colombier 	case OR:
8377dd7cddfSDavid du Colombier 		Assert(now->rgt->nxt == ZN, now->ntyp);
8387dd7cddfSDavid du Colombier 		Assert(now->lft->nxt == ZN, now->ntyp);
8397dd7cddfSDavid du Colombier 		n1 = now->lft;
8407dd7cddfSDavid du Colombier 		nx = g->Next;
8417dd7cddfSDavid du Colombier 
8427dd7cddfSDavid du Colombier 		n2 = now->rgt;
8437dd7cddfSDavid du Colombier 		n2->nxt = g->New;
8447dd7cddfSDavid du Colombier common:
8457dd7cddfSDavid du Colombier 		n1->nxt = g->New;
8467dd7cddfSDavid du Colombier 
8477dd7cddfSDavid du Colombier 		ng(ZS, g->incoming, n1, g->Old, nx);
8487dd7cddfSDavid du Colombier 		g->New = flatten(n2);
8497dd7cddfSDavid du Colombier 
8507dd7cddfSDavid du Colombier 		if (can_release) releasenode(1, now);
8517dd7cddfSDavid du Colombier 
8527dd7cddfSDavid du Colombier 		push_stack(g);
8537dd7cddfSDavid du Colombier 		break;
8547dd7cddfSDavid du Colombier 	}
8557dd7cddfSDavid du Colombier }
8567dd7cddfSDavid du Colombier 
8577dd7cddfSDavid du Colombier Node *
twocases(Node * p)8587dd7cddfSDavid du Colombier twocases(Node *p)
8597dd7cddfSDavid du Colombier {	Node *q;
8607dd7cddfSDavid du Colombier 	/* 1: ([]p1 && []p2) == [](p1 && p2) */
8617dd7cddfSDavid du Colombier 	/* 2: (<>p1 || <>p2) == <>(p1 || p2) */
8627dd7cddfSDavid du Colombier 
8637dd7cddfSDavid du Colombier 	if (!p) return p;
8647dd7cddfSDavid du Colombier 
8657dd7cddfSDavid du Colombier 	switch(p->ntyp) {
8667dd7cddfSDavid du Colombier 	case AND:
8677dd7cddfSDavid du Colombier 	case OR:
8687dd7cddfSDavid du Colombier 	case U_OPER:
8697dd7cddfSDavid du Colombier 	case V_OPER:
8707dd7cddfSDavid du Colombier 		p->lft = twocases(p->lft);
8717dd7cddfSDavid du Colombier 		p->rgt = twocases(p->rgt);
8727dd7cddfSDavid du Colombier 		break;
8737dd7cddfSDavid du Colombier #ifdef NXT
8747dd7cddfSDavid du Colombier 	case NEXT:
8757dd7cddfSDavid du Colombier #endif
8767dd7cddfSDavid du Colombier 	case NOT:
8777dd7cddfSDavid du Colombier 		p->lft = twocases(p->lft);
8787dd7cddfSDavid du Colombier 		break;
8797dd7cddfSDavid du Colombier 
8807dd7cddfSDavid du Colombier 	default:
8817dd7cddfSDavid du Colombier 		break;
8827dd7cddfSDavid du Colombier 	}
8837dd7cddfSDavid du Colombier 	if (p->ntyp == AND	/* 1 */
8847dd7cddfSDavid du Colombier 	&&  p->lft->ntyp == V_OPER
8857dd7cddfSDavid du Colombier 	&&  p->lft->lft->ntyp == FALSE
8867dd7cddfSDavid du Colombier 	&&  p->rgt->ntyp == V_OPER
8877dd7cddfSDavid du Colombier 	&&  p->rgt->lft->ntyp == FALSE)
8887dd7cddfSDavid du Colombier 	{	q = tl_nn(V_OPER, False,
8897dd7cddfSDavid du Colombier 			tl_nn(AND, p->lft->rgt, p->rgt->rgt));
8907dd7cddfSDavid du Colombier 	} else
8917dd7cddfSDavid du Colombier 	if (p->ntyp == OR	/* 2 */
8927dd7cddfSDavid du Colombier 	&&  p->lft->ntyp == U_OPER
8937dd7cddfSDavid du Colombier 	&&  p->lft->lft->ntyp == TRUE
8947dd7cddfSDavid du Colombier 	&&  p->rgt->ntyp == U_OPER
8957dd7cddfSDavid du Colombier 	&&  p->rgt->lft->ntyp == TRUE)
8967dd7cddfSDavid du Colombier 	{	q = tl_nn(U_OPER, True,
8977dd7cddfSDavid du Colombier 			tl_nn(OR, p->lft->rgt, p->rgt->rgt));
8987dd7cddfSDavid du Colombier 	} else
8997dd7cddfSDavid du Colombier 		q = p;
9007dd7cddfSDavid du Colombier 	return q;
9017dd7cddfSDavid du Colombier }
9027dd7cddfSDavid du Colombier 
9037dd7cddfSDavid du Colombier void
trans(Node * p)9047dd7cddfSDavid du Colombier trans(Node *p)
9057dd7cddfSDavid du Colombier {	Node	*op;
9067dd7cddfSDavid du Colombier 	Graph	*g;
9077dd7cddfSDavid du Colombier 
9087dd7cddfSDavid du Colombier 	if (!p || tl_errs) return;
9097dd7cddfSDavid du Colombier 
9107dd7cddfSDavid du Colombier 	p = twocases(p);
9117dd7cddfSDavid du Colombier 
9127dd7cddfSDavid du Colombier 	if (tl_verbose || tl_terse)
9137dd7cddfSDavid du Colombier 	{	fprintf(tl_out, "\t/* Normlzd: ");
9147dd7cddfSDavid du Colombier 		dump(p);
9157dd7cddfSDavid du Colombier 		fprintf(tl_out, " */\n");
9167dd7cddfSDavid du Colombier 	}
9177dd7cddfSDavid du Colombier 	if (tl_terse)
9187dd7cddfSDavid du Colombier 		return;
9197dd7cddfSDavid du Colombier 
9207dd7cddfSDavid du Colombier 	op = dupnode(p);
9217dd7cddfSDavid du Colombier 
9227dd7cddfSDavid du Colombier 	ng(ZS, getsym(tl_lookup("init")), p, ZN, ZN);
923312a1df1SDavid du Colombier 	while ((g = Nodes_Stack) != (Graph *) 0)
9247dd7cddfSDavid du Colombier 	{	Nodes_Stack = g->nxt;
925312a1df1SDavid du Colombier 		expand_g(g);
9267dd7cddfSDavid du Colombier 	}
9277dd7cddfSDavid du Colombier 	if (newstates)
9287dd7cddfSDavid du Colombier 		return;
9297dd7cddfSDavid du Colombier 
9307dd7cddfSDavid du Colombier 	fixinit(p);
9317dd7cddfSDavid du Colombier 	liveness(flatten(op));	/* was: liveness(op); */
9327dd7cddfSDavid du Colombier 
9337dd7cddfSDavid du Colombier 	mkbuchi();
9347dd7cddfSDavid du Colombier 	if (tl_verbose)
9357dd7cddfSDavid du Colombier 	{	printf("/*\n");
9367dd7cddfSDavid du Colombier 		printf(" * %d states in Streett automaton\n", Base);
9377dd7cddfSDavid du Colombier 		printf(" * %d Streett acceptance conditions\n", Max_Red);
9387dd7cddfSDavid du Colombier 		printf(" * %d Buchi states\n", Total);
9397dd7cddfSDavid du Colombier 		printf(" */\n");
9407dd7cddfSDavid du Colombier 	}
9417dd7cddfSDavid du Colombier }
942