tl_trans.c 17 KB

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