pangen5.c 16 KB

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