pangen7.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925
  1. /***** spin: pangen7.c *****/
  2. /* Copyright (c) 1989-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. /* pangen7.c: Version 5.3.0 2010, synchronous product of never claims */
  11. #include <stdlib.h>
  12. #include "spin.h"
  13. #include "y.tab.h"
  14. #include <assert.h>
  15. #ifdef PC
  16. extern int unlink(const char *);
  17. #else
  18. #include <unistd.h>
  19. #endif
  20. extern ProcList *rdy;
  21. extern Element *Al_El;
  22. extern int nclaims, verbose, Strict;
  23. typedef struct Succ_List Succ_List;
  24. typedef struct SQueue SQueue;
  25. typedef struct OneState OneState;
  26. typedef struct State_Stack State_Stack;
  27. typedef struct Guard Guard;
  28. struct Succ_List {
  29. SQueue *s;
  30. Succ_List *nxt;
  31. };
  32. struct OneState {
  33. int *combo; /* the combination of claim states */
  34. Succ_List *succ; /* list of ptrs to immediate successor states */
  35. };
  36. struct SQueue {
  37. OneState state;
  38. SQueue *nxt;
  39. };
  40. struct State_Stack {
  41. int *n;
  42. State_Stack *nxt;
  43. };
  44. struct Guard {
  45. Lextok *t;
  46. Guard *nxt;
  47. };
  48. SQueue *sq, *sd, *render; /* states move from sq to sd to render to holding */
  49. SQueue *holding, *lasthold;
  50. State_Stack *dsts;
  51. int nst; /* max nr of states in claims */
  52. int *Ist; /* initial states */
  53. int *Nacc; /* number of accept states in claim */
  54. int *Nst; /* next states */
  55. int **reached; /* n claims x states */
  56. int unfolding; /* to make sure all accept states are reached */
  57. int is_accept; /* remember if the current state is accepting in any claim */
  58. int not_printing; /* set during explore_product */
  59. Element ****matrix; /* n x two-dimensional arrays state x state */
  60. Element **Selfs; /* self-loop states at end of claims */
  61. static void get_seq(int, Sequence *);
  62. static void set_el(int n, Element *e);
  63. static void gen_product(void);
  64. static void print_state_nm(char *, int *, char *);
  65. static SQueue *find_state(int *);
  66. static SQueue *retrieve_state(int *);
  67. static int
  68. same_state(int *a, int *b)
  69. { int i;
  70. for (i = 0; i < nclaims; i++)
  71. { if (a[i] != b[i])
  72. { return 0;
  73. } }
  74. return 1;
  75. }
  76. static int
  77. in_stack(SQueue *s, SQueue *in)
  78. { SQueue *q;
  79. for (q = in; q; q = q->nxt)
  80. { if (same_state(q->state.combo, s->state.combo))
  81. { return 1;
  82. } }
  83. return 0;
  84. }
  85. static void
  86. to_render(SQueue *s)
  87. { SQueue *a, *q, *last; /* find in sd/sq and move to render, if not already there */
  88. int n;
  89. for (n = 0; n < nclaims; n++)
  90. { reached[n][ s->state.combo[n] ] |= 2;
  91. }
  92. for (q = render; q; q = q->nxt)
  93. { if (same_state(q->state.combo, s->state.combo))
  94. { return;
  95. } }
  96. for (q = holding; q; q = q->nxt)
  97. { if (same_state(q->state.combo, s->state.combo))
  98. { return;
  99. } }
  100. a = sd;
  101. more:
  102. for (q = a, last = 0; q; last = q, q = q->nxt)
  103. { if (same_state(q->state.combo, s->state.combo))
  104. { if (!last)
  105. { if (a == sd)
  106. { sd = q->nxt;
  107. } else if (a == sq)
  108. { sq = q->nxt;
  109. } else
  110. { holding = q->nxt;
  111. }
  112. } else
  113. { last->nxt = q->nxt;
  114. }
  115. q->nxt = render;
  116. render = q;
  117. return;
  118. } }
  119. if (verbose)
  120. { print_state_nm("looking for: ", s->state.combo, "\n");
  121. }
  122. (void) find_state(s->state.combo); /* creates it in sq */
  123. if (a != sq)
  124. { a = sq;
  125. goto more;
  126. }
  127. fatal("cannot happen, to_render", 0);
  128. }
  129. static void
  130. wrap_text(char *pre, Lextok *t, char *post)
  131. {
  132. printf(pre);
  133. comment(stdout, t, 0);
  134. printf(post);
  135. }
  136. static State_Stack *
  137. push_dsts(int *n)
  138. { State_Stack *s;
  139. int i;
  140. for (s = dsts; s; s = s->nxt)
  141. { if (same_state(s->n, n))
  142. { if (verbose&64)
  143. { printf("\n");
  144. for (s = dsts; s; s = s->nxt)
  145. { print_state_nm("\t", s->n, "\n");
  146. }
  147. print_state_nm("\t", n, "\n");
  148. }
  149. return s;
  150. } }
  151. s = (State_Stack *) emalloc(sizeof(State_Stack));
  152. s->n = (int *) emalloc(nclaims * sizeof(int));
  153. for (i = 0; i < nclaims; i++)
  154. s->n[i] = n[i];
  155. s->nxt = dsts;
  156. dsts = s;
  157. return 0;
  158. }
  159. static void
  160. pop_dsts(void)
  161. {
  162. assert(dsts);
  163. dsts = dsts->nxt;
  164. }
  165. static void
  166. complete_transition(Succ_List *sl, Guard *g)
  167. { Guard *w;
  168. int cnt = 0;
  169. printf(" :: ");
  170. for (w = g; w; w = w->nxt)
  171. { if (w->t->ntyp == CONST
  172. && w->t->val == 1)
  173. { continue;
  174. } else if (w->t->ntyp == 'c'
  175. && w->t->lft->ntyp == CONST
  176. && w->t->lft->val == 1)
  177. { continue; /* 'true' */
  178. }
  179. if (cnt > 0)
  180. { printf(" && ");
  181. }
  182. wrap_text("", w->t, "");
  183. cnt++;
  184. }
  185. if (cnt == 0)
  186. { printf("true");
  187. }
  188. print_state_nm(" -> goto ", sl->s->state.combo, "");
  189. if (is_accept > 0)
  190. { printf("_U%d\n", (unfolding+1)%nclaims);
  191. } else
  192. { printf("_U%d\n", unfolding);
  193. }
  194. }
  195. static void
  196. state_body(OneState *s, Guard *guard)
  197. { Succ_List *sl;
  198. State_Stack *y;
  199. Guard *g;
  200. int i, once;
  201. for (sl = s->succ; sl; sl = sl->nxt)
  202. { once = 0;
  203. for (i = 0; i < nclaims; i++)
  204. { Element *e;
  205. e = matrix[i][s->combo[i]][sl->s->state.combo[i]];
  206. /* if one of the claims has a DO or IF move
  207. then pull its target state forward, once
  208. */
  209. if (!e
  210. || e->n->ntyp == NON_ATOMIC
  211. || e->n->ntyp == DO
  212. || e->n->ntyp == IF)
  213. { s = &(sl->s->state);
  214. y = push_dsts(s->combo);
  215. if (!y)
  216. { if (once++ == 0)
  217. { assert(s->succ);
  218. state_body(s, guard);
  219. }
  220. pop_dsts();
  221. } else if (!y->nxt) /* self-loop transition */
  222. { if (!not_printing) printf(" /* self-loop */\n");
  223. } else
  224. { /* non_fatal("loop in state body", 0); ** maybe ok */
  225. }
  226. continue;
  227. } else
  228. { g = (Guard *) emalloc(sizeof(Guard));
  229. g->t = e->n;
  230. g->nxt = guard;
  231. guard = g;
  232. } }
  233. if (guard && !once)
  234. { if (!not_printing) complete_transition(sl, guard);
  235. to_render(sl->s);
  236. } }
  237. }
  238. static struct X {
  239. char *s; int n;
  240. } spl[] = {
  241. {"end", 3 },
  242. {"accept", 6 },
  243. {0, 0 },
  244. };
  245. static int slcnt;
  246. extern Label *labtab;
  247. static ProcList *
  248. locate_claim(int n)
  249. { ProcList *p;
  250. int i;
  251. for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
  252. { if (i == n)
  253. { break;
  254. } }
  255. assert(p && p->b == N_CLAIM);
  256. return p;
  257. }
  258. static void
  259. elim_lab(Element *e)
  260. { Label *l, *lst;
  261. for (l = labtab, lst = NULL; l; lst = l, l = l->nxt)
  262. { if (l->e == e)
  263. { if (lst)
  264. { lst->nxt = l->nxt;
  265. } else
  266. { labtab = l->nxt;
  267. }
  268. break;
  269. } }
  270. }
  271. static int
  272. claim_has_accept(ProcList *p)
  273. { Label *l;
  274. for (l = labtab; l; l = l->nxt)
  275. { if (strcmp(l->c->name, p->n->name) == 0
  276. && strncmp(l->s->name, "accept", 6) == 0)
  277. { return 1;
  278. } }
  279. return 0;
  280. }
  281. static void
  282. prune_accept(void)
  283. { int n;
  284. for (n = 0; n < nclaims; n++)
  285. { if ((reached[n][Selfs[n]->seqno] & 2) == 0)
  286. { if (verbose)
  287. { printf("claim %d: selfloop not reachable\n", n);
  288. }
  289. elim_lab(Selfs[n]);
  290. Nacc[n] = claim_has_accept(locate_claim(n));
  291. } }
  292. }
  293. static void
  294. mk_accepting(int n, Element *e)
  295. { ProcList *p;
  296. Label *l;
  297. int i;
  298. assert(!Selfs[n]);
  299. Selfs[n] = e;
  300. l = (Label *) emalloc(sizeof(Label));
  301. l->s = (Symbol *) emalloc(sizeof(Symbol));
  302. l->s->name = "accept00";
  303. l->c = (Symbol *) emalloc(sizeof(Symbol));
  304. l->uiid = 0; /* this is not in an inline */
  305. for (p = rdy, i = 0; p; p = p->nxt, i++) /* find claim name */
  306. { if (i == n)
  307. { l->c->name = p->n->name;
  308. break;
  309. } }
  310. assert(p && p->b == N_CLAIM);
  311. Nacc[n] = 1;
  312. l->e = e;
  313. l->nxt = labtab;
  314. labtab = l;
  315. }
  316. static void
  317. check_special(int *nrs)
  318. { ProcList *p;
  319. Label *l;
  320. int i, j, nmatches;
  321. int any_accepts = 0;
  322. for (i = 0; i < nclaims; i++)
  323. { any_accepts += Nacc[i];
  324. }
  325. is_accept = 0;
  326. for (j = 0; spl[j].n; j++) /* 2 special label prefixes */
  327. { nmatches = 0;
  328. for (p = rdy, i = 0; p; p = p->nxt, i++) /* check each claim */
  329. { if (p->b != N_CLAIM)
  330. { continue;
  331. }
  332. /* claim i in state nrs[i], type p->tn, name p->n->name
  333. * either the state has an accept label, or the claim has none,
  334. * so that all its states should be considered accepting
  335. * --- but only if other claims do have accept states!
  336. */
  337. if (Strict == 0 && j == 1 && Nacc[i] == 0 && any_accepts > 0)
  338. { if ((verbose&32) && i == unfolding)
  339. { printf(" /* claim %d pseudo-accept */\n", i);
  340. }
  341. goto is_accepting;
  342. }
  343. for (l = labtab; l; l = l->nxt) /* check its labels */
  344. { if (strcmp(l->c->name, p->n->name) == 0 /* right claim */
  345. && l->e->seqno == nrs[i] /* right state */
  346. && strncmp(l->s->name, spl[j].s, spl[j].n) == 0)
  347. { if (j == 1) /* accept state */
  348. { char buf[32];
  349. is_accepting: if (strchr(p->n->name, ':'))
  350. { sprintf(buf, "N%d", i);
  351. } else
  352. { strcpy(buf, p->n->name);
  353. }
  354. if (unfolding == 0 && i == 0)
  355. { if (!not_printing)
  356. printf("%s_%s_%d:\n", /* true accept */
  357. spl[j].s, buf, slcnt++);
  358. } else if (verbose&32)
  359. { if (!not_printing)
  360. printf("%s_%s%d:\n",
  361. buf, spl[j].s, slcnt++);
  362. }
  363. if (i == unfolding)
  364. { is_accept++; /* move to next unfolding */
  365. }
  366. } else
  367. { nmatches++;
  368. }
  369. break;
  370. } } }
  371. if (j == 0 && nmatches == nclaims) /* end-state */
  372. { if (!not_printing)
  373. { printf("%s%d:\n", spl[j].s, slcnt++);
  374. } } }
  375. }
  376. static int
  377. render_state(SQueue *q)
  378. {
  379. if (!q || !q->state.succ)
  380. { if (verbose&64)
  381. { printf(" no exit\n");
  382. }
  383. return 0;
  384. }
  385. check_special(q->state.combo); /* accept or end-state labels */
  386. dsts = (State_Stack *) 0;
  387. push_dsts(q->state.combo); /* to detect loops */
  388. if (!not_printing)
  389. { print_state_nm("", q->state.combo, ""); /* the name */
  390. printf("_U%d:\n\tdo\n", unfolding);
  391. }
  392. state_body(&(q->state), (Guard *) 0);
  393. if (!not_printing)
  394. { printf("\tod;\n");
  395. }
  396. pop_dsts();
  397. return 1;
  398. }
  399. static void
  400. explore_product(void)
  401. { SQueue *q;
  402. /* all states are in the sd queue */
  403. q = retrieve_state(Ist); /* retrieve from the sd q */
  404. q->nxt = render; /* put in render q */
  405. render = q;
  406. do {
  407. q = render;
  408. render = render->nxt;
  409. q->nxt = 0; /* remove from render q */
  410. if (verbose&64)
  411. { print_state_nm("explore: ", q->state.combo, "\n");
  412. }
  413. not_printing = 1;
  414. render_state(q); /* may add new states */
  415. not_printing = 0;
  416. if (lasthold)
  417. { lasthold->nxt = q;
  418. lasthold = q;
  419. } else
  420. { holding = lasthold = q;
  421. }
  422. } while (render);
  423. assert(!dsts);
  424. }
  425. static void
  426. print_product(void)
  427. { SQueue *q;
  428. int cnt;
  429. if (unfolding == 0)
  430. { printf("never Product {\n"); /* name expected by iSpin */
  431. q = find_state(Ist); /* should find it in the holding q */
  432. assert(q);
  433. q->nxt = holding; /* put it at the front */
  434. holding = q;
  435. }
  436. render = holding;
  437. holding = lasthold = 0;
  438. printf("/* ============= U%d ============= */\n", unfolding);
  439. cnt = 0;
  440. do {
  441. q = render;
  442. render = render->nxt;
  443. q->nxt = 0;
  444. if (verbose&64)
  445. { print_state_nm("print: ", q->state.combo, "\n");
  446. }
  447. cnt += render_state(q);
  448. if (lasthold)
  449. { lasthold->nxt = q;
  450. lasthold = q;
  451. } else
  452. { holding = lasthold = q;
  453. }
  454. } while (render);
  455. assert(!dsts);
  456. if (cnt == 0)
  457. { printf(" 0;\n");
  458. }
  459. if (unfolding == nclaims-1)
  460. { printf("}\n");
  461. }
  462. }
  463. static void
  464. prune_dead(void)
  465. { Succ_List *sl, *last;
  466. SQueue *q;
  467. int cnt;
  468. do { cnt = 0;
  469. for (q = sd; q; q = q->nxt)
  470. { /* if successor is deadend, remove it
  471. * unless it's a move to the end-state of the claim
  472. */
  473. last = (Succ_List *) 0;
  474. for (sl = q->state.succ; sl; last = sl, sl = sl->nxt)
  475. { if (!sl->s->state.succ) /* no successor */
  476. { if (!last)
  477. { q->state.succ = sl->nxt;
  478. } else
  479. { last->nxt = sl->nxt;
  480. }
  481. cnt++;
  482. } } }
  483. } while (cnt > 0);
  484. }
  485. static void
  486. print_raw(void)
  487. { int i, j, n;
  488. printf("#if 0\n");
  489. for (n = 0; n < nclaims; n++)
  490. { printf("C%d:\n", n);
  491. for (i = 0; i < nst; i++)
  492. { if (reached[n][i])
  493. for (j = 0; j < nst; j++)
  494. { if (matrix[n][i][j])
  495. { if (reached[n][i] & 2) printf("+");
  496. if (i == Ist[n]) printf("*");
  497. printf("\t%d", i);
  498. wrap_text(" -[", matrix[n][i][j]->n, "]->\t");
  499. printf("%d\n", j);
  500. } } } }
  501. printf("#endif\n\n");
  502. fflush(stdout);
  503. }
  504. void
  505. sync_product(void)
  506. { ProcList *p;
  507. Element *e;
  508. int n, i;
  509. if (nclaims <= 1) return;
  510. (void) unlink("pan.pre");
  511. Ist = (int *) emalloc(sizeof(int) * nclaims);
  512. Nacc = (int *) emalloc(sizeof(int) * nclaims);
  513. Nst = (int *) emalloc(sizeof(int) * nclaims);
  514. reached = (int **) emalloc(sizeof(int *) * nclaims);
  515. Selfs = (Element **) emalloc(sizeof(Element *) * nclaims);
  516. matrix = (Element ****) emalloc(sizeof(Element ***) * nclaims); /* claims */
  517. for (p = rdy, i = 0; p; p = p->nxt, i++)
  518. { if (p->b == N_CLAIM)
  519. { nst = max(p->s->maxel, nst);
  520. Nacc[i] = claim_has_accept(p);
  521. } }
  522. for (n = 0; n < nclaims; n++)
  523. { reached[n] = (int *) emalloc(sizeof(int) * nst);
  524. matrix[n] = (Element ***) emalloc(sizeof(Element **) * nst); /* rows */
  525. for (i = 0; i < nst; i++) /* cols */
  526. { matrix[n][i] = (Element **) emalloc(sizeof(Element *) * nst);
  527. } }
  528. for (e = Al_El; e; e = e->Nxt)
  529. { e->status &= ~DONE;
  530. }
  531. for (p = rdy, n=0; p; p = p->nxt, n++)
  532. { if (p->b == N_CLAIM)
  533. { /* fill in matrix[n] */
  534. e = p->s->frst;
  535. Ist[n] = huntele(e, e->status, -1)->seqno;
  536. reached[n][Ist[n]] = 1|2;
  537. get_seq(n, p->s);
  538. } }
  539. if (verbose) /* show only the input automata */
  540. { print_raw();
  541. }
  542. gen_product(); /* create product automaton */
  543. }
  544. static int
  545. nxt_trans(int n, int cs, int frst)
  546. { int j;
  547. for (j = frst; j < nst; j++)
  548. { if (reached[n][cs]
  549. && matrix[n][cs][j])
  550. { return j;
  551. } }
  552. return -1;
  553. }
  554. static void
  555. print_state_nm(char *p, int *s, char *a)
  556. { int i;
  557. printf("%sP", p);
  558. for (i = 0; i < nclaims; i++)
  559. { printf("_%d", s[i]);
  560. }
  561. printf("%s", a);
  562. }
  563. static void
  564. create_transition(OneState *s, SQueue *it)
  565. { int n, from, upto;
  566. int *F = s->combo;
  567. int *T = it->state.combo;
  568. Succ_List *sl;
  569. Lextok *t;
  570. if (verbose&64)
  571. { print_state_nm("", F, " ");
  572. print_state_nm("-> ", T, "\t");
  573. }
  574. /* check if any of the claims is blocked */
  575. /* which makes the state a dead-end */
  576. for (n = 0; n < nclaims; n++)
  577. { from = F[n];
  578. upto = T[n];
  579. t = matrix[n][from][upto]->n;
  580. if (verbose&64)
  581. { wrap_text("", t, " ");
  582. }
  583. if (t->ntyp == 'c'
  584. && t->lft->ntyp == CONST)
  585. { if (t->lft->val == 0) /* i.e., false */
  586. { goto done;
  587. } } }
  588. sl = (Succ_List *) emalloc(sizeof(Succ_List));
  589. sl->s = it;
  590. sl->nxt = s->succ;
  591. s->succ = sl;
  592. done:
  593. if (verbose&64)
  594. { printf("\n");
  595. }
  596. }
  597. static SQueue *
  598. find_state(int *cs)
  599. { SQueue *nq, *a = sq;
  600. int i;
  601. again: /* check in nq, sq, and then in the render q */
  602. for (nq = a; nq; nq = nq->nxt)
  603. { if (same_state(nq->state.combo, cs))
  604. { return nq; /* found */
  605. } }
  606. if (a == sq && sd)
  607. { a = sd;
  608. goto again; /* check the other stack too */
  609. } else if (a == sd && render)
  610. { a = render;
  611. goto again;
  612. }
  613. nq = (SQueue *) emalloc(sizeof(SQueue));
  614. nq->state.combo = (int *) emalloc(nclaims * sizeof(int));
  615. for (i = 0; i < nclaims; i++)
  616. { nq->state.combo[i] = cs[i];
  617. }
  618. nq->nxt = sq; /* add to sq stack */
  619. sq = nq;
  620. return nq;
  621. }
  622. static SQueue *
  623. retrieve_state(int *s)
  624. { SQueue *nq, *last = NULL;
  625. for (nq = sd; nq; last = nq, nq = nq->nxt)
  626. { if (same_state(nq->state.combo, s))
  627. { if (last)
  628. { last->nxt = nq->nxt;
  629. } else
  630. { sd = nq;
  631. }
  632. return nq; /* found */
  633. } }
  634. fatal("cannot happen: retrieve_state", 0);
  635. return (SQueue *) 0;
  636. }
  637. static void
  638. all_successors(int n, OneState *cur)
  639. { int i, j = 0;
  640. if (n >= nclaims)
  641. { create_transition(cur, find_state(Nst));
  642. } else
  643. { i = cur->combo[n];
  644. for (;;)
  645. { j = nxt_trans(n, i, j);
  646. if (j < 0) break;
  647. Nst[n] = j;
  648. all_successors(n+1, cur);
  649. j++;
  650. } }
  651. }
  652. static void
  653. gen_product(void)
  654. { OneState *cur_st;
  655. SQueue *q;
  656. find_state(Ist); /* create initial state */
  657. while (sq)
  658. { if (in_stack(sq, sd))
  659. { sq = sq->nxt;
  660. continue;
  661. }
  662. cur_st = &(sq->state);
  663. q = sq;
  664. sq = sq->nxt; /* delete from sq stack */
  665. q->nxt = sd; /* and move to done stack */
  666. sd = q;
  667. all_successors(0, cur_st);
  668. }
  669. /* all states are in the sd queue now */
  670. prune_dead();
  671. explore_product(); /* check if added accept-self-loops are reachable */
  672. prune_accept();
  673. if (verbose)
  674. { print_raw();
  675. }
  676. /* PM: merge states with identical successor lists */
  677. /* all outgoing transitions from accept-states
  678. from claim n in copy n connect to states in copy (n+1)%nclaims
  679. only accept states from claim 0 in copy 0 are true accept states
  680. in the product
  681. PM: what about claims that have no accept states (e.g., restrictions)
  682. */
  683. for (unfolding = 0; unfolding < nclaims; unfolding++)
  684. { print_product();
  685. }
  686. }
  687. static void
  688. t_record(int n, Element *e, Element *g)
  689. { int from = e->seqno, upto = g?g->seqno:0;
  690. assert(from >= 0 && from < nst);
  691. assert(upto >= 0 && upto < nst);
  692. matrix[n][from][upto] = e;
  693. reached[n][upto] |= 1;
  694. }
  695. static void
  696. get_sub(int n, Element *e)
  697. {
  698. if (e->n->ntyp == D_STEP
  699. || e->n->ntyp == ATOMIC)
  700. { fatal("atomic or d_step in never claim product", 0);
  701. }
  702. /* NON_ATOMIC */
  703. e->n->sl->this->last->nxt = e->nxt;
  704. get_seq(n, e->n->sl->this);
  705. t_record(n, e, e->n->sl->this->frst);
  706. }
  707. static void
  708. set_el(int n, Element *e)
  709. { Element *g;
  710. if (e->n->ntyp == '@') /* change to self-loop */
  711. { e->n->ntyp = CONST;
  712. e->n->val = 1; /* true */
  713. e->nxt = e;
  714. g = e;
  715. mk_accepting(n, e);
  716. } else
  717. if (e->n->ntyp == GOTO)
  718. { g = get_lab(e->n, 1);
  719. g = huntele(g, e->status, -1);
  720. } else if (e->nxt)
  721. { g = huntele(e->nxt, e->status, -1);
  722. } else
  723. { g = NULL;
  724. }
  725. t_record(n, e, g);
  726. }
  727. static void
  728. get_seq(int n, Sequence *s)
  729. { SeqList *h;
  730. Element *e;
  731. e = huntele(s->frst, s->frst->status, -1);
  732. for ( ; e; e = e->nxt)
  733. { if (e->status & DONE)
  734. { goto checklast;
  735. }
  736. e->status |= DONE;
  737. if (e->n->ntyp == UNLESS)
  738. { fatal("unless stmnt in never claim product", 0);
  739. }
  740. if (e->sub) /* IF or DO */
  741. { Lextok *x = NULL;
  742. Lextok *y = NULL;
  743. Lextok *haselse = NULL;
  744. for (h = e->sub; h; h = h->nxt)
  745. { Lextok *t = h->this->frst->n;
  746. if (t->ntyp == ELSE)
  747. { if (verbose&64) printf("else at line %d\n", t->ln);
  748. haselse = t;
  749. continue;
  750. }
  751. if (t->ntyp != 'c')
  752. { fatal("product, 'else' combined with non-condition", 0);
  753. }
  754. if (t->lft->ntyp == CONST /* true */
  755. && t->lft->val == 1
  756. && y == NULL)
  757. { y = nn(ZN, CONST, ZN, ZN);
  758. y->val = 0;
  759. } else
  760. { if (!x)
  761. x = t;
  762. else
  763. x = nn(ZN, OR, x, t);
  764. if (verbose&64)
  765. { wrap_text(" [", x, "]\n");
  766. } } }
  767. if (haselse)
  768. { if (!y)
  769. { y = nn(ZN, '!', x, ZN);
  770. }
  771. if (verbose&64)
  772. { wrap_text(" [else: ", y, "]\n");
  773. }
  774. haselse->ntyp = 'c'; /* replace else */
  775. haselse->lft = y;
  776. }
  777. for (h = e->sub; h; h = h->nxt)
  778. { t_record(n, e, h->this->frst);
  779. get_seq(n, h->this);
  780. }
  781. } else
  782. { if (e->n->ntyp == ATOMIC
  783. || e->n->ntyp == D_STEP
  784. || e->n->ntyp == NON_ATOMIC)
  785. { get_sub(n, e);
  786. } else
  787. { set_el(n, e);
  788. }
  789. }
  790. checklast: if (e == s->last)
  791. break;
  792. }
  793. }