tl_trans.c 17 KB

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