flow.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794
  1. /***** spin: flow.c *****/
  2. /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* No guarantee whatsoever is expressed or implied by the distribution of */
  5. /* this code. Permission is given to distribute this code provided that */
  6. /* this introductory message is not removed and no monies are exchanged. */
  7. /* Software written by Gerard J. Holzmann. For tool documentation see: */
  8. /* http://spinroot.com/ */
  9. /* Send all bug-reports and/or questions to: bugs@spinroot.com */
  10. #include "spin.h"
  11. #include "y.tab.h"
  12. extern Symbol *Fname;
  13. extern int nr_errs, lineno, verbose;
  14. extern short has_unless, has_badelse;
  15. Element *Al_El = ZE;
  16. Label *labtab = (Label *) 0;
  17. int Unique=0, Elcnt=0, DstepStart = -1;
  18. static Lbreak *breakstack = (Lbreak *) 0;
  19. static Lextok *innermost;
  20. static SeqList *cur_s = (SeqList *) 0;
  21. static int break_id=0;
  22. static Element *if_seq(Lextok *);
  23. static Element *new_el(Lextok *);
  24. static Element *unless_seq(Lextok *);
  25. static void add_el(Element *, Sequence *);
  26. static void attach_escape(Sequence *, Sequence *);
  27. static void mov_lab(Symbol *, Element *, Element *);
  28. static void walk_atomic(Element *, Element *, int);
  29. void
  30. open_seq(int top)
  31. { SeqList *t;
  32. Sequence *s = (Sequence *) emalloc(sizeof(Sequence));
  33. t = seqlist(s, cur_s);
  34. cur_s = t;
  35. if (top) Elcnt = 1;
  36. }
  37. void
  38. rem_Seq(void)
  39. {
  40. DstepStart = Unique;
  41. }
  42. void
  43. unrem_Seq(void)
  44. {
  45. DstepStart = -1;
  46. }
  47. static int
  48. Rjumpslocal(Element *q, Element *stop)
  49. { Element *lb, *f;
  50. SeqList *h;
  51. /* allow no jumps out of a d_step sequence */
  52. for (f = q; f && f != stop; f = f->nxt)
  53. { if (f && f->n && f->n->ntyp == GOTO)
  54. { lb = get_lab(f->n, 0);
  55. if (!lb || lb->Seqno < DstepStart)
  56. { lineno = f->n->ln;
  57. Fname = f->n->fn;
  58. return 0;
  59. } }
  60. for (h = f->sub; h; h = h->nxt)
  61. { if (!Rjumpslocal(h->this->frst, h->this->last))
  62. return 0;
  63. } }
  64. return 1;
  65. }
  66. void
  67. cross_dsteps(Lextok *a, Lextok *b)
  68. {
  69. if (a && b
  70. && a->indstep != b->indstep)
  71. { lineno = a->ln;
  72. Fname = a->fn;
  73. fatal("jump into d_step sequence", (char *) 0);
  74. }
  75. }
  76. int
  77. is_skip(Lextok *n)
  78. {
  79. return (n->ntyp == PRINT
  80. || n->ntyp == PRINTM
  81. || (n->ntyp == 'c'
  82. && n->lft
  83. && n->lft->ntyp == CONST
  84. && n->lft->val == 1));
  85. }
  86. void
  87. check_sequence(Sequence *s)
  88. { Element *e, *le = ZE;
  89. Lextok *n;
  90. int cnt = 0;
  91. for (e = s->frst; e; le = e, e = e->nxt)
  92. { n = e->n;
  93. if (is_skip(n) && !has_lab(e, 0))
  94. { cnt++;
  95. if (cnt > 1
  96. && n->ntyp != PRINT
  97. && n->ntyp != PRINTM)
  98. { if (verbose&32)
  99. printf("spin: line %d %s, redundant skip\n",
  100. n->ln, n->fn->name);
  101. if (e != s->frst
  102. && e != s->last
  103. && e != s->extent)
  104. { e->status |= DONE; /* not unreachable */
  105. le->nxt = e->nxt; /* remove it */
  106. e = le;
  107. }
  108. }
  109. } else
  110. cnt = 0;
  111. }
  112. }
  113. void
  114. prune_opts(Lextok *n)
  115. { SeqList *l;
  116. extern Symbol *context;
  117. extern char *claimproc;
  118. if (!n
  119. || (context && claimproc && strcmp(context->name, claimproc) == 0))
  120. return;
  121. for (l = n->sl; l; l = l->nxt) /* find sequences of unlabeled skips */
  122. check_sequence(l->this);
  123. }
  124. Sequence *
  125. close_seq(int nottop)
  126. { Sequence *s = cur_s->this;
  127. Symbol *z;
  128. if (nottop > 0 && (z = has_lab(s->frst, 0)))
  129. { printf("error: (%s:%d) label %s placed incorrectly\n",
  130. (s->frst->n)?s->frst->n->fn->name:"-",
  131. (s->frst->n)?s->frst->n->ln:0,
  132. z->name);
  133. switch (nottop) {
  134. case 1:
  135. printf("=====> stmnt unless Label: stmnt\n");
  136. printf("sorry, cannot jump to the guard of an\n");
  137. printf("escape (it is not a unique state)\n");
  138. break;
  139. case 2:
  140. printf("=====> instead of ");
  141. printf("\"Label: stmnt unless stmnt\"\n");
  142. printf("=====> always use ");
  143. printf("\"Label: { stmnt unless stmnt }\"\n");
  144. break;
  145. case 3:
  146. printf("=====> instead of ");
  147. printf("\"atomic { Label: statement ... }\"\n");
  148. printf("=====> always use ");
  149. printf("\"Label: atomic { statement ... }\"\n");
  150. break;
  151. case 4:
  152. printf("=====> instead of ");
  153. printf("\"d_step { Label: statement ... }\"\n");
  154. printf("=====> always use ");
  155. printf("\"Label: d_step { statement ... }\"\n");
  156. break;
  157. case 5:
  158. printf("=====> instead of ");
  159. printf("\"{ Label: statement ... }\"\n");
  160. printf("=====> always use ");
  161. printf("\"Label: { statement ... }\"\n");
  162. break;
  163. case 6:
  164. printf("=====>instead of\n");
  165. printf(" do (or if)\n");
  166. printf(" :: ...\n");
  167. printf(" :: Label: statement\n");
  168. printf(" od (of fi)\n");
  169. printf("=====>always use\n");
  170. printf("Label: do (or if)\n");
  171. printf(" :: ...\n");
  172. printf(" :: statement\n");
  173. printf(" od (or fi)\n");
  174. break;
  175. case 7:
  176. printf("cannot happen - labels\n");
  177. break;
  178. }
  179. alldone(1);
  180. }
  181. if (nottop == 4
  182. && !Rjumpslocal(s->frst, s->last))
  183. fatal("non_local jump in d_step sequence", (char *) 0);
  184. cur_s = cur_s->nxt;
  185. s->maxel = Elcnt;
  186. s->extent = s->last;
  187. if (!s->last)
  188. fatal("sequence must have at least one statement", (char *) 0);
  189. return s;
  190. }
  191. Lextok *
  192. do_unless(Lextok *No, Lextok *Es)
  193. { SeqList *Sl;
  194. Lextok *Re = nn(ZN, UNLESS, ZN, ZN);
  195. Re->ln = No->ln;
  196. Re->fn = No->fn;
  197. has_unless++;
  198. if (Es->ntyp == NON_ATOMIC)
  199. Sl = Es->sl;
  200. else
  201. { open_seq(0); add_seq(Es);
  202. Sl = seqlist(close_seq(1), 0);
  203. }
  204. if (No->ntyp == NON_ATOMIC)
  205. { No->sl->nxt = Sl;
  206. Sl = No->sl;
  207. } else if (No->ntyp == ':'
  208. && (No->lft->ntyp == NON_ATOMIC
  209. || No->lft->ntyp == ATOMIC
  210. || No->lft->ntyp == D_STEP))
  211. {
  212. int tok = No->lft->ntyp;
  213. No->lft->sl->nxt = Sl;
  214. Re->sl = No->lft->sl;
  215. open_seq(0); add_seq(Re);
  216. Re = nn(ZN, tok, ZN, ZN);
  217. Re->sl = seqlist(close_seq(7), 0);
  218. Re->ln = No->ln;
  219. Re->fn = No->fn;
  220. Re = nn(No, ':', Re, ZN); /* lift label */
  221. Re->ln = No->ln;
  222. Re->fn = No->fn;
  223. return Re;
  224. } else
  225. { open_seq(0); add_seq(No);
  226. Sl = seqlist(close_seq(2), Sl);
  227. }
  228. Re->sl = Sl;
  229. return Re;
  230. }
  231. SeqList *
  232. seqlist(Sequence *s, SeqList *r)
  233. { SeqList *t = (SeqList *) emalloc(sizeof(SeqList));
  234. t->this = s;
  235. t->nxt = r;
  236. return t;
  237. }
  238. static Element *
  239. new_el(Lextok *n)
  240. { Element *m;
  241. if (n)
  242. { if (n->ntyp == IF || n->ntyp == DO)
  243. return if_seq(n);
  244. if (n->ntyp == UNLESS)
  245. return unless_seq(n);
  246. }
  247. m = (Element *) emalloc(sizeof(Element));
  248. m->n = n;
  249. m->seqno = Elcnt++;
  250. m->Seqno = Unique++;
  251. m->Nxt = Al_El; Al_El = m;
  252. return m;
  253. }
  254. static int
  255. has_chanref(Lextok *n)
  256. {
  257. if (!n) return 0;
  258. switch (n->ntyp) {
  259. case 's': case 'r':
  260. #if 0
  261. case 'R': case LEN:
  262. #endif
  263. case FULL: case NFULL:
  264. case EMPTY: case NEMPTY:
  265. return 1;
  266. default:
  267. break;
  268. }
  269. if (has_chanref(n->lft))
  270. return 1;
  271. return has_chanref(n->rgt);
  272. }
  273. void
  274. loose_ends(void) /* properly tie-up ends of sub-sequences */
  275. { Element *e, *f;
  276. for (e = Al_El; e; e = e->Nxt)
  277. { if (!e->n
  278. || !e->nxt)
  279. continue;
  280. switch (e->n->ntyp) {
  281. case ATOMIC:
  282. case NON_ATOMIC:
  283. case D_STEP:
  284. f = e->nxt;
  285. while (f && f->n->ntyp == '.')
  286. f = f->nxt;
  287. if (0) printf("link %d, {%d .. %d} -> %d (ntyp=%d) was %d\n",
  288. e->seqno,
  289. e->n->sl->this->frst->seqno,
  290. e->n->sl->this->last->seqno,
  291. f?f->seqno:-1, f?f->n->ntyp:-1,
  292. e->n->sl->this->last->nxt?e->n->sl->this->last->nxt->seqno:-1);
  293. if (!e->n->sl->this->last->nxt)
  294. e->n->sl->this->last->nxt = f;
  295. else
  296. { if (e->n->sl->this->last->nxt->n->ntyp != GOTO)
  297. { if (!f || e->n->sl->this->last->nxt->seqno != f->seqno)
  298. non_fatal("unexpected: loose ends", (char *)0);
  299. } else
  300. e->n->sl->this->last = e->n->sl->this->last->nxt;
  301. /*
  302. * fix_dest can push a goto into the nxt position
  303. * in that case the goto wins and f is not needed
  304. * but the last fields needs adjusting
  305. */
  306. }
  307. break;
  308. } }
  309. }
  310. static Element *
  311. if_seq(Lextok *n)
  312. { int tok = n->ntyp;
  313. SeqList *s = n->sl;
  314. Element *e = new_el(ZN);
  315. Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */
  316. SeqList *z, *prev_z = (SeqList *) 0;
  317. SeqList *move_else = (SeqList *) 0; /* to end of optionlist */
  318. int ref_chans = 0;
  319. for (z = s; z; z = z->nxt)
  320. { if (!z->this->frst)
  321. continue;
  322. if (z->this->frst->n->ntyp == ELSE)
  323. { if (move_else)
  324. fatal("duplicate `else'", (char *) 0);
  325. if (z->nxt) /* is not already at the end */
  326. { move_else = z;
  327. if (prev_z)
  328. prev_z->nxt = z->nxt;
  329. else
  330. s = n->sl = z->nxt;
  331. continue;
  332. }
  333. } else
  334. ref_chans |= has_chanref(z->this->frst->n);
  335. prev_z = z;
  336. }
  337. if (move_else)
  338. { move_else->nxt = (SeqList *) 0;
  339. /* if there is no prev, then else was at the end */
  340. if (!prev_z) fatal("cannot happen - if_seq", (char *) 0);
  341. prev_z->nxt = move_else;
  342. prev_z = move_else;
  343. }
  344. if (prev_z
  345. && ref_chans
  346. && prev_z->this->frst->n->ntyp == ELSE)
  347. { prev_z->this->frst->n->val = 1;
  348. has_badelse++;
  349. non_fatal("dubious use of 'else' combined with i/o,",
  350. (char *)0);
  351. nr_errs--;
  352. }
  353. e->n = nn(n, tok, ZN, ZN);
  354. e->n->sl = s; /* preserve as info only */
  355. e->sub = s;
  356. for (z = s; z; prev_z = z, z = z->nxt)
  357. add_el(t, z->this); /* append target */
  358. if (tok == DO)
  359. { add_el(t, cur_s->this); /* target upfront */
  360. t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */
  361. set_lab(break_dest(), t); /* new exit */
  362. breakstack = breakstack->nxt; /* pop stack */
  363. }
  364. add_el(e, cur_s->this);
  365. add_el(t, cur_s->this);
  366. return e; /* destination node for label */
  367. }
  368. static void
  369. escape_el(Element *f, Sequence *e)
  370. { SeqList *z;
  371. for (z = f->esc; z; z = z->nxt)
  372. if (z->this == e)
  373. return; /* already there */
  374. /* cover the lower-level escapes of this state */
  375. for (z = f->esc; z; z = z->nxt)
  376. attach_escape(z->this, e);
  377. /* now attach escape to the state itself */
  378. f->esc = seqlist(e, f->esc); /* in lifo order... */
  379. #ifdef DEBUG
  380. printf("attach %d (", e->frst->Seqno);
  381. comment(stdout, e->frst->n, 0);
  382. printf(") to %d (", f->Seqno);
  383. comment(stdout, f->n, 0);
  384. printf(")\n");
  385. #endif
  386. switch (f->n->ntyp) {
  387. case UNLESS:
  388. attach_escape(f->sub->this, e);
  389. break;
  390. case IF:
  391. case DO:
  392. for (z = f->sub; z; z = z->nxt)
  393. attach_escape(z->this, e);
  394. break;
  395. case D_STEP:
  396. /* attach only to the guard stmnt */
  397. escape_el(f->n->sl->this->frst, e);
  398. break;
  399. case ATOMIC:
  400. case NON_ATOMIC:
  401. /* attach to all stmnts */
  402. attach_escape(f->n->sl->this, e);
  403. break;
  404. }
  405. }
  406. static void
  407. attach_escape(Sequence *n, Sequence *e)
  408. { Element *f;
  409. for (f = n->frst; f; f = f->nxt)
  410. { escape_el(f, e);
  411. if (f == n->extent)
  412. break;
  413. }
  414. }
  415. static Element *
  416. unless_seq(Lextok *n)
  417. { SeqList *s = n->sl;
  418. Element *e = new_el(ZN);
  419. Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */
  420. SeqList *z;
  421. e->n = nn(n, UNLESS, ZN, ZN);
  422. e->n->sl = s; /* info only */
  423. e->sub = s;
  424. /* need 2 sequences: normal execution and escape */
  425. if (!s || !s->nxt || s->nxt->nxt)
  426. fatal("unexpected unless structure", (char *)0);
  427. /* append the target state to both */
  428. for (z = s; z; z = z->nxt)
  429. add_el(t, z->this);
  430. /* attach escapes to all states in normal sequence */
  431. attach_escape(s->this, s->nxt->this);
  432. add_el(e, cur_s->this);
  433. add_el(t, cur_s->this);
  434. #ifdef DEBUG
  435. printf("unless element (%d,%d):\n", e->Seqno, t->Seqno);
  436. for (z = s; z; z = z->nxt)
  437. { Element *x; printf("\t%d,%d,%d :: ",
  438. z->this->frst->Seqno,
  439. z->this->extent->Seqno,
  440. z->this->last->Seqno);
  441. for (x = z->this->frst; x; x = x->nxt)
  442. printf("(%d)", x->Seqno);
  443. printf("\n");
  444. }
  445. #endif
  446. return e;
  447. }
  448. Element *
  449. mk_skip(void)
  450. { Lextok *t = nn(ZN, CONST, ZN, ZN);
  451. t->val = 1;
  452. return new_el(nn(ZN, 'c', t, ZN));
  453. }
  454. static void
  455. add_el(Element *e, Sequence *s)
  456. {
  457. if (e->n->ntyp == GOTO)
  458. { Symbol *z = has_lab(e, (1|2|4));
  459. if (z)
  460. { Element *y; /* insert a skip */
  461. y = mk_skip();
  462. mov_lab(z, e, y); /* inherit label */
  463. add_el(y, s);
  464. } }
  465. #ifdef DEBUG
  466. printf("add_el %d after %d -- ",
  467. e->Seqno, (s->last)?s->last->Seqno:-1);
  468. comment(stdout, e->n, 0);
  469. printf("\n");
  470. #endif
  471. if (!s->frst)
  472. s->frst = e;
  473. else
  474. s->last->nxt = e;
  475. s->last = e;
  476. }
  477. static Element *
  478. colons(Lextok *n)
  479. {
  480. if (!n)
  481. return ZE;
  482. if (n->ntyp == ':')
  483. { Element *e = colons(n->lft);
  484. set_lab(n->sym, e);
  485. return e;
  486. }
  487. innermost = n;
  488. return new_el(n);
  489. }
  490. void
  491. add_seq(Lextok *n)
  492. { Element *e;
  493. if (!n) return;
  494. innermost = n;
  495. e = colons(n);
  496. if (innermost->ntyp != IF
  497. && innermost->ntyp != DO
  498. && innermost->ntyp != UNLESS)
  499. add_el(e, cur_s->this);
  500. }
  501. void
  502. set_lab(Symbol *s, Element *e)
  503. { Label *l; extern Symbol *context;
  504. if (!s) return;
  505. for (l = labtab; l; l = l->nxt)
  506. if (l->s == s && l->c == context)
  507. { non_fatal("label %s redeclared", s->name);
  508. break;
  509. }
  510. l = (Label *) emalloc(sizeof(Label));
  511. l->s = s;
  512. l->c = context;
  513. l->e = e;
  514. l->nxt = labtab;
  515. labtab = l;
  516. }
  517. Element *
  518. get_lab(Lextok *n, int md)
  519. { Label *l;
  520. Symbol *s = n->sym;
  521. for (l = labtab; l; l = l->nxt)
  522. if (s == l->s)
  523. return (l->e);
  524. lineno = n->ln;
  525. Fname = n->fn;
  526. if (md) fatal("undefined label %s", s->name);
  527. return ZE;
  528. }
  529. Symbol *
  530. has_lab(Element *e, int special)
  531. { Label *l;
  532. for (l = labtab; l; l = l->nxt)
  533. { if (e != l->e)
  534. continue;
  535. if (special == 0
  536. || ((special&1) && !strncmp(l->s->name, "accept", 6))
  537. || ((special&2) && !strncmp(l->s->name, "end", 3))
  538. || ((special&4) && !strncmp(l->s->name, "progress", 8)))
  539. return (l->s);
  540. }
  541. return ZS;
  542. }
  543. static void
  544. mov_lab(Symbol *z, Element *e, Element *y)
  545. { Label *l;
  546. for (l = labtab; l; l = l->nxt)
  547. if (e == l->e)
  548. { l->e = y;
  549. return;
  550. }
  551. if (e->n)
  552. { lineno = e->n->ln;
  553. Fname = e->n->fn;
  554. }
  555. fatal("cannot happen - mov_lab %s", z->name);
  556. }
  557. void
  558. fix_dest(Symbol *c, Symbol *a) /* c:label name, a:proctype name */
  559. { Label *l; extern Symbol *context;
  560. #if 0
  561. printf("ref to label '%s' in proctype '%s', search:\n",
  562. c->name, a->name);
  563. for (l = labtab; l; l = l->nxt)
  564. printf(" %s in %s\n", l->s->name, l->c->name);
  565. #endif
  566. for (l = labtab; l; l = l->nxt)
  567. { if (strcmp(c->name, l->s->name) == 0
  568. && strcmp(a->name, l->c->name) == 0) /* ? */
  569. break;
  570. }
  571. if (!l)
  572. { printf("spin: label '%s' (proctype %s)\n", c->name, a->name);
  573. non_fatal("unknown label '%s'", c->name);
  574. if (context == a)
  575. printf("spin: cannot remote ref a label inside the same proctype\n");
  576. return;
  577. }
  578. if (!l->e || !l->e->n)
  579. fatal("fix_dest error (%s)", c->name);
  580. if (l->e->n->ntyp == GOTO)
  581. { Element *y = (Element *) emalloc(sizeof(Element));
  582. int keep_ln = l->e->n->ln;
  583. Symbol *keep_fn = l->e->n->fn;
  584. /* insert skip - or target is optimized away */
  585. y->n = l->e->n; /* copy of the goto */
  586. y->seqno = find_maxel(a); /* unique seqno within proc */
  587. y->nxt = l->e->nxt;
  588. y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y;
  589. /* turn the original element+seqno into a skip */
  590. l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN);
  591. l->e->n->ln = l->e->n->lft->ln = keep_ln;
  592. l->e->n->fn = l->e->n->lft->fn = keep_fn;
  593. l->e->n->lft->val = 1;
  594. l->e->nxt = y; /* append the goto */
  595. }
  596. l->e->status |= CHECK2; /* treat as if global */
  597. if (l->e->status & (ATOM | L_ATOM | D_ATOM))
  598. { non_fatal("cannot reference label inside atomic or d_step (%s)",
  599. c->name);
  600. }
  601. }
  602. int
  603. find_lab(Symbol *s, Symbol *c, int markit)
  604. { Label *l;
  605. for (l = labtab; l; l = l->nxt)
  606. { if (strcmp(s->name, l->s->name) == 0
  607. && strcmp(c->name, l->c->name) == 0)
  608. { l->visible |= markit;
  609. return (l->e->seqno);
  610. } }
  611. return 0;
  612. }
  613. void
  614. pushbreak(void)
  615. { Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak));
  616. Symbol *l;
  617. char buf[64];
  618. sprintf(buf, ":b%d", break_id++);
  619. l = lookup(buf);
  620. r->l = l;
  621. r->nxt = breakstack;
  622. breakstack = r;
  623. }
  624. Symbol *
  625. break_dest(void)
  626. {
  627. if (!breakstack)
  628. fatal("misplaced break statement", (char *)0);
  629. return breakstack->l;
  630. }
  631. void
  632. make_atomic(Sequence *s, int added)
  633. { Element *f;
  634. walk_atomic(s->frst, s->last, added);
  635. f = s->last;
  636. switch (f->n->ntyp) { /* is last step basic stmnt or sequence ? */
  637. case NON_ATOMIC:
  638. case ATOMIC:
  639. /* redo and search for the last step of that sequence */
  640. make_atomic(f->n->sl->this, added);
  641. break;
  642. case UNLESS:
  643. /* escapes are folded into main sequence */
  644. make_atomic(f->sub->this, added);
  645. break;
  646. default:
  647. f->status &= ~ATOM;
  648. f->status |= L_ATOM;
  649. break;
  650. }
  651. }
  652. static void
  653. walk_atomic(Element *a, Element *b, int added)
  654. { Element *f; Symbol *ofn; int oln;
  655. SeqList *h;
  656. ofn = Fname;
  657. oln = lineno;
  658. for (f = a; ; f = f->nxt)
  659. { f->status |= (ATOM|added);
  660. switch (f->n->ntyp) {
  661. case ATOMIC:
  662. if (verbose&32)
  663. printf("spin: warning, line %3d %s, atomic inside %s (ignored)\n",
  664. f->n->ln, f->n->fn->name, (added)?"d_step":"atomic");
  665. goto mknonat;
  666. case D_STEP:
  667. if (!(verbose&32))
  668. { if (added) goto mknonat;
  669. break;
  670. }
  671. printf("spin: warning, line %3d %s, d_step inside ",
  672. f->n->ln, f->n->fn->name);
  673. if (added)
  674. { printf("d_step (ignored)\n");
  675. goto mknonat;
  676. }
  677. printf("atomic\n");
  678. break;
  679. case NON_ATOMIC:
  680. mknonat: f->n->ntyp = NON_ATOMIC; /* can jump here */
  681. h = f->n->sl;
  682. walk_atomic(h->this->frst, h->this->last, added);
  683. break;
  684. case UNLESS:
  685. if (added)
  686. { printf("spin: error, line %3d %s, unless in d_step (ignored)\n",
  687. f->n->ln, f->n->fn->name);
  688. }
  689. }
  690. for (h = f->sub; h; h = h->nxt)
  691. walk_atomic(h->this->frst, h->this->last, added);
  692. if (f == b)
  693. break;
  694. }
  695. Fname = ofn;
  696. lineno = oln;
  697. }
  698. void
  699. dumplabels(void)
  700. { Label *l;
  701. for (l = labtab; l; l = l->nxt)
  702. if (l->c != 0 && l->s->name[0] != ':')
  703. printf("label %s %d <%s>\n",
  704. l->s->name, l->e->seqno, l->c->name);
  705. }