1 /***** tl_spin: tl_buchi.c *****/
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
8 * Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper,
9 * presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995.
14 extern int tl_verbose, tl_clutter, Total, Max_Red;
15 extern char *claim_name;
17 FILE *tl_out; /* if standalone: = stdout; */
19 typedef struct Transition {
22 int redundant, merged, marked;
23 struct Transition *nxt;
26 typedef struct State {
30 unsigned char redundant;
31 unsigned char accepting;
32 unsigned char reachable;
36 static State *never = (State *) 0;
47 sametrans(Transition *s, Transition *t)
49 if (strcmp(s->name->name, t->name->name) != 0)
51 return isequal(s->cond, t->cond);
69 p->lft = Prune(p->lft);
71 { releasenode(1, p->rgt);
74 p->rgt = Prune(p->rgt);
76 { releasenode(1, p->lft);
81 p->lft = Prune(p->lft);
84 p->rgt = Prune(p->rgt);
96 for (b = never; b; b = b->nxt)
97 if (!strcmp(b->name->name, nm))
99 if (strcmp(nm, "accept_all"))
100 { if (strncmp(nm, "accept", 6))
101 { int i; char altnm[64];
102 for (i = 0; i < 64; i++)
106 Fatal("name too long %s", nm);
107 sprintf(altnm, "accept%s", &nm[i]);
108 return findstate(altnm);
110 /* Fatal("buchi: no state %s", nm); */
119 if (!b || b->reachable) return;
123 printf("/* redundant state %s */\n",
125 for (t = b->trans; t; t = t->nxt)
127 { Dfs(findstate(t->name->name));
129 && strcmp(t->name->name, "accept_all") == 0)
136 retarget(char *from, char *to)
139 Symbol *To = tl_lookup(to);
141 if (tl_verbose) printf("replace %s with %s\n", from, to);
143 for (b = never; b; b = b->nxt)
144 { if (!strcmp(b->name->name, from))
147 for (t = b->trans; t; t = t->nxt)
148 { if (!strcmp(t->name->name, from))
163 n->lft = nonxt(n->lft);
164 n->rgt = nonxt(n->rgt);
165 if (!n->lft || !n->rgt)
169 n->lft = nonxt(n->lft);
170 n->rgt = nonxt(n->rgt);
185 combination(Node *s, Node *t)
192 { printf("\tnonxtA: "); dump(a);
193 printf("\n\tnonxtB: "); dump(b);
196 /* if there's only a X(f), its equivalent to true */
200 nc = tl_nn(OR, a, b);
202 nc = tl_nn(OR, s, t);
205 { printf("\tcombo: "); dump(nc);
212 unclutter(Node *n, char *snm)
213 { Node *t, *s, *v, *u;
216 /* check only simple cases like !q && q */
217 for (t = n; t; t = t->rgt)
219 { if (t->ntyp != AND || !t->lft)
221 if (t->lft->ntyp != PREDICATE
223 && t->lft->ntyp != NEXT
225 && t->lft->ntyp != NOT)
228 { if (t->ntyp != PREDICATE
237 for (t = n; t; t = t->rgt)
243 && v->lft->ntyp == PREDICATE)
245 for (s = n; s; s = s->rgt)
246 { if (s == t) continue;
251 if (u->ntyp == PREDICATE
252 && strcmp(u->sym->name, w->name) == 0)
254 { printf("BINGO %s:\t", snm);
270 for (p = never; p; p = p->nxt)
271 for (s = p->trans; s; s = s->nxt)
272 { s->cond = unclutter(s->cond, p->name->name);
274 && s->cond->ntyp == FALSE)
286 for (s = a->trans; s; s = s->nxt)
287 { printf("%s ", s->name?s->name->name:"-");
289 printf(" %d %d %d\n", s->redundant, s->merged, s->marked);
297 Node *nc; int cnt = 0;
299 for (b = never; b; b = b->nxt)
300 { if (!b->reachable) continue;
302 for (s = b->trans; s; s = s->nxt)
303 { if (s->redundant) continue;
305 for (t = s->nxt; t; t = t->nxt)
307 && !strcmp(s->name->name, t->name->name))
309 { printf("===\nstate %s, trans to %s redundant\n",
310 b->name->name, s->name->name);
312 printf(" conditions ");
313 dump(s->cond); printf(" <-> ");
314 dump(t->cond); printf("\n");
317 if (!s->cond) /* same as T */
318 { releasenode(1, t->cond); /* T or t */
321 { releasenode(1, s->cond);
324 { nc = combination(s->cond, t->cond);
326 t->cond = rewrite(nc);
336 all_trans_match(State *a, State *b)
338 int found, result = 0;
340 if (a->accepting != b->accepting)
343 for (s = a->trans; s; s = s->nxt)
344 { if (s->redundant) continue;
346 for (t = b->trans; t; t = t->nxt)
347 { if (t->redundant) continue;
356 for (s = b->trans; s; s = s->nxt)
357 { if (s->redundant || s->marked) continue;
359 for (t = a->trans; t; t = t->nxt)
360 { if (t->redundant) continue;
370 for (s = b->trans; s; s = s->nxt)
381 all_bucky(State *a, State *b)
383 int found, result = 0;
385 for (s = a->trans; s; s = s->nxt)
386 { if (s->redundant) continue;
388 for (t = b->trans; t; t = t->nxt)
389 { if (t->redundant) continue;
391 if (isequal(s->cond, t->cond))
392 { if (strcmp(s->name->name, b->name->name) == 0
393 && strcmp(t->name->name, a->name->name) == 0)
394 { found = 1; /* they point to each other */
398 if (strcmp(s->name->name, t->name->name) == 0
399 && strcmp(s->name->name, "accept_all") == 0)
403 /* same exit from which there is no return */
410 for (s = b->trans; s; s = s->nxt)
411 { if (s->redundant || s->marked) continue;
413 for (t = a->trans; t; t = t->nxt)
414 { if (t->redundant) continue;
416 if (isequal(s->cond, t->cond))
417 { if (strcmp(s->name->name, a->name->name) == 0
418 && strcmp(t->name->name, b->name->name) == 0)
423 if (strcmp(s->name->name, t->name->name) == 0
424 && strcmp(s->name->name, "accept_all") == 0)
436 for (s = b->trans; s; s = s->nxt)
443 { State *a, *b, *c, *d;
448 for (a = never; a; a = a->nxt)
449 { if (!a->reachable) continue;
451 if (a->redundant) continue;
453 for (b = a->nxt; b; b = b->nxt)
454 { if (!b->reachable) continue;
456 if (b->redundant) continue;
461 { printf("%s bucky match %s\n",
462 a->name->name, b->name->name);
465 if (a->accepting && !b->accepting)
466 { if (strcmp(b->name->name, "T0_init") == 0)
476 retarget(c->name->name, d->name->name);
477 if (!strncmp(c->name->name, "accept", 6)
480 sprintf(buf, "T0%s", &(c->name->name[6]));
481 retarget(buf, d->name->name);
486 } while (m && cnt < 10);
501 for (a = never; a; a = a->nxt)
502 { if (v && !a->reachable) continue;
504 if (a->redundant) continue; /* 3.3.10 */
506 for (b = a->nxt; b; b = b->nxt)
507 { if (v && !b->reachable) continue;
509 if (b->redundant) continue; /* 3.3.10 */
511 if (all_trans_match(a, b))
514 { printf("%d: state %s equals state %s\n",
515 cnt, a->name->name, b->name->name);
520 retarget(a->name->name, b->name->name);
521 if (!strncmp(a->name->name, "accept", 6)
524 sprintf(buf, "T0%s", &(a->name->name[6]));
525 retarget(buf, b->name->name);
531 { printf("\n%d: state %s differs from state %s [%d,%d]\n",
532 cnt, a->name->name, b->name->name,
533 a->accepting, b->accepting);
541 } while (m && cnt < 10);
548 rev_trans(Transition *t) /* print transitions in reverse order... */
553 if (t->redundant && !tl_verbose) return;
555 if (strcmp(t->name->name, "accept_all") == 0) /* 6.2.4 */
556 { /* not d_step because there may be remote refs */
557 fprintf(tl_out, "\t:: atomic { (");
558 if (dump_cond(t->cond, t->cond, 1))
559 fprintf(tl_out, "1");
560 fprintf(tl_out, ") -> assert(!(");
561 if (dump_cond(t->cond, t->cond, 1))
562 fprintf(tl_out, "1");
563 fprintf(tl_out, ")) }\n");
565 { fprintf(tl_out, "\t:: (");
566 if (dump_cond(t->cond, t->cond, 1))
567 fprintf(tl_out, "1");
568 fprintf(tl_out, ") -> goto %s\n", t->name->name);
576 if (!b || (!tl_verbose && !b->reachable)) return;
578 b->reachable = 0; /* print only once */
579 fprintf(tl_out, "%s:\n", b->name->name);
582 { fprintf(tl_out, " /* ");
583 dump(b->colors->Other);
584 fprintf(tl_out, " */\n");
587 if (strncmp(b->name->name, "accept", 6) == 0
589 fprintf(tl_out, "T0%s:\n", &(b->name->name[6]));
591 fprintf(tl_out, "\tdo\n");
594 if (!tcnt) fprintf(tl_out, "\t:: false\n");
595 fprintf(tl_out, "\tod;\n");
600 addtrans(Graph *col, char *from, Node *op, char *to)
604 t = (Transition *) tl_emalloc(sizeof(Transition));
605 t->name = tl_lookup(to);
606 t->cond = Prune(dupnode(op));
609 { printf("\n%s <<\t", from); dump(op);
610 printf("\n\t"); dump(t->cond);
611 printf(">> %s\n", t->name->name);
613 if (t->cond) t->cond = rewrite(t->cond);
615 for (b = never; b; b = b->nxt)
616 if (!strcmp(b->name->name, from))
621 b = (State *) tl_emalloc(sizeof(State));
622 b->name = tl_lookup(from);
625 if (!strncmp(from, "accept", 6))
634 for (p = never; p; p = p->nxt)
641 { State *b; int cnt1, cnt2=0;
642 extern void put_uform(void);
644 if (tl_clutter) clutter();
646 b = findstate("T0_init");
647 if (b && (Max_Red == 0))
651 b = findstate("T0_init");
653 fprintf(tl_out, "never %s { /* ", claim_name?claim_name:"");
655 fprintf(tl_out, " */\n");
661 cnt2 = mergestates(1);
663 printf("/* >>%d,%d<< */\n", cnt1, cnt2);
671 if (b && b->accepting)
672 fprintf(tl_out, "accept_init:\n");
675 { fprintf(tl_out, " 0 /* false */;\n");
677 { printstate(b); /* init state must be first */
678 for (b = never; b; b = b->nxt)
682 fprintf(tl_out, "accept_all:\n skip\n");
683 fprintf(tl_out, "}\n");