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