1*219b2ee8SDavid du Colombier /***** spin: flow.c *****/ 2*219b2ee8SDavid du Colombier 3*219b2ee8SDavid du Colombier /* Copyright (c) 1991,1995 by AT&T Corporation. All Rights Reserved. */ 4*219b2ee8SDavid du Colombier /* This software is for educational purposes only. */ 5*219b2ee8SDavid du Colombier /* Permission is given to distribute this code provided that this intro- */ 6*219b2ee8SDavid du Colombier /* ductory message is not removed and no monies are exchanged. */ 7*219b2ee8SDavid du Colombier /* No guarantee is expressed or implied by the distribution of this code. */ 8*219b2ee8SDavid du Colombier /* Software written by Gerard J. Holzmann as part of the book: */ 9*219b2ee8SDavid du Colombier /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */ 10*219b2ee8SDavid du Colombier /* Prentice Hall, Englewood Cliffs, NJ, 07632. */ 11*219b2ee8SDavid du Colombier /* Send bug-reports and/or questions to: gerard@research.att.com */ 12*219b2ee8SDavid du Colombier 13*219b2ee8SDavid du Colombier #include "spin.h" 14*219b2ee8SDavid du Colombier #include "y.tab.h" 15*219b2ee8SDavid du Colombier 16*219b2ee8SDavid du Colombier Element *Al_El = ZE; 17*219b2ee8SDavid du Colombier Label *labtab = (Label *) 0; 18*219b2ee8SDavid du Colombier Lbreak *breakstack = (Lbreak *) 0; 19*219b2ee8SDavid du Colombier Lextok *innermost; 20*219b2ee8SDavid du Colombier SeqList *cur_s = (SeqList *) 0; 21*219b2ee8SDavid du Colombier int Elcnt=0, Unique=0, break_id=0; 22*219b2ee8SDavid du Colombier int DstepStart = -1; 23*219b2ee8SDavid du Colombier 24*219b2ee8SDavid du Colombier extern Symbol *Fname; 25*219b2ee8SDavid du Colombier extern int lineno, has_unless; 26*219b2ee8SDavid du Colombier 27*219b2ee8SDavid du Colombier void 28*219b2ee8SDavid du Colombier open_seq(int top) 29*219b2ee8SDavid du Colombier { SeqList *t; 30*219b2ee8SDavid du Colombier Sequence *s = (Sequence *) emalloc(sizeof(Sequence)); 31*219b2ee8SDavid du Colombier 32*219b2ee8SDavid du Colombier t = seqlist(s, cur_s); 33*219b2ee8SDavid du Colombier cur_s = t; 34*219b2ee8SDavid du Colombier if (top) Elcnt = 1; 35*219b2ee8SDavid du Colombier } 36*219b2ee8SDavid du Colombier 37*219b2ee8SDavid du Colombier void 38*219b2ee8SDavid du Colombier rem_Seq(void) 39*219b2ee8SDavid du Colombier { 40*219b2ee8SDavid du Colombier DstepStart = Unique; 41*219b2ee8SDavid du Colombier } 42*219b2ee8SDavid du Colombier 43*219b2ee8SDavid du Colombier void 44*219b2ee8SDavid du Colombier unrem_Seq(void) 45*219b2ee8SDavid du Colombier { 46*219b2ee8SDavid du Colombier DstepStart = -1; 47*219b2ee8SDavid du Colombier } 48*219b2ee8SDavid du Colombier 49*219b2ee8SDavid du Colombier int 50*219b2ee8SDavid du Colombier Rjumpslocal(Element *q, Element *stop) 51*219b2ee8SDavid du Colombier { Element *lb, *f; 52*219b2ee8SDavid du Colombier SeqList *h; 53*219b2ee8SDavid du Colombier 54*219b2ee8SDavid du Colombier /* allow no jumps out of a d_step sequence */ 55*219b2ee8SDavid du Colombier for (f = q; f && f != stop; f = f->nxt) 56*219b2ee8SDavid du Colombier { if (f && f->n && f->n->ntyp == GOTO) 57*219b2ee8SDavid du Colombier { lb = get_lab(f->n, 0); 58*219b2ee8SDavid du Colombier if (!lb || lb->Seqno < DstepStart) 59*219b2ee8SDavid du Colombier { lineno = f->n->ln; 60*219b2ee8SDavid du Colombier Fname = f->n->fn; 61*219b2ee8SDavid du Colombier return 0; 62*219b2ee8SDavid du Colombier } } 63*219b2ee8SDavid du Colombier for (h = f->sub; h; h = h->nxt) 64*219b2ee8SDavid du Colombier { if (!Rjumpslocal(h->this->frst, h->this->last)) 65*219b2ee8SDavid du Colombier return 0; 66*219b2ee8SDavid du Colombier 67*219b2ee8SDavid du Colombier } } 68*219b2ee8SDavid du Colombier return 1; 69*219b2ee8SDavid du Colombier } 70*219b2ee8SDavid du Colombier 71*219b2ee8SDavid du Colombier void 72*219b2ee8SDavid du Colombier cross_dsteps(Lextok *a, Lextok *b) 73*219b2ee8SDavid du Colombier { 74*219b2ee8SDavid du Colombier if (a && b 75*219b2ee8SDavid du Colombier && a->indstep != b->indstep) 76*219b2ee8SDavid du Colombier { lineno = a->ln; 77*219b2ee8SDavid du Colombier Fname = a->fn; 78*219b2ee8SDavid du Colombier fatal("jump into d_step sequence", (char *) 0); 79*219b2ee8SDavid du Colombier } 80*219b2ee8SDavid du Colombier } 81*219b2ee8SDavid du Colombier 82*219b2ee8SDavid du Colombier Sequence * 83*219b2ee8SDavid du Colombier close_seq(int nottop) 84*219b2ee8SDavid du Colombier { Sequence *s = cur_s->this; 85*219b2ee8SDavid du Colombier Symbol *z; 86*219b2ee8SDavid du Colombier 87*219b2ee8SDavid du Colombier if (nottop > 0 && (z = has_lab(s->frst))) 88*219b2ee8SDavid du Colombier { printf("error: (%s:%d) label %s placed incorrectly\n", 89*219b2ee8SDavid du Colombier (s->frst->n)?s->frst->n->fn->name:"-", 90*219b2ee8SDavid du Colombier (s->frst->n)?s->frst->n->ln:0, 91*219b2ee8SDavid du Colombier z->name); 92*219b2ee8SDavid du Colombier switch (nottop) { 93*219b2ee8SDavid du Colombier case 1: 94*219b2ee8SDavid du Colombier printf("=====> stmnt unless Label: stmnt\n"); 95*219b2ee8SDavid du Colombier printf("sorry, cannot jump to the guard of an\n"); 96*219b2ee8SDavid du Colombier printf("escape (it is not a unique state)\n"); 97*219b2ee8SDavid du Colombier break; 98*219b2ee8SDavid du Colombier case 2: 99*219b2ee8SDavid du Colombier printf("=====> instead of "); 100*219b2ee8SDavid du Colombier printf("\"Label: stmnt unless stmnt\"\n"); 101*219b2ee8SDavid du Colombier printf("=====> always use "); 102*219b2ee8SDavid du Colombier printf("\"Label: { stmnt unless stmnt }\"\n"); 103*219b2ee8SDavid du Colombier break; 104*219b2ee8SDavid du Colombier case 3: 105*219b2ee8SDavid du Colombier printf("=====> instead of "); 106*219b2ee8SDavid du Colombier printf("\"atomic { Label: statement ... }\"\n"); 107*219b2ee8SDavid du Colombier printf("=====> always use "); 108*219b2ee8SDavid du Colombier printf("\"Label: atomic { statement ... }\"\n"); 109*219b2ee8SDavid du Colombier break; 110*219b2ee8SDavid du Colombier case 4: 111*219b2ee8SDavid du Colombier printf("=====> instead of "); 112*219b2ee8SDavid du Colombier printf("\"d_step { Label: statement ... }\"\n"); 113*219b2ee8SDavid du Colombier printf("=====> always use "); 114*219b2ee8SDavid du Colombier printf("\"Label: d_step { statement ... }\"\n"); 115*219b2ee8SDavid du Colombier break; 116*219b2ee8SDavid du Colombier case 5: 117*219b2ee8SDavid du Colombier printf("=====> instead of "); 118*219b2ee8SDavid du Colombier printf("\"{ Label: statement ... }\"\n"); 119*219b2ee8SDavid du Colombier printf("=====> always use "); 120*219b2ee8SDavid du Colombier printf("\"Label: { statement ... }\"\n"); 121*219b2ee8SDavid du Colombier break; 122*219b2ee8SDavid du Colombier case 6: 123*219b2ee8SDavid du Colombier printf("=====>instead of\n"); 124*219b2ee8SDavid du Colombier printf(" do (or if)\n"); 125*219b2ee8SDavid du Colombier printf(" :: ...\n"); 126*219b2ee8SDavid du Colombier printf(" :: Label: statement\n"); 127*219b2ee8SDavid du Colombier printf(" od (of fi)\n"); 128*219b2ee8SDavid du Colombier printf("=====>always use\n"); 129*219b2ee8SDavid du Colombier printf("Label: do (or if)\n"); 130*219b2ee8SDavid du Colombier printf(" :: ...\n"); 131*219b2ee8SDavid du Colombier printf(" :: statement\n"); 132*219b2ee8SDavid du Colombier printf(" od (or fi)\n"); 133*219b2ee8SDavid du Colombier break; 134*219b2ee8SDavid du Colombier case 7: 135*219b2ee8SDavid du Colombier printf("cannot happen - labels\n"); 136*219b2ee8SDavid du Colombier break; 137*219b2ee8SDavid du Colombier } 138*219b2ee8SDavid du Colombier exit(1); 139*219b2ee8SDavid du Colombier } 140*219b2ee8SDavid du Colombier 141*219b2ee8SDavid du Colombier if (nottop == 4 142*219b2ee8SDavid du Colombier && !Rjumpslocal(s->frst, s->last)) 143*219b2ee8SDavid du Colombier fatal("non_local jump in d_step sequence", (char *) 0); 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier cur_s = cur_s->nxt; 146*219b2ee8SDavid du Colombier s->maxel = Elcnt; 147*219b2ee8SDavid du Colombier s->extent = s->last; 148*219b2ee8SDavid du Colombier return s; 149*219b2ee8SDavid du Colombier } 150*219b2ee8SDavid du Colombier 151*219b2ee8SDavid du Colombier Lextok * 152*219b2ee8SDavid du Colombier do_unless(Lextok *No, Lextok *Es) 153*219b2ee8SDavid du Colombier { SeqList *Sl; 154*219b2ee8SDavid du Colombier Lextok *Re = nn(ZN, UNLESS, ZN, ZN); 155*219b2ee8SDavid du Colombier Re->ln = No->ln; 156*219b2ee8SDavid du Colombier Re->fn = No->fn; 157*219b2ee8SDavid du Colombier 158*219b2ee8SDavid du Colombier has_unless++; 159*219b2ee8SDavid du Colombier if (Es->ntyp == NON_ATOMIC) 160*219b2ee8SDavid du Colombier Sl = Es->sl; 161*219b2ee8SDavid du Colombier else 162*219b2ee8SDavid du Colombier { open_seq(0); add_seq(Es); 163*219b2ee8SDavid du Colombier Sl = seqlist(close_seq(1), 0); 164*219b2ee8SDavid du Colombier } 165*219b2ee8SDavid du Colombier 166*219b2ee8SDavid du Colombier if (No->ntyp == NON_ATOMIC) 167*219b2ee8SDavid du Colombier { No->sl->nxt = Sl; 168*219b2ee8SDavid du Colombier Sl = No->sl; 169*219b2ee8SDavid du Colombier } else if (No->ntyp == ':' 170*219b2ee8SDavid du Colombier && (No->lft->ntyp == NON_ATOMIC 171*219b2ee8SDavid du Colombier || No->lft->ntyp == ATOMIC 172*219b2ee8SDavid du Colombier || No->lft->ntyp == D_STEP)) 173*219b2ee8SDavid du Colombier { 174*219b2ee8SDavid du Colombier int tok = No->lft->ntyp; 175*219b2ee8SDavid du Colombier 176*219b2ee8SDavid du Colombier No->lft->sl->nxt = Sl; 177*219b2ee8SDavid du Colombier Re->sl = No->lft->sl; 178*219b2ee8SDavid du Colombier 179*219b2ee8SDavid du Colombier open_seq(0); add_seq(Re); 180*219b2ee8SDavid du Colombier Re = nn(ZN, tok, ZN, ZN); 181*219b2ee8SDavid du Colombier Re->sl = seqlist(close_seq(7), 0); 182*219b2ee8SDavid du Colombier Re->ln = No->ln; 183*219b2ee8SDavid du Colombier Re->fn = No->fn; 184*219b2ee8SDavid du Colombier 185*219b2ee8SDavid du Colombier Re = nn(No, ':', Re, ZN); /* lift label */ 186*219b2ee8SDavid du Colombier Re->ln = No->ln; 187*219b2ee8SDavid du Colombier Re->fn = No->fn; 188*219b2ee8SDavid du Colombier return Re; 189*219b2ee8SDavid du Colombier } else 190*219b2ee8SDavid du Colombier { open_seq(0); add_seq(No); 191*219b2ee8SDavid du Colombier Sl = seqlist(close_seq(2), Sl); 192*219b2ee8SDavid du Colombier } 193*219b2ee8SDavid du Colombier 194*219b2ee8SDavid du Colombier Re->sl = Sl; 195*219b2ee8SDavid du Colombier return Re; 196*219b2ee8SDavid du Colombier } 197*219b2ee8SDavid du Colombier 198*219b2ee8SDavid du Colombier SeqList * 199*219b2ee8SDavid du Colombier seqlist(Sequence *s, SeqList *r) 200*219b2ee8SDavid du Colombier { SeqList *t = (SeqList *) emalloc(sizeof(SeqList)); 201*219b2ee8SDavid du Colombier 202*219b2ee8SDavid du Colombier t->this = s; 203*219b2ee8SDavid du Colombier t->nxt = r; 204*219b2ee8SDavid du Colombier return t; 205*219b2ee8SDavid du Colombier } 206*219b2ee8SDavid du Colombier 207*219b2ee8SDavid du Colombier Element * 208*219b2ee8SDavid du Colombier new_el(Lextok *n) 209*219b2ee8SDavid du Colombier { Element *m; 210*219b2ee8SDavid du Colombier 211*219b2ee8SDavid du Colombier if (n) 212*219b2ee8SDavid du Colombier { if (n->ntyp == IF || n->ntyp == DO) 213*219b2ee8SDavid du Colombier return if_seq(n); 214*219b2ee8SDavid du Colombier if (n->ntyp == UNLESS) 215*219b2ee8SDavid du Colombier return unless_seq(n); 216*219b2ee8SDavid du Colombier } 217*219b2ee8SDavid du Colombier m = (Element *) emalloc(sizeof(Element)); 218*219b2ee8SDavid du Colombier m->n = n; 219*219b2ee8SDavid du Colombier m->seqno = Elcnt++; 220*219b2ee8SDavid du Colombier m->Seqno = Unique++; 221*219b2ee8SDavid du Colombier m->Nxt = Al_El; Al_El = m; 222*219b2ee8SDavid du Colombier return m; 223*219b2ee8SDavid du Colombier } 224*219b2ee8SDavid du Colombier 225*219b2ee8SDavid du Colombier Element * 226*219b2ee8SDavid du Colombier if_seq(Lextok *n) 227*219b2ee8SDavid du Colombier { int tok = n->ntyp; 228*219b2ee8SDavid du Colombier SeqList *s = n->sl; 229*219b2ee8SDavid du Colombier Element *e = new_el(ZN); 230*219b2ee8SDavid du Colombier Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */ 231*219b2ee8SDavid du Colombier SeqList *z, *prev_z = (SeqList *) 0; 232*219b2ee8SDavid du Colombier SeqList *move_else = (SeqList *) 0; /* to end of optionlist */ 233*219b2ee8SDavid du Colombier int has_probes = 0; 234*219b2ee8SDavid du Colombier 235*219b2ee8SDavid du Colombier for (z = s; z; z = z->nxt) 236*219b2ee8SDavid du Colombier { if (z->this->frst->n->ntyp == ELSE) 237*219b2ee8SDavid du Colombier { if (move_else) 238*219b2ee8SDavid du Colombier fatal("duplicate `else'", (char *) 0); 239*219b2ee8SDavid du Colombier if (z->nxt) /* is not already at the end */ 240*219b2ee8SDavid du Colombier { move_else = z; 241*219b2ee8SDavid du Colombier if (prev_z) 242*219b2ee8SDavid du Colombier prev_z->nxt = z->nxt; 243*219b2ee8SDavid du Colombier else 244*219b2ee8SDavid du Colombier s = n->sl = z->nxt; 245*219b2ee8SDavid du Colombier continue; 246*219b2ee8SDavid du Colombier } 247*219b2ee8SDavid du Colombier } else 248*219b2ee8SDavid du Colombier { has_probes |= has_typ(z->this->frst->n, FULL); 249*219b2ee8SDavid du Colombier has_probes |= has_typ(z->this->frst->n, NFULL); 250*219b2ee8SDavid du Colombier has_probes |= has_typ(z->this->frst->n, EMPTY); 251*219b2ee8SDavid du Colombier has_probes |= has_typ(z->this->frst->n, NEMPTY); 252*219b2ee8SDavid du Colombier } 253*219b2ee8SDavid du Colombier prev_z = z; 254*219b2ee8SDavid du Colombier } 255*219b2ee8SDavid du Colombier if (move_else) 256*219b2ee8SDavid du Colombier { move_else->nxt = (SeqList *) 0; 257*219b2ee8SDavid du Colombier /* if there is no prev, then else was at the end */ 258*219b2ee8SDavid du Colombier if (!prev_z) fatal("cannot happen - if_seq", (char *) 0); 259*219b2ee8SDavid du Colombier prev_z->nxt = move_else; 260*219b2ee8SDavid du Colombier prev_z = move_else; 261*219b2ee8SDavid du Colombier } 262*219b2ee8SDavid du Colombier if (prev_z 263*219b2ee8SDavid du Colombier && has_probes 264*219b2ee8SDavid du Colombier && prev_z->this->frst->n->ntyp == ELSE) 265*219b2ee8SDavid du Colombier prev_z->this->frst->n->val = 1; 266*219b2ee8SDavid du Colombier 267*219b2ee8SDavid du Colombier e->n = nn(n, tok, ZN, ZN); 268*219b2ee8SDavid du Colombier e->n->sl = s; /* preserve as info only */ 269*219b2ee8SDavid du Colombier e->sub = s; 270*219b2ee8SDavid du Colombier for (z = s; z; prev_z = z, z = z->nxt) 271*219b2ee8SDavid du Colombier add_el(t, z->this); /* append target */ 272*219b2ee8SDavid du Colombier if (tok == DO) 273*219b2ee8SDavid du Colombier { add_el(t, cur_s->this); /* target upfront */ 274*219b2ee8SDavid du Colombier t = new_el(nn(n, BREAK, ZN, ZN)); /* break target */ 275*219b2ee8SDavid du Colombier set_lab(break_dest(), t); /* new exit */ 276*219b2ee8SDavid du Colombier breakstack = breakstack->nxt; /* pop stack */ 277*219b2ee8SDavid du Colombier } 278*219b2ee8SDavid du Colombier add_el(e, cur_s->this); 279*219b2ee8SDavid du Colombier add_el(t, cur_s->this); 280*219b2ee8SDavid du Colombier return e; /* destination node for label */ 281*219b2ee8SDavid du Colombier } 282*219b2ee8SDavid du Colombier 283*219b2ee8SDavid du Colombier void 284*219b2ee8SDavid du Colombier attach_escape(Sequence *n, Sequence *e) 285*219b2ee8SDavid du Colombier { Element *f; SeqList *z; 286*219b2ee8SDavid du Colombier 287*219b2ee8SDavid du Colombier for (f = n->frst; f; f = f->nxt) 288*219b2ee8SDavid du Colombier { f->esc = seqlist(e, f->esc); /* but, this is lifo order... */ 289*219b2ee8SDavid du Colombier #ifdef DEBUG 290*219b2ee8SDavid du Colombier printf("attach %d (", e->frst->Seqno); 291*219b2ee8SDavid du Colombier comment(stdout, e->frst->n, 0); 292*219b2ee8SDavid du Colombier printf(") to %d (", f->Seqno); 293*219b2ee8SDavid du Colombier comment(stdout, f->n, 0); 294*219b2ee8SDavid du Colombier printf(")\n"); 295*219b2ee8SDavid du Colombier #endif 296*219b2ee8SDavid du Colombier if (f->n->ntyp == UNLESS) 297*219b2ee8SDavid du Colombier { attach_escape(f->sub->this, e); 298*219b2ee8SDavid du Colombier } else 299*219b2ee8SDavid du Colombier if (f->n->ntyp == IF 300*219b2ee8SDavid du Colombier || f->n->ntyp == DO) 301*219b2ee8SDavid du Colombier { for (z = f->sub; z; z = z->nxt) 302*219b2ee8SDavid du Colombier attach_escape(z->this, e); 303*219b2ee8SDavid du Colombier } else 304*219b2ee8SDavid du Colombier if (f->n->ntyp == ATOMIC 305*219b2ee8SDavid du Colombier || f->n->ntyp == D_STEP 306*219b2ee8SDavid du Colombier || f->n->ntyp == NON_ATOMIC) 307*219b2ee8SDavid du Colombier { attach_escape(f->n->sl->this, e); 308*219b2ee8SDavid du Colombier } 309*219b2ee8SDavid du Colombier if (f == n->extent) break; 310*219b2ee8SDavid du Colombier } 311*219b2ee8SDavid du Colombier } 312*219b2ee8SDavid du Colombier 313*219b2ee8SDavid du Colombier Element * 314*219b2ee8SDavid du Colombier unless_seq(Lextok *n) 315*219b2ee8SDavid du Colombier { SeqList *s = n->sl; 316*219b2ee8SDavid du Colombier Element *e = new_el(ZN); 317*219b2ee8SDavid du Colombier Element *t = new_el(nn(ZN,'.',ZN,ZN)); /* target */ 318*219b2ee8SDavid du Colombier SeqList *z; 319*219b2ee8SDavid du Colombier 320*219b2ee8SDavid du Colombier e->n = nn(n, UNLESS, ZN, ZN); 321*219b2ee8SDavid du Colombier e->n->sl = s; /* info only */ 322*219b2ee8SDavid du Colombier e->sub = s; 323*219b2ee8SDavid du Colombier 324*219b2ee8SDavid du Colombier /* 325*219b2ee8SDavid du Colombier * check that there are precisely two sequences: 326*219b2ee8SDavid du Colombier * the normal execution and the escape. 327*219b2ee8SDavid du Colombier */ 328*219b2ee8SDavid du Colombier if (!s || !s->nxt || s->nxt->nxt) 329*219b2ee8SDavid du Colombier fatal("unexpected unless structure", (char *)0); 330*219b2ee8SDavid du Colombier /* 331*219b2ee8SDavid du Colombier * append the target state to both 332*219b2ee8SDavid du Colombier */ 333*219b2ee8SDavid du Colombier for (z = s; z; z = z->nxt) 334*219b2ee8SDavid du Colombier add_el(t, z->this); 335*219b2ee8SDavid du Colombier /* 336*219b2ee8SDavid du Colombier * distributed the escape sequence over all states in 337*219b2ee8SDavid du Colombier * the normal execution sequence 338*219b2ee8SDavid du Colombier */ 339*219b2ee8SDavid du Colombier attach_escape(s->this, s->nxt->this); 340*219b2ee8SDavid du Colombier 341*219b2ee8SDavid du Colombier add_el(e, cur_s->this); 342*219b2ee8SDavid du Colombier add_el(t, cur_s->this); 343*219b2ee8SDavid du Colombier #ifdef DEBUG 344*219b2ee8SDavid du Colombier printf("unless element (%d,%d):\n", e->Seqno, t->Seqno); 345*219b2ee8SDavid du Colombier for (z = s; z; z = z->nxt) 346*219b2ee8SDavid du Colombier { Element *x; printf("\t%d,%d,%d :: ", 347*219b2ee8SDavid du Colombier z->this->frst->Seqno, 348*219b2ee8SDavid du Colombier z->this->extent->Seqno, 349*219b2ee8SDavid du Colombier z->this->last->Seqno); 350*219b2ee8SDavid du Colombier for (x = z->this->frst; x; x = x->nxt) 351*219b2ee8SDavid du Colombier printf("(%d)", x->Seqno); 352*219b2ee8SDavid du Colombier printf("\n"); 353*219b2ee8SDavid du Colombier } 354*219b2ee8SDavid du Colombier #endif 355*219b2ee8SDavid du Colombier return e; 356*219b2ee8SDavid du Colombier } 357*219b2ee8SDavid du Colombier 358*219b2ee8SDavid du Colombier Element * 359*219b2ee8SDavid du Colombier mk_skip(void) 360*219b2ee8SDavid du Colombier { Lextok *t = nn(ZN, CONST, ZN, ZN); 361*219b2ee8SDavid du Colombier t->val = 1; 362*219b2ee8SDavid du Colombier return new_el(nn(ZN, 'c', t, ZN)); 363*219b2ee8SDavid du Colombier } 364*219b2ee8SDavid du Colombier 365*219b2ee8SDavid du Colombier void 366*219b2ee8SDavid du Colombier add_el(Element *e, Sequence *s) 367*219b2ee8SDavid du Colombier { 368*219b2ee8SDavid du Colombier if (e->n->ntyp == GOTO) 369*219b2ee8SDavid du Colombier { Symbol *z; 370*219b2ee8SDavid du Colombier if ((z = has_lab(e)) 371*219b2ee8SDavid du Colombier && (strncmp(z->name, "progress", 8) == 0 372*219b2ee8SDavid du Colombier || strncmp(z->name, "accept", 6) == 0 373*219b2ee8SDavid du Colombier || strncmp(z->name, "end", 3) == 0)) 374*219b2ee8SDavid du Colombier { Element *y; /* insert a skip */ 375*219b2ee8SDavid du Colombier y = mk_skip(); 376*219b2ee8SDavid du Colombier mov_lab(z, e, y); /* inherit label */ 377*219b2ee8SDavid du Colombier add_el(y, s); 378*219b2ee8SDavid du Colombier } } 379*219b2ee8SDavid du Colombier #ifdef DEBUG 380*219b2ee8SDavid du Colombier printf("add_el %d after %d -- ", 381*219b2ee8SDavid du Colombier e->Seqno, (s->last)?s->last->Seqno:-1); 382*219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 383*219b2ee8SDavid du Colombier printf("\n"); 384*219b2ee8SDavid du Colombier #endif 385*219b2ee8SDavid du Colombier if (!s->frst) 386*219b2ee8SDavid du Colombier s->frst = e; 387*219b2ee8SDavid du Colombier else 388*219b2ee8SDavid du Colombier s->last->nxt = e; 389*219b2ee8SDavid du Colombier s->last = e; 390*219b2ee8SDavid du Colombier } 391*219b2ee8SDavid du Colombier 392*219b2ee8SDavid du Colombier Element * 393*219b2ee8SDavid du Colombier colons(Lextok *n) 394*219b2ee8SDavid du Colombier { 395*219b2ee8SDavid du Colombier if (!n) 396*219b2ee8SDavid du Colombier return ZE; 397*219b2ee8SDavid du Colombier if (n->ntyp == ':') 398*219b2ee8SDavid du Colombier { Element *e = colons(n->lft); 399*219b2ee8SDavid du Colombier set_lab(n->sym, e); 400*219b2ee8SDavid du Colombier return e; 401*219b2ee8SDavid du Colombier } 402*219b2ee8SDavid du Colombier innermost = n; 403*219b2ee8SDavid du Colombier return new_el(n); 404*219b2ee8SDavid du Colombier } 405*219b2ee8SDavid du Colombier 406*219b2ee8SDavid du Colombier void 407*219b2ee8SDavid du Colombier add_seq(Lextok *n) 408*219b2ee8SDavid du Colombier { Element *e; 409*219b2ee8SDavid du Colombier 410*219b2ee8SDavid du Colombier if (!n) return; 411*219b2ee8SDavid du Colombier innermost = n; 412*219b2ee8SDavid du Colombier e = colons(n); 413*219b2ee8SDavid du Colombier if (innermost->ntyp != IF 414*219b2ee8SDavid du Colombier && innermost->ntyp != DO 415*219b2ee8SDavid du Colombier && innermost->ntyp != UNLESS) 416*219b2ee8SDavid du Colombier add_el(e, cur_s->this); 417*219b2ee8SDavid du Colombier } 418*219b2ee8SDavid du Colombier 419*219b2ee8SDavid du Colombier void 420*219b2ee8SDavid du Colombier set_lab(Symbol *s, Element *e) 421*219b2ee8SDavid du Colombier { Label *l; extern Symbol *context; 422*219b2ee8SDavid du Colombier 423*219b2ee8SDavid du Colombier if (!s) return; 424*219b2ee8SDavid du Colombier l = (Label *) emalloc(sizeof(Label)); 425*219b2ee8SDavid du Colombier l->s = s; 426*219b2ee8SDavid du Colombier l->c = context; 427*219b2ee8SDavid du Colombier l->e = e; 428*219b2ee8SDavid du Colombier l->nxt = labtab; 429*219b2ee8SDavid du Colombier labtab = l; 430*219b2ee8SDavid du Colombier } 431*219b2ee8SDavid du Colombier 432*219b2ee8SDavid du Colombier Element * 433*219b2ee8SDavid du Colombier get_lab(Lextok *n, int md) 434*219b2ee8SDavid du Colombier { Label *l; 435*219b2ee8SDavid du Colombier Symbol *s = n->sym; 436*219b2ee8SDavid du Colombier 437*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 438*219b2ee8SDavid du Colombier if (s == l->s) 439*219b2ee8SDavid du Colombier return (l->e); 440*219b2ee8SDavid du Colombier lineno = n->ln; 441*219b2ee8SDavid du Colombier Fname = n->fn; 442*219b2ee8SDavid du Colombier if (md) fatal("undefined label %s", s->name); 443*219b2ee8SDavid du Colombier return ZE; 444*219b2ee8SDavid du Colombier } 445*219b2ee8SDavid du Colombier 446*219b2ee8SDavid du Colombier Symbol * 447*219b2ee8SDavid du Colombier has_lab(Element *e) 448*219b2ee8SDavid du Colombier { Label *l; 449*219b2ee8SDavid du Colombier 450*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 451*219b2ee8SDavid du Colombier if (e == l->e) 452*219b2ee8SDavid du Colombier return (l->s); 453*219b2ee8SDavid du Colombier return ZS; 454*219b2ee8SDavid du Colombier } 455*219b2ee8SDavid du Colombier 456*219b2ee8SDavid du Colombier void 457*219b2ee8SDavid du Colombier mov_lab(Symbol *z, Element *e, Element *y) 458*219b2ee8SDavid du Colombier { Label *l; 459*219b2ee8SDavid du Colombier 460*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 461*219b2ee8SDavid du Colombier if (e == l->e) 462*219b2ee8SDavid du Colombier { l->e = y; 463*219b2ee8SDavid du Colombier return; 464*219b2ee8SDavid du Colombier } 465*219b2ee8SDavid du Colombier if (e->n) 466*219b2ee8SDavid du Colombier { lineno = e->n->ln; 467*219b2ee8SDavid du Colombier Fname = e->n->fn; 468*219b2ee8SDavid du Colombier } 469*219b2ee8SDavid du Colombier fatal("cannot happen - mov_lab %s", z->name); 470*219b2ee8SDavid du Colombier } 471*219b2ee8SDavid du Colombier 472*219b2ee8SDavid du Colombier void 473*219b2ee8SDavid du Colombier fix_dest(Symbol *c, Symbol *a) /* label, proctype */ 474*219b2ee8SDavid du Colombier { Label *l; 475*219b2ee8SDavid du Colombier 476*219b2ee8SDavid du Colombier 477*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 478*219b2ee8SDavid du Colombier { if (strcmp(c->name, l->s->name) == 0 479*219b2ee8SDavid du Colombier && strcmp(a->name, l->c->name) == 0) 480*219b2ee8SDavid du Colombier break; 481*219b2ee8SDavid du Colombier } 482*219b2ee8SDavid du Colombier 483*219b2ee8SDavid du Colombier if (!l) 484*219b2ee8SDavid du Colombier { non_fatal("unknown label '%s'", c->name); 485*219b2ee8SDavid du Colombier return; 486*219b2ee8SDavid du Colombier } 487*219b2ee8SDavid du Colombier if (!l->e || !l->e->n) 488*219b2ee8SDavid du Colombier fatal("fix_dest error (%s)", c->name); 489*219b2ee8SDavid du Colombier if (l->e->n->ntyp == GOTO) 490*219b2ee8SDavid du Colombier { Element *y = (Element *) emalloc(sizeof(Element)); 491*219b2ee8SDavid du Colombier int keep_ln = l->e->n->ln; 492*219b2ee8SDavid du Colombier Symbol *keep_fn = l->e->n->fn; 493*219b2ee8SDavid du Colombier 494*219b2ee8SDavid du Colombier /* insert skip - or target is optimized away */ 495*219b2ee8SDavid du Colombier y->n = l->e->n; /* copy of the goto */ 496*219b2ee8SDavid du Colombier y->seqno = find_maxel(a); /* unique seqno within proc */ 497*219b2ee8SDavid du Colombier y->nxt = l->e->nxt; 498*219b2ee8SDavid du Colombier y->Seqno = Unique++; y->Nxt = Al_El; Al_El = y; 499*219b2ee8SDavid du Colombier 500*219b2ee8SDavid du Colombier /* turn the original element+seqno into a skip */ 501*219b2ee8SDavid du Colombier l->e->n = nn(ZN, 'c', nn(ZN, CONST, ZN, ZN), ZN); 502*219b2ee8SDavid du Colombier l->e->n->ln = l->e->n->lft->ln = keep_ln; 503*219b2ee8SDavid du Colombier l->e->n->fn = l->e->n->lft->fn = keep_fn; 504*219b2ee8SDavid du Colombier l->e->n->lft->val = 1; 505*219b2ee8SDavid du Colombier l->e->nxt = y; /* append the goto */ 506*219b2ee8SDavid du Colombier } 507*219b2ee8SDavid du Colombier } 508*219b2ee8SDavid du Colombier 509*219b2ee8SDavid du Colombier int 510*219b2ee8SDavid du Colombier find_lab(Symbol *s, Symbol *c) 511*219b2ee8SDavid du Colombier { Label *l; 512*219b2ee8SDavid du Colombier 513*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 514*219b2ee8SDavid du Colombier { if (strcmp(s->name, l->s->name) == 0 515*219b2ee8SDavid du Colombier && strcmp(c->name, l->c->name) == 0) 516*219b2ee8SDavid du Colombier return (l->e->seqno); 517*219b2ee8SDavid du Colombier } 518*219b2ee8SDavid du Colombier return 0; 519*219b2ee8SDavid du Colombier } 520*219b2ee8SDavid du Colombier 521*219b2ee8SDavid du Colombier void 522*219b2ee8SDavid du Colombier pushbreak(void) 523*219b2ee8SDavid du Colombier { Lbreak *r = (Lbreak *) emalloc(sizeof(Lbreak)); 524*219b2ee8SDavid du Colombier Symbol *l; 525*219b2ee8SDavid du Colombier char buf[32]; 526*219b2ee8SDavid du Colombier 527*219b2ee8SDavid du Colombier sprintf(buf, ":b%d", break_id++); 528*219b2ee8SDavid du Colombier l = lookup(buf); 529*219b2ee8SDavid du Colombier r->l = l; 530*219b2ee8SDavid du Colombier r->nxt = breakstack; 531*219b2ee8SDavid du Colombier breakstack = r; 532*219b2ee8SDavid du Colombier } 533*219b2ee8SDavid du Colombier 534*219b2ee8SDavid du Colombier Symbol * 535*219b2ee8SDavid du Colombier break_dest(void) 536*219b2ee8SDavid du Colombier { 537*219b2ee8SDavid du Colombier if (!breakstack) 538*219b2ee8SDavid du Colombier fatal("misplaced break statement", (char *)0); 539*219b2ee8SDavid du Colombier return breakstack->l; 540*219b2ee8SDavid du Colombier } 541*219b2ee8SDavid du Colombier 542*219b2ee8SDavid du Colombier void 543*219b2ee8SDavid du Colombier make_atomic(Sequence *s, int added) 544*219b2ee8SDavid du Colombier { 545*219b2ee8SDavid du Colombier walk_atomic(s->frst, s->last, added); 546*219b2ee8SDavid du Colombier s->last->status &= ~ATOM; 547*219b2ee8SDavid du Colombier s->last->status |= L_ATOM; 548*219b2ee8SDavid du Colombier } 549*219b2ee8SDavid du Colombier 550*219b2ee8SDavid du Colombier void 551*219b2ee8SDavid du Colombier walk_atomic(Element *a, Element *b, int added) 552*219b2ee8SDavid du Colombier { Element *f; 553*219b2ee8SDavid du Colombier SeqList *h; 554*219b2ee8SDavid du Colombier char *str = (added)?"d_step":"atomic"; 555*219b2ee8SDavid du Colombier 556*219b2ee8SDavid du Colombier for (f = a; ; f = f->nxt) 557*219b2ee8SDavid du Colombier { f->status |= (ATOM|added); 558*219b2ee8SDavid du Colombier switch (f->n->ntyp) { 559*219b2ee8SDavid du Colombier case ATOMIC: 560*219b2ee8SDavid du Colombier lineno = f->n->ln; 561*219b2ee8SDavid du Colombier Fname = f->n->fn; 562*219b2ee8SDavid du Colombier non_fatal("atomic inside %s", str); 563*219b2ee8SDavid du Colombier break; 564*219b2ee8SDavid du Colombier case D_STEP: 565*219b2ee8SDavid du Colombier lineno = f->n->ln; 566*219b2ee8SDavid du Colombier Fname = f->n->fn; 567*219b2ee8SDavid du Colombier non_fatal("d_step inside %s", str); 568*219b2ee8SDavid du Colombier break; 569*219b2ee8SDavid du Colombier case NON_ATOMIC: 570*219b2ee8SDavid du Colombier h = f->n->sl; 571*219b2ee8SDavid du Colombier walk_atomic(h->this->frst, h->this->last, added); 572*219b2ee8SDavid du Colombier break; 573*219b2ee8SDavid du Colombier } 574*219b2ee8SDavid du Colombier 575*219b2ee8SDavid du Colombier for (h = f->sub; h; h = h->nxt) 576*219b2ee8SDavid du Colombier walk_atomic(h->this->frst, h->this->last, added); 577*219b2ee8SDavid du Colombier if (f == b) 578*219b2ee8SDavid du Colombier break; 579*219b2ee8SDavid du Colombier } 580*219b2ee8SDavid du Colombier } 581*219b2ee8SDavid du Colombier 582*219b2ee8SDavid du Colombier void 583*219b2ee8SDavid du Colombier dumplabels(void) 584*219b2ee8SDavid du Colombier { Label *l; 585*219b2ee8SDavid du Colombier 586*219b2ee8SDavid du Colombier for (l = labtab; l; l = l->nxt) 587*219b2ee8SDavid du Colombier if (l->c != 0 && l->s->name[0] != ':') 588*219b2ee8SDavid du Colombier printf("label %s %d <%s>\n", 589*219b2ee8SDavid du Colombier l->s->name, l->e->seqno, l->c->name); 590*219b2ee8SDavid du Colombier } 591