pangen5.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  1. /***** spin: pangen5.c *****/
  2. /* Copyright (c) 1999-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. */
  8. #include "spin.h"
  9. #include "version.h"
  10. #ifdef PC
  11. #include "y_tab.h"
  12. #else
  13. #include "y.tab.h"
  14. #endif
  15. typedef struct BuildStack {
  16. FSM_trans *t;
  17. struct BuildStack *nxt;
  18. } BuildStack;
  19. extern ProcList *rdy;
  20. extern int verbose, eventmapnr, claimnr, rvopt, xspin;
  21. extern Element *Al_El;
  22. static FSM_state *fsm;
  23. static FSM_state *fsm_free;
  24. static FSM_trans *trans_free;
  25. static FSM_use *use_free;
  26. static BuildStack *bs, *bf;
  27. static FSM_state **fsm_tbl;
  28. static int max_st_id;
  29. static int cur_st_id;
  30. static int o_max;
  31. static void ana_seq(Sequence *);
  32. static void ana_stmnt(FSM_trans *, Lextok *, int);
  33. extern int has_global(Lextok *);
  34. void
  35. fsm_table(void)
  36. { FSM_state *f;
  37. max_st_id += 2;
  38. /* fprintf(stderr, "omax %d, max=%d\n", o_max, max_st_id); */
  39. if (o_max < max_st_id)
  40. { o_max = max_st_id;
  41. fsm_tbl = (FSM_state **) emalloc(max_st_id * sizeof(FSM_state *));
  42. } else
  43. memset((char *)fsm_tbl, 0, max_st_id * sizeof(FSM_state *));
  44. cur_st_id = max_st_id;
  45. max_st_id = 0;
  46. for (f = fsm; f; f = f->nxt)
  47. fsm_tbl[f->from] = f;
  48. }
  49. static int
  50. FSM_DFS(int from, FSM_use *u)
  51. { FSM_state *f;
  52. FSM_trans *t;
  53. FSM_use *v;
  54. int n;
  55. if (from == 0)
  56. return 1;
  57. f = fsm_tbl[from];
  58. if (!f)
  59. { printf("cannot find state %d\n", from);
  60. fatal("fsm_dfs: cannot happen\n", (char *) 0);
  61. }
  62. if (f->seen)
  63. return 1;
  64. f->seen = 1;
  65. for (t = f->t; t; t = t->nxt)
  66. {
  67. for (n = 0; n < 2; n++)
  68. for (v = t->Val[n]; v; v = v->nxt)
  69. if (u->var == v->var)
  70. return n; /* a read or write */
  71. if (!FSM_DFS(t->to, u))
  72. return 0;
  73. }
  74. return 1;
  75. }
  76. static void
  77. new_dfs(void)
  78. { int i;
  79. for (i = 0; i < cur_st_id; i++)
  80. if (fsm_tbl[i])
  81. fsm_tbl[i]->seen = 0;
  82. }
  83. static int
  84. good_dead(Element *e, FSM_use *u)
  85. {
  86. switch (u->special) {
  87. case 2: /* ok if it's a receive */
  88. if (e->n->ntyp == ASGN
  89. && e->n->rgt->ntyp == CONST
  90. && e->n->rgt->val == 0)
  91. return 0;
  92. break;
  93. case 1: /* must be able to use oval */
  94. if (e->n->ntyp != 'c'
  95. && e->n->ntyp != 'r')
  96. return 0; /* can't really happen */
  97. break;
  98. }
  99. return 1;
  100. }
  101. #if 0
  102. static int
  103. badjump(Element *e)
  104. { Element *g;
  105. /* e->n->ntyp == GOTO */
  106. g = get_lab(e->n, 1);
  107. g = huntele(g, e->status);
  108. if (g && g->n)
  109. { switch (g->n->ntyp) {
  110. case ATOMIC:
  111. case NON_ATOMIC:
  112. case D_STEP:
  113. case IF:
  114. case DO:
  115. case UNLESS:
  116. case ELSE:
  117. return 1;
  118. } }
  119. return 0;
  120. }
  121. #endif
  122. static int howdeep = 0;
  123. static int
  124. eligible(FSM_trans *v)
  125. { Element *el = ZE;
  126. Lextok *lt = ZN;
  127. if (v) el = v->step;
  128. if (el) lt = v->step->n;
  129. if (!lt /* dead end */
  130. || v->nxt /* has alternatives */
  131. || el->esc /* has an escape */
  132. || (el->status&CHECK2) /* remotely referenced */
  133. || lt->ntyp == ATOMIC
  134. || lt->ntyp == NON_ATOMIC /* used for inlines -- should be able to handle this */
  135. #if 1
  136. || lt->ntyp == IF
  137. #endif
  138. || has_lab(el, 0) /* any label at all */
  139. || lt->ntyp == DO
  140. || lt->ntyp == UNLESS
  141. || lt->ntyp == D_STEP
  142. || lt->ntyp == ELSE
  143. || lt->ntyp == '@'
  144. || lt->ntyp == 'c'
  145. || lt->ntyp == 'r'
  146. || lt->ntyp == 's')
  147. return 0;
  148. #if 0
  149. if (lt && lt->ntyp == GOTO && badjump(el))
  150. return 0;
  151. #endif
  152. if (!(el->status&(2|4))) /* not atomic */
  153. { int unsafe = (el->status&I_GLOB)?1:has_global(el->n);
  154. if (unsafe)
  155. return 0;
  156. }
  157. #if 0
  158. if (lt->ntyp == IF)
  159. { SeqList *h;
  160. Element *g;
  161. int cnt=0, has_else=0;
  162. /* is it clearly deterministic? */
  163. for (h = v->step->sub; h; h = h->nxt, cnt++)
  164. { g = huntstart(h->this->frst);
  165. if (!g || g->esc || !g->n)
  166. return 0;
  167. switch (g->n->ntyp) {
  168. case ELSE:
  169. has_else=1;
  170. /* fall through */
  171. case 'c':
  172. break;
  173. default:
  174. return 0;
  175. }
  176. }
  177. if (cnt != 2 || !has_else)
  178. return 0;
  179. /* should also be no GOTO, BREAK, or ineligible stmnts in either sequence */
  180. printf("spin: %s:%d: may have handled if\n",
  181. lt->fn?lt->fn->name:"", lt->ln);
  182. return 0;
  183. }
  184. #endif
  185. return 1;
  186. }
  187. static int
  188. canfill_in(FSM_trans *v)
  189. { Element *el = v->step;
  190. Lextok *lt = v->step->n;
  191. if (!lt /* dead end */
  192. || v->nxt /* has alternatives */
  193. || el->esc /* has an escape */
  194. || (el->status&CHECK2)) /* remotely referenced */
  195. return 0;
  196. if (!(el->status&(2|4)) /* not atomic */
  197. && ((el->status&I_GLOB)
  198. || has_global(el->n))) /* and not safe */
  199. return 0;
  200. return 1;
  201. }
  202. static int
  203. pushbuild(FSM_trans *v)
  204. { BuildStack *b;
  205. for (b = bs; b; b = b->nxt)
  206. if (b->t == v)
  207. return 0;
  208. if (bf)
  209. { b = bf;
  210. bf = bf->nxt;
  211. } else
  212. b = (BuildStack *) emalloc(sizeof(BuildStack));
  213. b->t = v;
  214. b->nxt = bs;
  215. bs = b;
  216. return 1;
  217. }
  218. static void
  219. popbuild(void)
  220. { BuildStack *f;
  221. if (!bs)
  222. fatal("cannot happen, popbuild", (char *) 0);
  223. f = bs;
  224. bs = bs->nxt;
  225. f->nxt = bf;
  226. bf = f; /* freelist */
  227. }
  228. static int
  229. build_step(FSM_trans *v)
  230. { FSM_state *f;
  231. Element *el = v->step;
  232. Lextok *lt = ZN;
  233. int st = v->to;
  234. int r;
  235. if (!el) return -1;
  236. lt = v->step->n;
  237. if (v->step->merge)
  238. return v->step->merge; /* already done */
  239. if (!eligible(v)) /* non-blocking */
  240. return -1;
  241. if (!pushbuild(v)) /* cycle detected */
  242. return -1; /* break cycle */
  243. f = fsm_tbl[st];
  244. #if 0
  245. if (verbose&32)
  246. { if (++howdeep == 1)
  247. printf("spin: %s, line %3d, merge:\n",
  248. lt->fn->name,
  249. lt->ln);
  250. printf("\t[%d] <seqno %d>\t", howdeep, el->seqno);
  251. comment(stdout, lt, 0);
  252. printf(";\n");
  253. }
  254. #endif
  255. r = build_step(f->t);
  256. v->step->merge = (r == -1) ? st : r;
  257. #if 0
  258. if (verbose&32)
  259. howdeep--;
  260. #endif
  261. popbuild();
  262. return v->step->merge;
  263. }
  264. static void
  265. FSM_MERGER(char *pname) /* find candidates for safely merging steps */
  266. { FSM_state *f, *g;
  267. FSM_trans *t;
  268. Lextok *lt;
  269. for (f = fsm; f; f = f->nxt) /* all states */
  270. for (t = f->t; t; t = t->nxt) /* all edges */
  271. { if (!t->step) continue; /* happens with 'unless' */
  272. t->step->merge_in = f->in; /* ?? */
  273. if (t->step->merge)
  274. continue;
  275. lt = t->step->n;
  276. if (lt->ntyp == 'c'
  277. || lt->ntyp == 'r'
  278. || lt->ntyp == 's') /* blocking stmnts */
  279. continue; /* handled in 2nd scan */
  280. if (!eligible(t))
  281. continue;
  282. g = fsm_tbl[t->to];
  283. if (!eligible(g->t))
  284. {
  285. #define SINGLES
  286. #ifdef SINGLES
  287. t->step->merge_single = t->to;
  288. #if 0
  289. if ((verbose&32))
  290. { printf("spin: %s, line %3d, merge_single:\n\t<seqno %d>\t",
  291. t->step->n->fn->name,
  292. t->step->n->ln,
  293. t->step->seqno);
  294. comment(stdout, t->step->n, 0);
  295. printf(";\n");
  296. }
  297. #endif
  298. #endif
  299. /* t is an isolated eligible step:
  300. *
  301. * a merge_start can connect to a proper
  302. * merge chain or to a merge_single
  303. * a merge chain can be preceded by
  304. * a merge_start, but not by a merge_single
  305. */
  306. continue;
  307. }
  308. (void) build_step(t);
  309. }
  310. /* 2nd scan -- find possible merge_starts */
  311. for (f = fsm; f; f = f->nxt) /* all states */
  312. for (t = f->t; t; t = t->nxt) /* all edges */
  313. { if (!t->step || t->step->merge)
  314. continue;
  315. lt = t->step->n;
  316. if (lt->ntyp == 'c'
  317. || lt->ntyp == 'r'
  318. || lt->ntyp == 's') /* blocking stmnts */
  319. { if (!canfill_in(t))
  320. continue;
  321. g = fsm_tbl[t->to];
  322. if (!g || !g->t || !g->t->step)
  323. continue;
  324. if (g->t->step->merge)
  325. t->step->merge_start = g->t->step->merge;
  326. #ifdef SINGLES
  327. else if (g->t->step->merge_single)
  328. t->step->merge_start = g->t->step->merge_single;
  329. #endif
  330. #if 0
  331. if ((verbose&32)
  332. && t->step->merge_start)
  333. { printf("spin: %s, line %3d, merge_START:\n\t<seqno %d>\t",
  334. lt->fn->name,
  335. lt->ln,
  336. t->step->seqno);
  337. comment(stdout, lt, 0);
  338. printf(";\n");
  339. }
  340. #endif
  341. }
  342. }
  343. }
  344. static void
  345. FSM_ANA(void)
  346. { FSM_state *f;
  347. FSM_trans *t;
  348. FSM_use *u, *v, *w;
  349. int n;
  350. for (f = fsm; f; f = f->nxt) /* all states */
  351. for (t = f->t; t; t = t->nxt) /* all edges */
  352. for (n = 0; n < 2; n++) /* reads and writes */
  353. for (u = t->Val[n]; u; u = u->nxt)
  354. { if (!u->var->context /* global */
  355. || u->var->type == CHAN
  356. || u->var->type == STRUCT)
  357. continue;
  358. new_dfs();
  359. if (FSM_DFS(t->to, u)) /* cannot hit read before hitting write */
  360. u->special = n+1; /* means, reset to 0 after use */
  361. }
  362. for (f = fsm; f; f = f->nxt)
  363. for (t = f->t; t; t = t->nxt)
  364. for (n = 0; n < 2; n++)
  365. for (u = t->Val[n], w = (FSM_use *) 0; u; )
  366. { if (u->special)
  367. { v = u->nxt;
  368. if (!w) /* remove from list */
  369. t->Val[n] = v;
  370. else
  371. w->nxt = v;
  372. #if 0
  373. if (verbose&32)
  374. { printf("%s : %3d: %d -> %d \t",
  375. t->step->n->fn->name,
  376. t->step->n->ln,
  377. f->from,
  378. t->to);
  379. comment(stdout, t->step->n, 0);
  380. printf("\t%c%d: %s\n", n==0?'R':'L',
  381. u->special, u->var->name);
  382. }
  383. #endif
  384. if (good_dead(t->step, u))
  385. { u->nxt = t->step->dead; /* insert into dead */
  386. t->step->dead = u;
  387. }
  388. u = v;
  389. } else
  390. { w = u;
  391. u = u->nxt;
  392. } }
  393. }
  394. static void
  395. rel_use(FSM_use *u)
  396. {
  397. if (!u) return;
  398. rel_use(u->nxt);
  399. u->var = (Symbol *) 0;
  400. u->special = 0;
  401. u->nxt = use_free;
  402. use_free = u;
  403. }
  404. static void
  405. rel_trans(FSM_trans *t)
  406. {
  407. if (!t) return;
  408. rel_trans(t->nxt);
  409. rel_use(t->Val[0]);
  410. rel_use(t->Val[1]);
  411. t->Val[0] = t->Val[1] = (FSM_use *) 0;
  412. t->nxt = trans_free;
  413. trans_free = t;
  414. }
  415. static void
  416. rel_state(FSM_state *f)
  417. {
  418. if (!f) return;
  419. rel_state(f->nxt);
  420. rel_trans(f->t);
  421. f->t = (FSM_trans *) 0;
  422. f->nxt = fsm_free;
  423. fsm_free = f;
  424. }
  425. static void
  426. FSM_DEL(void)
  427. {
  428. rel_state(fsm);
  429. fsm = (FSM_state *) 0;
  430. }
  431. static FSM_state *
  432. mkstate(int s)
  433. { FSM_state *f;
  434. /* fsm_tbl isn't allocated yet */
  435. for (f = fsm; f; f = f->nxt)
  436. if (f->from == s)
  437. break;
  438. if (!f)
  439. { if (fsm_free)
  440. { f = fsm_free;
  441. memset(f, 0, sizeof(FSM_state));
  442. fsm_free = fsm_free->nxt;
  443. } else
  444. f = (FSM_state *) emalloc(sizeof(FSM_state));
  445. f->from = s;
  446. f->t = (FSM_trans *) 0;
  447. f->nxt = fsm;
  448. fsm = f;
  449. if (s > max_st_id)
  450. max_st_id = s;
  451. }
  452. return f;
  453. }
  454. static void
  455. FSM_EDGE(int from, int to, Element *e)
  456. { FSM_state *f;
  457. FSM_trans *t;
  458. f = mkstate(from); /* find it or else make it */
  459. if (trans_free)
  460. { t = trans_free;
  461. memset(t, 0, sizeof(FSM_trans));
  462. trans_free = trans_free->nxt;
  463. } else
  464. t = (FSM_trans *) emalloc(sizeof(FSM_trans));
  465. t->to = to;
  466. t->step = e;
  467. t->nxt = f->t;
  468. f->t = t;
  469. f = mkstate(to);
  470. f->in++;
  471. if (t->step)
  472. ana_stmnt(t, t->step->n, 0);
  473. }
  474. #define LVAL 1
  475. #define RVAL 0
  476. static void
  477. ana_var(FSM_trans *t, Lextok *now, int usage)
  478. { FSM_use *u, *v;
  479. if (!t
  480. || !now
  481. || !now->sym
  482. || now->sym->name[0] == '_')
  483. return;
  484. v = t->Val[usage];
  485. for (u = v; u; u = u->nxt)
  486. if (u->var == now->sym)
  487. return; /* it's already there */
  488. if (!now->lft)
  489. { /* not for array vars -- it's hard to tell statically
  490. if the index would, at runtime, evaluate to the
  491. same values at lval and rval references
  492. */
  493. if (use_free)
  494. { u = use_free;
  495. use_free = use_free->nxt;
  496. } else
  497. u = (FSM_use *) emalloc(sizeof(FSM_use));
  498. u->var = now->sym;
  499. u->nxt = t->Val[usage];
  500. t->Val[usage] = u;
  501. } else
  502. ana_stmnt(t, now->lft, RVAL); /* index */
  503. if (now->sym->type == STRUCT
  504. && now->rgt
  505. && now->rgt->lft)
  506. ana_var(t, now->rgt->lft, usage);
  507. }
  508. static void
  509. ana_stmnt(FSM_trans *t, Lextok *now, int usage)
  510. { Lextok *v;
  511. if (!t || !now) return;
  512. switch (now->ntyp) {
  513. case '.':
  514. case BREAK:
  515. case GOTO:
  516. case CONST:
  517. case TIMEOUT:
  518. case NONPROGRESS:
  519. case ELSE:
  520. case '@':
  521. case 'q':
  522. case IF:
  523. case DO:
  524. case ATOMIC:
  525. case NON_ATOMIC:
  526. case D_STEP:
  527. break;
  528. case '!':
  529. case UMIN:
  530. case '~':
  531. case ENABLED:
  532. case PC_VAL:
  533. case LEN:
  534. case FULL:
  535. case EMPTY:
  536. case NFULL:
  537. case NEMPTY:
  538. case ASSERT:
  539. case 'c':
  540. ana_stmnt(t, now->lft, RVAL);
  541. break;
  542. case '/':
  543. case '*':
  544. case '-':
  545. case '+':
  546. case '%':
  547. case '&':
  548. case '^':
  549. case '|':
  550. case LT:
  551. case GT:
  552. case LE:
  553. case GE:
  554. case NE:
  555. case EQ:
  556. case OR:
  557. case AND:
  558. case LSHIFT:
  559. case RSHIFT:
  560. ana_stmnt(t,now->lft, RVAL);
  561. ana_stmnt(t,now->rgt, RVAL);
  562. break;
  563. case ASGN:
  564. ana_stmnt(t, now->lft, LVAL);
  565. ana_stmnt(t, now->rgt, RVAL);
  566. break;
  567. case PRINT:
  568. case RUN:
  569. for (v = now->lft; v; v = v->rgt)
  570. ana_stmnt(t, v->lft, RVAL);
  571. break;
  572. case 's':
  573. ana_stmnt(t, now->lft, RVAL);
  574. for (v = now->rgt; v; v = v->rgt)
  575. ana_stmnt(t, v->lft, RVAL);
  576. break;
  577. case 'R':
  578. case 'r':
  579. ana_stmnt(t, now->lft, RVAL);
  580. for (v = now->rgt; v; v = v->rgt)
  581. { if (v->lft->ntyp == EVAL)
  582. ana_stmnt(t, v->lft->lft, RVAL);
  583. else
  584. if (v->lft->ntyp != CONST
  585. && now->ntyp != 'R') /* was v->lft->ntyp */
  586. ana_stmnt(t, v->lft, LVAL);
  587. }
  588. break;
  589. case '?':
  590. ana_stmnt(t, now->lft, RVAL);
  591. ana_stmnt(t, now->rgt->lft, RVAL);
  592. ana_stmnt(t, now->rgt->rgt, RVAL);
  593. break;
  594. case NAME:
  595. ana_var(t, now, usage);
  596. break;
  597. case 'p': /* remote ref */
  598. ana_stmnt(t, now->lft->lft, RVAL); /* process id */
  599. ana_var(t, now, RVAL);
  600. ana_var(t, now->rgt, RVAL);
  601. break;
  602. default:
  603. printf("spin: bad node type %d (ana_stmnt)\n", now->ntyp);
  604. fatal("aborting", (char *) 0);
  605. }
  606. }
  607. void
  608. ana_src(int dataflow, int merger)
  609. { ProcList *p;
  610. Element *e;
  611. int counter = 1;
  612. for (p = rdy; p; p = p->nxt)
  613. { if (p->tn == eventmapnr
  614. || p->tn == claimnr)
  615. continue;
  616. ana_seq(p->s);
  617. fsm_table();
  618. e = p->s->frst;
  619. #if 0
  620. if (dataflow || merger)
  621. { printf("spin: %d, optimizing '%s'",
  622. counter++, p->n->name);
  623. fflush(stdout);
  624. }
  625. #endif
  626. if (dataflow)
  627. { FSM_ANA();
  628. }
  629. if (merger)
  630. { FSM_MERGER(p->n->name);
  631. huntele(e, e->status)->merge_in = 1; /* start-state */
  632. #if 0
  633. printf("\n");
  634. #endif
  635. }
  636. FSM_DEL();
  637. }
  638. for (e = Al_El; e; e = e->Nxt)
  639. {
  640. if (!(e->status&DONE) && (verbose&32))
  641. { printf("unreachable code: ");
  642. printf("%s, line %3d: ",
  643. e->n->fn->name, e->n->ln);
  644. comment(stdout, e->n, 0);
  645. printf("\n");
  646. }
  647. e->status &= ~DONE;
  648. }
  649. }
  650. #if 0
  651. void
  652. whichnodeis(int s)
  653. { Element *e;
  654. for (e = Al_El; e; e = e->Nxt)
  655. if (e->seqno == s)
  656. { printf("\n\tnode %s:%d: ",
  657. e->n->fn->name, e->n->ln);
  658. comment(stdout, e->n, 0);
  659. printf("\n");
  660. }
  661. }
  662. #endif
  663. void
  664. spit_recvs(FILE *f1, FILE *f2)
  665. { Element *e;
  666. Sequence *s;
  667. extern int Unique;
  668. fprintf(f1, "unsigned char Is_Recv[%d];\n", Unique);
  669. fprintf(f2, "void\nset_recvs(void)\n{\n");
  670. for (e = Al_El; e; e = e->Nxt)
  671. { if (!e->n) continue;
  672. switch (e->n->ntyp) {
  673. case 'r':
  674. markit: fprintf(f2, "\tIs_Recv[%d] = 1;\n", e->Seqno);
  675. break;
  676. case D_STEP:
  677. s = e->n->sl->this;
  678. switch (s->frst->n->ntyp) {
  679. case DO:
  680. fatal("unexpected: do at start of d_step", (char *) 0);
  681. case IF: /* conservative: fall through */
  682. case 'r': goto markit;
  683. }
  684. break;
  685. }
  686. }
  687. fprintf(f2, "}\n");
  688. if (rvopt)
  689. {
  690. fprintf(f2, "int\nno_recvs(int me)\n{\n");
  691. fprintf(f2, " int h; uchar ot; short tt;\n");
  692. fprintf(f2, " Trans *t;\n");
  693. fprintf(f2, " for (h = BASE; h < (int) now._nr_pr; h++)\n");
  694. fprintf(f2, " { if (h == me) continue;\n");
  695. fprintf(f2, " tt = (short) ((P0 *)pptr(h))->_p;\n");
  696. fprintf(f2, " ot = (uchar) ((P0 *)pptr(h))->_t;\n");
  697. fprintf(f2, " for (t = trans[ot][tt]; t; t = t->nxt)\n");
  698. fprintf(f2, " if (Is_Recv[t->t_id]) return 0;\n");
  699. fprintf(f2, " }\n");
  700. fprintf(f2, " return 1;\n");
  701. fprintf(f2, "}\n");
  702. }
  703. }
  704. static void
  705. ana_seq(Sequence *s)
  706. { SeqList *h;
  707. Sequence *t;
  708. Element *e, *g;
  709. int From, To;
  710. for (e = s->frst; e; e = e->nxt)
  711. { if (e->status & DONE)
  712. goto checklast;
  713. e->status |= DONE;
  714. From = e->seqno;
  715. if (e->n->ntyp == UNLESS)
  716. ana_seq(e->sub->this);
  717. else if (e->sub)
  718. { for (h = e->sub; h; h = h->nxt)
  719. { g = huntstart(h->this->frst);
  720. To = g->seqno;
  721. if (g->n->ntyp != 'c'
  722. || g->n->lft->ntyp != CONST
  723. || g->n->lft->val != 0
  724. || g->esc)
  725. FSM_EDGE(From, To, e);
  726. /* else it's a dead link */
  727. }
  728. for (h = e->sub; h; h = h->nxt)
  729. ana_seq(h->this);
  730. } else if (e->n->ntyp == ATOMIC
  731. || e->n->ntyp == D_STEP
  732. || e->n->ntyp == NON_ATOMIC)
  733. {
  734. t = e->n->sl->this;
  735. g = huntstart(t->frst);
  736. t->last->nxt = e->nxt;
  737. To = g->seqno;
  738. FSM_EDGE(From, To, e);
  739. ana_seq(t);
  740. } else
  741. { if (e->n->ntyp == GOTO)
  742. { g = get_lab(e->n, 1);
  743. g = huntele(g, e->status);
  744. To = g->seqno;
  745. } else if (e->nxt)
  746. { g = huntele(e->nxt, e->status);
  747. To = g->seqno;
  748. } else
  749. To = 0;
  750. FSM_EDGE(From, To, e);
  751. if (e->esc
  752. && e->n->ntyp != GOTO
  753. && e->n->ntyp != '.')
  754. for (h = e->esc; h; h = h->nxt)
  755. { g = huntstart(h->this->frst);
  756. To = g->seqno;
  757. FSM_EDGE(From, To, ZE);
  758. ana_seq(h->this);
  759. }
  760. }
  761. checklast: if (e == s->last)
  762. break;
  763. }
  764. }