pangen5.c 16 KB

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