flow.c 17 KB

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