1*219b2ee8SDavid du Colombier /***** spin: dstep.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 char *NextLab[64]; 17*219b2ee8SDavid du Colombier int Level=0, GenCode=0, IsGuard=0, TestOnly=0; 18*219b2ee8SDavid du Colombier int Tj=0, Jt=0, LastGoto=0; 19*219b2ee8SDavid du Colombier int Tojump[512], Jumpto[512], Special[512]; 20*219b2ee8SDavid du Colombier 21*219b2ee8SDavid du Colombier void 22*219b2ee8SDavid du Colombier Sourced(int n, int special) 23*219b2ee8SDavid du Colombier { int i; 24*219b2ee8SDavid du Colombier for (i = 0; i < Tj; i++) 25*219b2ee8SDavid du Colombier if (Tojump[i] == n) 26*219b2ee8SDavid du Colombier return; 27*219b2ee8SDavid du Colombier Special[Tj] = special; 28*219b2ee8SDavid du Colombier Tojump[Tj++] = n; 29*219b2ee8SDavid du Colombier } 30*219b2ee8SDavid du Colombier 31*219b2ee8SDavid du Colombier void 32*219b2ee8SDavid du Colombier Dested(int n) 33*219b2ee8SDavid du Colombier { int i; 34*219b2ee8SDavid du Colombier 35*219b2ee8SDavid du Colombier LastGoto = 1; 36*219b2ee8SDavid du Colombier for (i = 0; i < Tj; i++) 37*219b2ee8SDavid du Colombier if (Tojump[i] == n) 38*219b2ee8SDavid du Colombier return; 39*219b2ee8SDavid du Colombier for (i = 0; i < Jt; i++) 40*219b2ee8SDavid du Colombier if (Jumpto[i] == n) 41*219b2ee8SDavid du Colombier return; 42*219b2ee8SDavid du Colombier Jumpto[Jt++] = n; 43*219b2ee8SDavid du Colombier } 44*219b2ee8SDavid du Colombier 45*219b2ee8SDavid du Colombier void 46*219b2ee8SDavid du Colombier Mopup(FILE *fd) 47*219b2ee8SDavid du Colombier { int i, j; 48*219b2ee8SDavid du Colombier for (i = 0; i < Jt; i++) 49*219b2ee8SDavid du Colombier { for (j = 0; j < Tj; j++) 50*219b2ee8SDavid du Colombier { if (Tojump[j] == Jumpto[i]) 51*219b2ee8SDavid du Colombier break; 52*219b2ee8SDavid du Colombier } 53*219b2ee8SDavid du Colombier if (j == Tj) 54*219b2ee8SDavid du Colombier { char buf[12]; 55*219b2ee8SDavid du Colombier sprintf(buf, "S_%.3d_0", Jumpto[i]); 56*219b2ee8SDavid du Colombier non_fatal("goto %s breaks from d_step seq", buf); 57*219b2ee8SDavid du Colombier } } 58*219b2ee8SDavid du Colombier for (j = 0; j < Tj; j++) 59*219b2ee8SDavid du Colombier { for (i = 0; i < Jt; i++) 60*219b2ee8SDavid du Colombier { if (Tojump[j] == Jumpto[i]) 61*219b2ee8SDavid du Colombier break; 62*219b2ee8SDavid du Colombier } 63*219b2ee8SDavid du Colombier #ifdef DEBUG 64*219b2ee8SDavid du Colombier if (i == Jt && !Special[i]) 65*219b2ee8SDavid du Colombier { fprintf(fd, "\t\t/* >>no goto's for S_%.3d_0<< */\n", 66*219b2ee8SDavid du Colombier Tojump[j]); 67*219b2ee8SDavid du Colombier } 68*219b2ee8SDavid du Colombier #endif 69*219b2ee8SDavid du Colombier } 70*219b2ee8SDavid du Colombier for (j = i = 0; j < Tj; j++) 71*219b2ee8SDavid du Colombier { if (Special[j]) 72*219b2ee8SDavid du Colombier { Tojump[i] = Tojump[j]; 73*219b2ee8SDavid du Colombier Special[i] = 2; 74*219b2ee8SDavid du Colombier i++; 75*219b2ee8SDavid du Colombier } } 76*219b2ee8SDavid du Colombier Tj = i; /* keep only the global exit-labels */ 77*219b2ee8SDavid du Colombier Jt = 0; 78*219b2ee8SDavid du Colombier } 79*219b2ee8SDavid du Colombier 80*219b2ee8SDavid du Colombier int 81*219b2ee8SDavid du Colombier FirstTime(int n) 82*219b2ee8SDavid du Colombier { int i; 83*219b2ee8SDavid du Colombier for (i = 0; i < Tj; i++) 84*219b2ee8SDavid du Colombier if (Tojump[i] == n) 85*219b2ee8SDavid du Colombier return (Special[i] <= 1); 86*219b2ee8SDavid du Colombier return 1; 87*219b2ee8SDavid du Colombier } 88*219b2ee8SDavid du Colombier 89*219b2ee8SDavid du Colombier void 90*219b2ee8SDavid du Colombier illegal(Element *e, char *str) 91*219b2ee8SDavid du Colombier { 92*219b2ee8SDavid du Colombier printf("illegal operator in 'step:' '"); 93*219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 94*219b2ee8SDavid du Colombier printf("'\n"); 95*219b2ee8SDavid du Colombier fatal("saw %s", str); 96*219b2ee8SDavid du Colombier } 97*219b2ee8SDavid du Colombier 98*219b2ee8SDavid du Colombier void 99*219b2ee8SDavid du Colombier filterbad(Element *e) 100*219b2ee8SDavid du Colombier { 101*219b2ee8SDavid du Colombier switch (e->n->ntyp) { 102*219b2ee8SDavid du Colombier case ASSERT: 103*219b2ee8SDavid du Colombier case PRINT: 104*219b2ee8SDavid du Colombier case 'c': 105*219b2ee8SDavid du Colombier /* run cannot be completely undone 106*219b2ee8SDavid du Colombier * with sv_save-sv_restor 107*219b2ee8SDavid du Colombier */ 108*219b2ee8SDavid du Colombier if (any_oper(e->n->lft, RUN)) 109*219b2ee8SDavid du Colombier illegal(e, "run operator"); 110*219b2ee8SDavid du Colombier break; 111*219b2ee8SDavid du Colombier case '@': 112*219b2ee8SDavid du Colombier illegal(e, "process termination"); 113*219b2ee8SDavid du Colombier break; 114*219b2ee8SDavid du Colombier case D_STEP: 115*219b2ee8SDavid du Colombier illegal(e, "nested d_step sequence"); 116*219b2ee8SDavid du Colombier break; 117*219b2ee8SDavid du Colombier case ATOMIC: 118*219b2ee8SDavid du Colombier illegal(e, "nested atomic sequence"); 119*219b2ee8SDavid du Colombier break; 120*219b2ee8SDavid du Colombier default: 121*219b2ee8SDavid du Colombier break; 122*219b2ee8SDavid du Colombier } 123*219b2ee8SDavid du Colombier } 124*219b2ee8SDavid du Colombier 125*219b2ee8SDavid du Colombier int 126*219b2ee8SDavid du Colombier CollectGuards(FILE *fd, Element *e, int inh) 127*219b2ee8SDavid du Colombier { SeqList *h; Element *ee; 128*219b2ee8SDavid du Colombier 129*219b2ee8SDavid du Colombier for (h = e->sub; h; h = h->nxt) 130*219b2ee8SDavid du Colombier { ee = huntstart(h->this->frst); 131*219b2ee8SDavid du Colombier filterbad(ee); 132*219b2ee8SDavid du Colombier switch (ee->n->ntyp) { 133*219b2ee8SDavid du Colombier case IF: 134*219b2ee8SDavid du Colombier inh += CollectGuards(fd, ee, inh); 135*219b2ee8SDavid du Colombier break; 136*219b2ee8SDavid du Colombier case '.': 137*219b2ee8SDavid du Colombier if (ee->nxt->n->ntyp == DO) 138*219b2ee8SDavid du Colombier inh += CollectGuards(fd, ee->nxt, inh); 139*219b2ee8SDavid du Colombier break; 140*219b2ee8SDavid du Colombier case ELSE: 141*219b2ee8SDavid du Colombier if (inh++ > 0) fprintf(fd, " || "); 142*219b2ee8SDavid du Colombier fprintf(fd, "(1 /* else */)"); 143*219b2ee8SDavid du Colombier break; 144*219b2ee8SDavid du Colombier case 'c': 145*219b2ee8SDavid du Colombier if (inh++ > 0) fprintf(fd, " || "); 146*219b2ee8SDavid du Colombier fprintf(fd, "("); TestOnly=1; 147*219b2ee8SDavid du Colombier putstmnt(fd, ee->n->lft, e->seqno); 148*219b2ee8SDavid du Colombier fprintf(fd, ")"); TestOnly=0; 149*219b2ee8SDavid du Colombier break; 150*219b2ee8SDavid du Colombier } 151*219b2ee8SDavid du Colombier } 152*219b2ee8SDavid du Colombier return inh; 153*219b2ee8SDavid du Colombier } 154*219b2ee8SDavid du Colombier 155*219b2ee8SDavid du Colombier int 156*219b2ee8SDavid du Colombier putcode(FILE *fd, Sequence *s, Element *nxt, int justguards) 157*219b2ee8SDavid du Colombier { int isg=0; 158*219b2ee8SDavid du Colombier 159*219b2ee8SDavid du Colombier NextLab[0] = "continue"; 160*219b2ee8SDavid du Colombier 161*219b2ee8SDavid du Colombier filterbad(s->frst); 162*219b2ee8SDavid du Colombier 163*219b2ee8SDavid du Colombier switch (s->frst->n->ntyp) { 164*219b2ee8SDavid du Colombier case UNLESS: 165*219b2ee8SDavid du Colombier non_fatal("'unless' inside d_step - ignored", (char *) 0); 166*219b2ee8SDavid du Colombier return putcode(fd, s->frst->n->sl->this, nxt, 0); 167*219b2ee8SDavid du Colombier case NON_ATOMIC: 168*219b2ee8SDavid du Colombier (void) putcode(fd, s->frst->n->sl->this, ZE, 1); 169*219b2ee8SDavid du Colombier break; 170*219b2ee8SDavid du Colombier case IF: 171*219b2ee8SDavid du Colombier fprintf(fd, "if (!("); 172*219b2ee8SDavid du Colombier if (!CollectGuards(fd, s->frst, 0)) 173*219b2ee8SDavid du Colombier fprintf(fd, "1"); 174*219b2ee8SDavid du Colombier fprintf(fd, "))\n\t\t\tcontinue;"); 175*219b2ee8SDavid du Colombier isg = 1; 176*219b2ee8SDavid du Colombier break; 177*219b2ee8SDavid du Colombier case '.': 178*219b2ee8SDavid du Colombier if (s->frst->nxt->n->ntyp == DO) 179*219b2ee8SDavid du Colombier { fprintf(fd, "if (!("); 180*219b2ee8SDavid du Colombier if (!CollectGuards(fd, s->frst->nxt, 0)) 181*219b2ee8SDavid du Colombier fprintf(fd, "1"); 182*219b2ee8SDavid du Colombier fprintf(fd, "))\n\t\t\tcontinue;"); 183*219b2ee8SDavid du Colombier isg = 1; 184*219b2ee8SDavid du Colombier } 185*219b2ee8SDavid du Colombier break; 186*219b2ee8SDavid du Colombier case 'R': 187*219b2ee8SDavid du Colombier case 'r': 188*219b2ee8SDavid du Colombier case 's': 189*219b2ee8SDavid du Colombier fprintf(fd, "if (!("); TestOnly=1; 190*219b2ee8SDavid du Colombier putstmnt(fd, s->frst->n, s->frst->seqno); 191*219b2ee8SDavid du Colombier fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0; 192*219b2ee8SDavid du Colombier break; 193*219b2ee8SDavid du Colombier case 'c': 194*219b2ee8SDavid du Colombier fprintf(fd, "if (!("); TestOnly=1; 195*219b2ee8SDavid du Colombier putstmnt(fd, s->frst->n->lft, s->frst->seqno); 196*219b2ee8SDavid du Colombier fprintf(fd, "))\n\t\t\tcontinue;"); TestOnly=0; 197*219b2ee8SDavid du Colombier break; 198*219b2ee8SDavid du Colombier } 199*219b2ee8SDavid du Colombier if (justguards) return 0; 200*219b2ee8SDavid du Colombier 201*219b2ee8SDavid du Colombier fprintf(fd, "\n#if defined(FULLSTACK) && defined(NOCOMP)\n"); 202*219b2ee8SDavid du Colombier fprintf(fd, "\t\tif (t->atom&2)\n"); 203*219b2ee8SDavid du Colombier fprintf(fd, "#endif\n"); 204*219b2ee8SDavid du Colombier fprintf(fd, "\t\tsv_save((char *)&now);\n"); 205*219b2ee8SDavid du Colombier putCode(fd, s->frst, s->extent, nxt, isg); 206*219b2ee8SDavid du Colombier 207*219b2ee8SDavid du Colombier if (nxt) 208*219b2ee8SDavid du Colombier { if (FirstTime(nxt->Seqno) 209*219b2ee8SDavid du Colombier && (!(nxt->status & DONE2) || !(nxt->status & D_ATOM))) 210*219b2ee8SDavid du Colombier { fprintf(fd, "S_%.3d_0: /* 1 */\n", nxt->Seqno); 211*219b2ee8SDavid du Colombier nxt->status |= DONE2; 212*219b2ee8SDavid du Colombier LastGoto = 0; 213*219b2ee8SDavid du Colombier } 214*219b2ee8SDavid du Colombier Sourced(nxt->Seqno, 1); 215*219b2ee8SDavid du Colombier Mopup(fd); 216*219b2ee8SDavid du Colombier } 217*219b2ee8SDavid du Colombier unskip(s->frst->seqno); 218*219b2ee8SDavid du Colombier return LastGoto; 219*219b2ee8SDavid du Colombier } 220*219b2ee8SDavid du Colombier 221*219b2ee8SDavid du Colombier void 222*219b2ee8SDavid du Colombier putCode(FILE *fd, Element *f, Element *last, Element *next, int isguard) 223*219b2ee8SDavid du Colombier { Element *e, *N; 224*219b2ee8SDavid du Colombier SeqList *h; int i; 225*219b2ee8SDavid du Colombier char NextOpt[32]; 226*219b2ee8SDavid du Colombier 227*219b2ee8SDavid du Colombier for (e = f; e; e = e->nxt) 228*219b2ee8SDavid du Colombier { if (e->status & DONE2) 229*219b2ee8SDavid du Colombier continue; 230*219b2ee8SDavid du Colombier e->status |= DONE2; 231*219b2ee8SDavid du Colombier 232*219b2ee8SDavid du Colombier if (!(e->status & D_ATOM)) 233*219b2ee8SDavid du Colombier { if (!LastGoto) 234*219b2ee8SDavid du Colombier { fprintf(fd, "\t\tgoto S_%.3d_0;\n", e->Seqno); 235*219b2ee8SDavid du Colombier Dested(e->Seqno); 236*219b2ee8SDavid du Colombier } 237*219b2ee8SDavid du Colombier break; 238*219b2ee8SDavid du Colombier } 239*219b2ee8SDavid du Colombier fprintf(fd, "S_%.3d_0: /* 2 */\n", e->Seqno); 240*219b2ee8SDavid du Colombier Sourced(e->Seqno, 0); 241*219b2ee8SDavid du Colombier 242*219b2ee8SDavid du Colombier if (!e->sub) 243*219b2ee8SDavid du Colombier { filterbad(e); 244*219b2ee8SDavid du Colombier switch (e->n->ntyp) { 245*219b2ee8SDavid du Colombier case NON_ATOMIC: 246*219b2ee8SDavid du Colombier h = e->n->sl; 247*219b2ee8SDavid du Colombier putCode(fd, h->this->frst, h->this->extent, e->nxt, 0); 248*219b2ee8SDavid du Colombier break; 249*219b2ee8SDavid du Colombier case BREAK: 250*219b2ee8SDavid du Colombier if (LastGoto) break; 251*219b2ee8SDavid du Colombier i = target(huntele(e->nxt, e->status))->Seqno; 252*219b2ee8SDavid du Colombier fprintf(fd, "\t\tgoto S_%.3d_0; /* 'break' */\n", i); 253*219b2ee8SDavid du Colombier Dested(i); 254*219b2ee8SDavid du Colombier break; 255*219b2ee8SDavid du Colombier case GOTO: 256*219b2ee8SDavid du Colombier if (LastGoto) break; 257*219b2ee8SDavid du Colombier i = huntele(get_lab(e->n,1), e->status)->Seqno; 258*219b2ee8SDavid du Colombier fprintf(fd, "\t\tgoto S_%.3d_0; /* 'goto' */\n", i); 259*219b2ee8SDavid du Colombier Dested(i); 260*219b2ee8SDavid du Colombier break; 261*219b2ee8SDavid du Colombier case '.': 262*219b2ee8SDavid du Colombier if (LastGoto) break; 263*219b2ee8SDavid du Colombier if (e->nxt->status & DONE2) 264*219b2ee8SDavid du Colombier { i = e->nxt?e->nxt->Seqno:0; 265*219b2ee8SDavid du Colombier fprintf(fd, "\t\tgoto S_%.3d_0; /* '.' */\n", i); 266*219b2ee8SDavid du Colombier Dested(i); 267*219b2ee8SDavid du Colombier } 268*219b2ee8SDavid du Colombier break; 269*219b2ee8SDavid du Colombier default: 270*219b2ee8SDavid du Colombier putskip(e->seqno); 271*219b2ee8SDavid du Colombier GenCode = 1; IsGuard = isguard; 272*219b2ee8SDavid du Colombier fprintf(fd, "\t\t"); 273*219b2ee8SDavid du Colombier putstmnt(fd, e->n, e->seqno); 274*219b2ee8SDavid du Colombier fprintf(fd, ";\n"); 275*219b2ee8SDavid du Colombier GenCode = IsGuard = isguard = LastGoto = 0; 276*219b2ee8SDavid du Colombier if (e->n->ntyp == ELSE) 277*219b2ee8SDavid du Colombier LastGoto = 1; 278*219b2ee8SDavid du Colombier break; 279*219b2ee8SDavid du Colombier } 280*219b2ee8SDavid du Colombier i = e->nxt?e->nxt->Seqno:0; 281*219b2ee8SDavid du Colombier if (e->nxt && e->nxt->status & DONE2 && !LastGoto) 282*219b2ee8SDavid du Colombier { fprintf(fd, "\t\tgoto S_%.3d_0; /* ';' */\n", i); 283*219b2ee8SDavid du Colombier Dested(i); 284*219b2ee8SDavid du Colombier break; 285*219b2ee8SDavid du Colombier } 286*219b2ee8SDavid du Colombier } else 287*219b2ee8SDavid du Colombier { for (h = e->sub, i=1; h; h = h->nxt, i++) 288*219b2ee8SDavid du Colombier { sprintf(NextOpt, "goto S_%.3d_%d", e->Seqno, i); 289*219b2ee8SDavid du Colombier NextLab[++Level] = NextOpt; 290*219b2ee8SDavid du Colombier N = (e->n->ntyp == DO) ? e : e->nxt; 291*219b2ee8SDavid du Colombier putCode(fd, h->this->frst, h->this->extent, N, 1); 292*219b2ee8SDavid du Colombier Level--; 293*219b2ee8SDavid du Colombier fprintf(fd, "%s: /* 3 */\n", &NextOpt[5]); 294*219b2ee8SDavid du Colombier } 295*219b2ee8SDavid du Colombier if (!LastGoto) 296*219b2ee8SDavid du Colombier { fprintf(fd, "\t\tUerror(\"blocking sel in d_step\");\n"); 297*219b2ee8SDavid du Colombier LastGoto = 0; 298*219b2ee8SDavid du Colombier } 299*219b2ee8SDavid du Colombier } 300*219b2ee8SDavid du Colombier if (e == last) 301*219b2ee8SDavid du Colombier { if (!LastGoto && next) 302*219b2ee8SDavid du Colombier { fprintf(fd, "\t\tgoto S_%.3d_0;\n", next->Seqno); 303*219b2ee8SDavid du Colombier Dested(next->Seqno); 304*219b2ee8SDavid du Colombier } 305*219b2ee8SDavid du Colombier break; 306*219b2ee8SDavid du Colombier } } 307*219b2ee8SDavid du Colombier } 308