pangen5.c 17 KB

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