tl_trans.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884
  1. /***** tl_spin: tl_trans.c *****/
  2. /* Copyright (c) 1995-2000 by Lucent Technologies - Bell Laboratories */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* Permission is given to distribute this code provided that this intro- */
  5. /* ductory message is not removed and no monies are exchanged. */
  6. /* No guarantee is expressed or implied by the distribution of this code. */
  7. /* Written by Gerard J. Holzmann, Bell Laboratories, U.S.A. */
  8. /* Based on the translation algorithm by Gerth, Peled, Vardi, and Wolper, */
  9. /* presented at the PSTV Conference, held in 1995, Warsaw, Poland 1995. */
  10. /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */
  11. #include "tl.h"
  12. extern FILE *tl_out;
  13. extern int tl_errs, tl_verbose, tl_terse, newstates;
  14. int Stack_mx=0, Max_Red=0, Total=0;
  15. static Mapping *Mapped = (Mapping *) 0;
  16. static Graph *Nodes_Set = (Graph *) 0;
  17. static Graph *Nodes_Stack = (Graph *) 0;
  18. static char dumpbuf[2048];
  19. static int Red_cnt = 0;
  20. static int Lab_cnt = 0;
  21. static int Base = 0;
  22. static int Stack_sz = 0;
  23. static Graph *findgraph(char *);
  24. static Graph *pop_stack(void);
  25. static Node *Duplicate(Node *);
  26. static Node *flatten(Node *);
  27. static Symbol *catSlist(Symbol *, Symbol *);
  28. static Symbol *dupSlist(Symbol *);
  29. static char *newname(void);
  30. static int choueka(Graph *, int);
  31. static int not_new(Graph *);
  32. static int set_prefix(char *, int, Graph *);
  33. static void Addout(char *, char *);
  34. static void fsm_trans(Graph *, int, char *);
  35. static void mkbuchi(void);
  36. static void expand(Graph *);
  37. static void fixinit(Node *);
  38. static void liveness(Node *);
  39. static void mk_grn(Node *);
  40. static void mk_red(Node *);
  41. static void ng(Symbol *, Symbol *, Node *, Node *, Node *);
  42. static void push_stack(Graph *);
  43. static void sdump(Node *);
  44. static void
  45. dump_graph(Graph *g)
  46. { Node *n1;
  47. printf("\n\tnew:\t");
  48. for (n1 = g->New; n1; n1 = n1->nxt)
  49. { dump(n1); printf(", "); }
  50. printf("\n\told:\t");
  51. for (n1 = g->Old; n1; n1 = n1->nxt)
  52. { dump(n1); printf(", "); }
  53. printf("\n\tnxt:\t");
  54. for (n1 = g->Next; n1; n1 = n1->nxt)
  55. { dump(n1); printf(", "); }
  56. printf("\n\tother:\t");
  57. for (n1 = g->Other; n1; n1 = n1->nxt)
  58. { dump(n1); printf(", "); }
  59. printf("\n");
  60. }
  61. static void
  62. push_stack(Graph *g)
  63. {
  64. if (!g) return;
  65. g->nxt = Nodes_Stack;
  66. Nodes_Stack = g;
  67. if (tl_verbose)
  68. { Symbol *z;
  69. printf("\nPush %s, from ", g->name->name);
  70. for (z = g->incoming; z; z = z->next)
  71. printf("%s, ", z->name);
  72. dump_graph(g);
  73. }
  74. Stack_sz++;
  75. if (Stack_sz > Stack_mx) Stack_mx = Stack_sz;
  76. }
  77. static Graph *
  78. pop_stack(void)
  79. { Graph *g = Nodes_Stack;
  80. if (g) Nodes_Stack = g->nxt;
  81. Stack_sz--;
  82. return g;
  83. }
  84. static char *
  85. newname(void)
  86. { static int cnt = 0;
  87. static char buf[32];
  88. sprintf(buf, "S%d", cnt++);
  89. return buf;
  90. }
  91. static int
  92. has_clause(int tok, Graph *p, Node *n)
  93. { Node *q, *qq;
  94. switch (n->ntyp) {
  95. case AND:
  96. return has_clause(tok, p, n->lft) &&
  97. has_clause(tok, p, n->rgt);
  98. case OR:
  99. return has_clause(tok, p, n->lft) ||
  100. has_clause(tok, p, n->rgt);
  101. }
  102. for (q = p->Other; q; q = q->nxt)
  103. { qq = right_linked(q);
  104. if (anywhere(tok, n, qq))
  105. return 1;
  106. }
  107. return 0;
  108. }
  109. static void
  110. mk_grn(Node *n)
  111. { Graph *p;
  112. n = right_linked(n);
  113. for (p = Nodes_Set; p; p = p->nxt)
  114. if (p->outgoing
  115. && has_clause(AND, p, n))
  116. { p->isgrn[p->grncnt++] =
  117. (unsigned char) Red_cnt;
  118. Lab_cnt++;
  119. }
  120. }
  121. static void
  122. mk_red(Node *n)
  123. { Graph *p;
  124. n = right_linked(n);
  125. for (p = Nodes_Set; p; p = p->nxt)
  126. { if (p->outgoing
  127. && has_clause(0, p, n))
  128. { if (p->redcnt >= 63)
  129. Fatal("too many Untils", (char *)0);
  130. p->isred[p->redcnt++] =
  131. (unsigned char) Red_cnt;
  132. Lab_cnt++; Max_Red = Red_cnt;
  133. } }
  134. }
  135. static void
  136. liveness(Node *n)
  137. {
  138. if (n)
  139. switch (n->ntyp) {
  140. #ifdef NXT
  141. case NEXT:
  142. liveness(n->lft);
  143. break;
  144. #endif
  145. case U_OPER:
  146. Red_cnt++;
  147. mk_red(n);
  148. mk_grn(n->rgt);
  149. /* fall through */
  150. case V_OPER:
  151. case OR: case AND:
  152. liveness(n->lft);
  153. liveness(n->rgt);
  154. break;
  155. }
  156. }
  157. static Graph *
  158. findgraph(char *nm)
  159. { Graph *p;
  160. Mapping *m;
  161. for (p = Nodes_Set; p; p = p->nxt)
  162. if (!strcmp(p->name->name, nm))
  163. return p;
  164. for (m = Mapped; m; m = m->nxt)
  165. if (strcmp(m->from, nm) == 0)
  166. return m->to;
  167. printf("warning: node %s not found\n", nm);
  168. return (Graph *) 0;
  169. }
  170. static void
  171. Addout(char *to, char *from)
  172. { Graph *p = findgraph(from);
  173. Symbol *s;
  174. if (!p) return;
  175. s = getsym(tl_lookup(to));
  176. s->next = p->outgoing;
  177. p->outgoing = s;
  178. }
  179. #ifdef NXT
  180. int
  181. only_nxt(Node *n)
  182. {
  183. switch (n->ntyp) {
  184. case NEXT:
  185. return 1;
  186. case OR:
  187. case AND:
  188. return only_nxt(n->rgt) && only_nxt(n->lft);
  189. default:
  190. return 0;
  191. }
  192. }
  193. #endif
  194. int
  195. dump_cond(Node *pp, Node *r, int first)
  196. { Node *q;
  197. int frst = first;
  198. if (!pp) return frst;
  199. q = dupnode(pp);
  200. q = rewrite(q);
  201. if (q->ntyp == PREDICATE
  202. || q->ntyp == NOT
  203. #ifndef NXT
  204. || q->ntyp == OR
  205. #endif
  206. || q->ntyp == FALSE)
  207. { if (!frst) fprintf(tl_out, " && ");
  208. dump(q);
  209. frst = 0;
  210. #ifdef NXT
  211. } else if (q->ntyp == OR)
  212. { if (!frst) fprintf(tl_out, " && ");
  213. fprintf(tl_out, "((");
  214. frst = dump_cond(q->lft, r, 1);
  215. if (!frst)
  216. fprintf(tl_out, ") || (");
  217. else
  218. { if (only_nxt(q->lft))
  219. { fprintf(tl_out, "1))");
  220. return 0;
  221. }
  222. }
  223. frst = dump_cond(q->rgt, r, 1);
  224. if (frst)
  225. { if (only_nxt(q->rgt))
  226. fprintf(tl_out, "1");
  227. else
  228. fprintf(tl_out, "0");
  229. frst = 0;
  230. }
  231. fprintf(tl_out, "))");
  232. #endif
  233. } else if (q->ntyp == V_OPER
  234. && !anywhere(AND, q->rgt, r))
  235. { frst = dump_cond(q->rgt, r, frst);
  236. } else if (q->ntyp == AND)
  237. {
  238. frst = dump_cond(q->lft, r, frst);
  239. frst = dump_cond(q->rgt, r, frst);
  240. }
  241. return frst;
  242. }
  243. static int
  244. choueka(Graph *p, int count)
  245. { int j, k, incr_cnt = 0;
  246. for (j = count; j <= Max_Red; j++) /* for each acceptance class */
  247. { int delta = 0;
  248. /* is state p labeled Grn-j OR not Red-j ? */
  249. for (k = 0; k < (int) p->grncnt; k++)
  250. if (p->isgrn[k] == j)
  251. { delta = 1;
  252. break;
  253. }
  254. if (delta)
  255. { incr_cnt++;
  256. continue;
  257. }
  258. for (k = 0; k < (int) p->redcnt; k++)
  259. if (p->isred[k] == j)
  260. { delta = 1;
  261. break;
  262. }
  263. if (delta) break;
  264. incr_cnt++;
  265. }
  266. return incr_cnt;
  267. }
  268. static int
  269. set_prefix(char *pref, int count, Graph *r2)
  270. { int incr_cnt = 0; /* acceptance class 'count' */
  271. if (Lab_cnt == 0
  272. || Max_Red == 0)
  273. sprintf(pref, "accept"); /* new */
  274. else if (count >= Max_Red)
  275. sprintf(pref, "T0"); /* cycle */
  276. else
  277. { incr_cnt = choueka(r2, count+1);
  278. if (incr_cnt + count >= Max_Red)
  279. sprintf(pref, "accept"); /* last hop */
  280. else
  281. sprintf(pref, "T%d", count+incr_cnt);
  282. }
  283. return incr_cnt;
  284. }
  285. static void
  286. fsm_trans(Graph *p, int count, char *curnm)
  287. { Graph *r;
  288. Symbol *s;
  289. char prefix[128], nwnm[128];
  290. if (!p->outgoing)
  291. addtrans(p, curnm, False, "accept_all");
  292. for (s = p->outgoing; s; s = s->next)
  293. { r = findgraph(s->name);
  294. if (!r) continue;
  295. if (r->outgoing)
  296. { (void) set_prefix(prefix, count, r);
  297. sprintf(nwnm, "%s_%s", prefix, s->name);
  298. } else
  299. strcpy(nwnm, "accept_all");
  300. addtrans(p, curnm, r->Old, nwnm);
  301. }
  302. }
  303. static void
  304. mkbuchi(void)
  305. { Graph *p;
  306. int k;
  307. char curnm[64];
  308. for (k = 0; k <= Max_Red; k++)
  309. for (p = Nodes_Set; p; p = p->nxt)
  310. { if (!p->outgoing)
  311. continue;
  312. if (k != 0
  313. && !strcmp(p->name->name, "init")
  314. && Max_Red != 0)
  315. continue;
  316. if (k == Max_Red
  317. && strcmp(p->name->name, "init") != 0)
  318. strcpy(curnm, "accept_");
  319. else
  320. sprintf(curnm, "T%d_", k);
  321. strcat(curnm, p->name->name);
  322. fsm_trans(p, k, curnm);
  323. }
  324. fsm_print();
  325. }
  326. static Symbol *
  327. dupSlist(Symbol *s)
  328. { Symbol *p1, *p2, *p3, *d = ZS;
  329. for (p1 = s; p1; p1 = p1->next)
  330. { for (p3 = d; p3; p3 = p3->next)
  331. { if (!strcmp(p3->name, p1->name))
  332. break;
  333. }
  334. if (p3) continue; /* a duplicate */
  335. p2 = getsym(p1);
  336. p2->next = d;
  337. d = p2;
  338. }
  339. return d;
  340. }
  341. static Symbol *
  342. catSlist(Symbol *a, Symbol *b)
  343. { Symbol *p1, *p2, *p3, *tmp;
  344. /* remove duplicates from b */
  345. for (p1 = a; p1; p1 = p1->next)
  346. { p3 = ZS;
  347. for (p2 = b; p2; p2 = p2->next)
  348. { if (strcmp(p1->name, p2->name))
  349. { p3 = p2;
  350. continue;
  351. }
  352. tmp = p2->next;
  353. tfree((void *) p2);
  354. if (p3)
  355. p3->next = tmp;
  356. else
  357. b = tmp;
  358. } }
  359. if (!a) return b;
  360. if (!b) return a;
  361. if (!b->next)
  362. { b->next = a;
  363. return b;
  364. }
  365. /* find end of list */
  366. for (p1 = a; p1->next; p1 = p1->next)
  367. ;
  368. p1->next = b;
  369. return a;
  370. }
  371. static void
  372. fixinit(Node *orig)
  373. { Graph *p1, *g;
  374. Symbol *q1, *q2 = ZS;
  375. ng(tl_lookup("init"), ZS, ZN, ZN, ZN);
  376. p1 = pop_stack();
  377. p1->nxt = Nodes_Set;
  378. p1->Other = p1->Old = orig;
  379. Nodes_Set = p1;
  380. for (g = Nodes_Set; g; g = g->nxt)
  381. { for (q1 = g->incoming; q1; q1 = q2)
  382. { q2 = q1->next;
  383. Addout(g->name->name, q1->name);
  384. tfree((void *) q1);
  385. }
  386. g->incoming = ZS;
  387. }
  388. }
  389. static Node *
  390. flatten(Node *p)
  391. { Node *q, *r, *z = ZN;
  392. for (q = p; q; q = q->nxt)
  393. { r = dupnode(q);
  394. if (z)
  395. z = tl_nn(AND, r, z);
  396. else
  397. z = r;
  398. }
  399. if (!z) return z;
  400. z = rewrite(z);
  401. return z;
  402. }
  403. static Node *
  404. Duplicate(Node *n)
  405. { Node *n1, *n2, *lst = ZN, *d = ZN;
  406. for (n1 = n; n1; n1 = n1->nxt)
  407. { n2 = dupnode(n1);
  408. if (lst)
  409. { lst->nxt = n2;
  410. lst = n2;
  411. } else
  412. d = lst = n2;
  413. }
  414. return d;
  415. }
  416. static void
  417. ng(Symbol *s, Symbol *in, Node *isnew, Node *isold, Node *next)
  418. { Graph *g = (Graph *) tl_emalloc(sizeof(Graph));
  419. if (s) g->name = s;
  420. else g->name = tl_lookup(newname());
  421. if (in) g->incoming = dupSlist(in);
  422. if (isnew) g->New = flatten(isnew);
  423. if (isold) g->Old = Duplicate(isold);
  424. if (next) g->Next = flatten(next);
  425. push_stack(g);
  426. }
  427. static void
  428. sdump(Node *n)
  429. {
  430. switch (n->ntyp) {
  431. case PREDICATE: strcat(dumpbuf, n->sym->name);
  432. break;
  433. case U_OPER: strcat(dumpbuf, "U");
  434. goto common2;
  435. case V_OPER: strcat(dumpbuf, "V");
  436. goto common2;
  437. case OR: strcat(dumpbuf, "|");
  438. goto common2;
  439. case AND: strcat(dumpbuf, "&");
  440. common2: sdump(n->rgt);
  441. common1: sdump(n->lft);
  442. break;
  443. #ifdef NXT
  444. case NEXT: strcat(dumpbuf, "X");
  445. goto common1;
  446. #endif
  447. case NOT: strcat(dumpbuf, "!");
  448. goto common1;
  449. case TRUE: strcat(dumpbuf, "T");
  450. break;
  451. case FALSE: strcat(dumpbuf, "F");
  452. break;
  453. default: strcat(dumpbuf, "?");
  454. break;
  455. }
  456. }
  457. Symbol *
  458. DoDump(Node *n)
  459. {
  460. if (!n) return ZS;
  461. if (n->ntyp == PREDICATE)
  462. return n->sym;
  463. dumpbuf[0] = '\0';
  464. sdump(n);
  465. return tl_lookup(dumpbuf);
  466. }
  467. static int
  468. not_new(Graph *g)
  469. { Graph *q1; Node *tmp, *n1, *n2;
  470. Mapping *map;
  471. tmp = flatten(g->Old); /* duplicate, collapse, normalize */
  472. g->Other = g->Old; /* non normalized full version */
  473. g->Old = tmp;
  474. g->oldstring = DoDump(g->Old);
  475. tmp = flatten(g->Next);
  476. g->nxtstring = DoDump(tmp);
  477. if (tl_verbose) dump_graph(g);
  478. Debug2("\tformula-old: [%s]\n", g->oldstring?g->oldstring->name:"true");
  479. Debug2("\tformula-nxt: [%s]\n", g->nxtstring?g->nxtstring->name:"true");
  480. for (q1 = Nodes_Set; q1; q1 = q1->nxt)
  481. { Debug2(" compare old to: %s", q1->name->name);
  482. Debug2(" [%s]", q1->oldstring?q1->oldstring->name:"true");
  483. Debug2(" compare nxt to: %s", q1->name->name);
  484. Debug2(" [%s]", q1->nxtstring?q1->nxtstring->name:"true");
  485. if (q1->oldstring != g->oldstring
  486. || q1->nxtstring != g->nxtstring)
  487. { Debug(" => different\n");
  488. continue;
  489. }
  490. Debug(" => match\n");
  491. if (g->incoming)
  492. q1->incoming = catSlist(g->incoming, q1->incoming);
  493. /* check if there's anything in g->Other that needs
  494. adding to q1->Other
  495. */
  496. for (n2 = g->Other; n2; n2 = n2->nxt)
  497. { for (n1 = q1->Other; n1; n1 = n1->nxt)
  498. if (isequal(n1, n2))
  499. break;
  500. if (!n1)
  501. { Node *n3 = dupnode(n2);
  502. /* don't mess up n2->nxt */
  503. n3->nxt = q1->Other;
  504. q1->Other = n3;
  505. } }
  506. map = (Mapping *) tl_emalloc(sizeof(Mapping));
  507. map->from = g->name->name;
  508. map->to = q1;
  509. map->nxt = Mapped;
  510. Mapped = map;
  511. for (n1 = g->Other; n1; n1 = n2)
  512. { n2 = n1->nxt;
  513. releasenode(1, n1);
  514. }
  515. for (n1 = g->Old; n1; n1 = n2)
  516. { n2 = n1->nxt;
  517. releasenode(1, n1);
  518. }
  519. for (n1 = g->Next; n1; n1 = n2)
  520. { n2 = n1->nxt;
  521. releasenode(1, n1);
  522. }
  523. return 1;
  524. }
  525. if (newstates) tl_verbose=1;
  526. Debug2(" New Node %s [", g->name->name);
  527. for (n1 = g->Old; n1; n1 = n1->nxt)
  528. { Dump(n1); Debug(", "); }
  529. Debug2("] nr %d\n", Base);
  530. if (newstates) tl_verbose=0;
  531. Base++;
  532. g->nxt = Nodes_Set;
  533. Nodes_Set = g;
  534. return 0;
  535. }
  536. static void
  537. expand(Graph *g)
  538. { Node *now, *n1, *n2, *nx;
  539. int can_release;
  540. extern void cache_dump(void);
  541. if (!g->New)
  542. { Debug2("\nDone with %s", g->name->name);
  543. if (tl_verbose) dump_graph(g);
  544. if (not_new(g))
  545. { if (tl_verbose) printf("\tIs Not New\n");
  546. return;
  547. }
  548. if (g->Next)
  549. { Debug(" Has Next [");
  550. for (n1 = g->Next; n1; n1 = n1->nxt)
  551. { Dump(n1); Debug(", "); }
  552. Debug("]\n");
  553. ng(ZS, getsym(g->name), g->Next, ZN, ZN);
  554. }
  555. return;
  556. }
  557. if (tl_verbose)
  558. { Symbol *z;
  559. printf("\nExpand %s, from ", g->name->name);
  560. for (z = g->incoming; z; z = z->next)
  561. printf("%s, ", z->name);
  562. printf("\n\thandle:\t"); Explain(g->New->ntyp);
  563. dump_graph(g);
  564. }
  565. if (g->New->ntyp == AND)
  566. { if (g->New->nxt)
  567. { n2 = g->New->rgt;
  568. while (n2->nxt)
  569. n2 = n2->nxt;
  570. n2->nxt = g->New->nxt;
  571. }
  572. n1 = n2 = g->New->lft;
  573. while (n2->nxt)
  574. n2 = n2->nxt;
  575. n2->nxt = g->New->rgt;
  576. releasenode(0, g->New);
  577. g->New = n1;
  578. push_stack(g);
  579. return;
  580. }
  581. can_release = 0; /* unless it need not go into Old */
  582. now = g->New;
  583. g->New = g->New->nxt;
  584. now->nxt = ZN;
  585. if (now->ntyp != TRUE
  586. #if 1
  587. /* 3.4.0 */
  588. )
  589. #else
  590. /* 3.3.9 */
  591. && now->ntyp != FALSE)
  592. #endif
  593. { if (g->Old)
  594. { for (n1 = g->Old; n1->nxt; n1 = n1->nxt)
  595. if (isequal(now, n1))
  596. { can_release = 1;
  597. goto out;
  598. }
  599. n1->nxt = now;
  600. } else
  601. g->Old = now;
  602. }
  603. out:
  604. switch (now->ntyp) {
  605. case FALSE:
  606. #if 1
  607. /* 3.4.0 */
  608. push_stack(g);
  609. #else
  610. releasenode(1, now);
  611. for (n1 = g->Old; n1; n1 = n2)
  612. { n2 = n1->nxt;
  613. releasenode(1, n1);
  614. }
  615. for (n1 = g->New; n1; n1 = n2)
  616. { n2 = n1->nxt;
  617. releasenode(1, n1);
  618. }
  619. for (n1 = g->Next; n1; n1 = n2)
  620. { n2 = n1->nxt;
  621. releasenode(1, n1);
  622. }
  623. #endif
  624. break;
  625. case TRUE:
  626. releasenode(1, now);
  627. push_stack(g);
  628. break;
  629. case PREDICATE:
  630. case NOT:
  631. if (can_release) releasenode(1, now);
  632. push_stack(g);
  633. break;
  634. case V_OPER:
  635. Assert(now->rgt->nxt == ZN, now->ntyp);
  636. Assert(now->lft->nxt == ZN, now->ntyp);
  637. n1 = now->rgt;
  638. n1->nxt = g->New;
  639. if (can_release)
  640. nx = now;
  641. else
  642. nx = getnode(now); /* now also appears in Old */
  643. nx->nxt = g->Next;
  644. n2 = now->lft;
  645. n2->nxt = getnode(now->rgt);
  646. n2->nxt->nxt = g->New;
  647. g->New = flatten(n2);
  648. push_stack(g);
  649. ng(ZS, g->incoming, n1, g->Old, nx);
  650. break;
  651. case U_OPER:
  652. Assert(now->rgt->nxt == ZN, now->ntyp);
  653. Assert(now->lft->nxt == ZN, now->ntyp);
  654. n1 = now->lft;
  655. if (can_release)
  656. nx = now;
  657. else
  658. nx = getnode(now); /* now also appears in Old */
  659. nx->nxt = g->Next;
  660. n2 = now->rgt;
  661. n2->nxt = g->New;
  662. goto common;
  663. #ifdef NXT
  664. case NEXT:
  665. nx = dupnode(now->lft);
  666. nx->nxt = g->Next;
  667. g->Next = nx;
  668. if (can_release) releasenode(0, now);
  669. push_stack(g);
  670. break;
  671. #endif
  672. case OR:
  673. Assert(now->rgt->nxt == ZN, now->ntyp);
  674. Assert(now->lft->nxt == ZN, now->ntyp);
  675. n1 = now->lft;
  676. nx = g->Next;
  677. n2 = now->rgt;
  678. n2->nxt = g->New;
  679. common:
  680. n1->nxt = g->New;
  681. ng(ZS, g->incoming, n1, g->Old, nx);
  682. g->New = flatten(n2);
  683. if (can_release) releasenode(1, now);
  684. push_stack(g);
  685. break;
  686. }
  687. }
  688. Node *
  689. twocases(Node *p)
  690. { Node *q;
  691. /* 1: ([]p1 && []p2) == [](p1 && p2) */
  692. /* 2: (<>p1 || <>p2) == <>(p1 || p2) */
  693. if (!p) return p;
  694. switch(p->ntyp) {
  695. case AND:
  696. case OR:
  697. case U_OPER:
  698. case V_OPER:
  699. p->lft = twocases(p->lft);
  700. p->rgt = twocases(p->rgt);
  701. break;
  702. #ifdef NXT
  703. case NEXT:
  704. #endif
  705. case NOT:
  706. p->lft = twocases(p->lft);
  707. break;
  708. default:
  709. break;
  710. }
  711. if (p->ntyp == AND /* 1 */
  712. && p->lft->ntyp == V_OPER
  713. && p->lft->lft->ntyp == FALSE
  714. && p->rgt->ntyp == V_OPER
  715. && p->rgt->lft->ntyp == FALSE)
  716. { q = tl_nn(V_OPER, False,
  717. tl_nn(AND, p->lft->rgt, p->rgt->rgt));
  718. } else
  719. if (p->ntyp == OR /* 2 */
  720. && p->lft->ntyp == U_OPER
  721. && p->lft->lft->ntyp == TRUE
  722. && p->rgt->ntyp == U_OPER
  723. && p->rgt->lft->ntyp == TRUE)
  724. { q = tl_nn(U_OPER, True,
  725. tl_nn(OR, p->lft->rgt, p->rgt->rgt));
  726. } else
  727. q = p;
  728. return q;
  729. }
  730. void
  731. trans(Node *p)
  732. { Node *op;
  733. Graph *g;
  734. if (!p || tl_errs) return;
  735. p = twocases(p);
  736. if (tl_verbose || tl_terse)
  737. { fprintf(tl_out, "\t/* Normlzd: ");
  738. dump(p);
  739. fprintf(tl_out, " */\n");
  740. }
  741. if (tl_terse)
  742. return;
  743. op = dupnode(p);
  744. ng(ZS, getsym(tl_lookup("init")), p, ZN, ZN);
  745. while (g = Nodes_Stack)
  746. { Nodes_Stack = g->nxt;
  747. expand(g);
  748. }
  749. if (newstates)
  750. return;
  751. fixinit(p);
  752. liveness(flatten(op)); /* was: liveness(op); */
  753. mkbuchi();
  754. if (tl_verbose)
  755. { printf("/*\n");
  756. printf(" * %d states in Streett automaton\n", Base);
  757. printf(" * %d Streett acceptance conditions\n", Max_Red);
  758. printf(" * %d Buchi states\n", Total);
  759. printf(" */\n");
  760. }
  761. }