1219b2ee8SDavid du Colombier /***** spin: run.c *****/ 2219b2ee8SDavid du Colombier 3*7dd7cddfSDavid du Colombier /* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories */ 4*7dd7cddfSDavid du Colombier /* All Rights Reserved. This software is for educational purposes only. */ 5219b2ee8SDavid du Colombier /* Permission is given to distribute this code provided that this intro- */ 6219b2ee8SDavid du Colombier /* ductory message is not removed and no monies are exchanged. */ 7219b2ee8SDavid du Colombier /* No guarantee is expressed or implied by the distribution of this code. */ 8219b2ee8SDavid du Colombier /* Software written by Gerard J. Holzmann as part of the book: */ 9219b2ee8SDavid du Colombier /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */ 10219b2ee8SDavid du Colombier /* Prentice Hall, Englewood Cliffs, NJ, 07632. */ 11*7dd7cddfSDavid du Colombier /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */ 12219b2ee8SDavid du Colombier 13*7dd7cddfSDavid du Colombier #include <stdlib.h> 14219b2ee8SDavid du Colombier #include "spin.h" 15*7dd7cddfSDavid du Colombier #ifdef PC 16*7dd7cddfSDavid du Colombier #include "y_tab.h" 17*7dd7cddfSDavid du Colombier #else 18219b2ee8SDavid du Colombier #include "y.tab.h" 19*7dd7cddfSDavid du Colombier #endif 20219b2ee8SDavid du Colombier 21*7dd7cddfSDavid du Colombier extern RunList *X, *run; 22219b2ee8SDavid du Colombier extern Symbol *Fname; 23219b2ee8SDavid du Colombier extern Element *LastStep; 24*7dd7cddfSDavid du Colombier extern int Rvous, lineno, Tval, interactive, MadeChoice; 25*7dd7cddfSDavid du Colombier extern int TstOnly, verbose, s_trail, xspin, jumpsteps, depth; 26*7dd7cddfSDavid du Colombier extern int nproc, nstop, no_print, like_java; 27219b2ee8SDavid du Colombier 28219b2ee8SDavid du Colombier static long Seed = 1; 29*7dd7cddfSDavid du Colombier static int E_Check = 0, Escape_Check = 0; 30*7dd7cddfSDavid du Colombier 31*7dd7cddfSDavid du Colombier static int eval_sync(Element *); 32*7dd7cddfSDavid du Colombier static int pc_enabled(Lextok *n); 33*7dd7cddfSDavid du Colombier extern void sr_buf(int, int); 34219b2ee8SDavid du Colombier 35219b2ee8SDavid du Colombier void 36219b2ee8SDavid du Colombier Srand(unsigned int s) 37219b2ee8SDavid du Colombier { Seed = s; 38219b2ee8SDavid du Colombier } 39219b2ee8SDavid du Colombier 40219b2ee8SDavid du Colombier long 41219b2ee8SDavid du Colombier Rand(void) 42219b2ee8SDavid du Colombier { /* CACM 31(10), Oct 1988 */ 43219b2ee8SDavid du Colombier Seed = 16807*(Seed%127773) - 2836*(Seed/127773); 44219b2ee8SDavid du Colombier if (Seed <= 0) Seed += 2147483647; 45219b2ee8SDavid du Colombier return Seed; 46219b2ee8SDavid du Colombier } 47219b2ee8SDavid du Colombier 48219b2ee8SDavid du Colombier Element * 49*7dd7cddfSDavid du Colombier rev_escape(SeqList *e) 50*7dd7cddfSDavid du Colombier { Element *r; 51*7dd7cddfSDavid du Colombier 52*7dd7cddfSDavid du Colombier if (!e) 53*7dd7cddfSDavid du Colombier return (Element *) 0; 54*7dd7cddfSDavid du Colombier 55*7dd7cddfSDavid du Colombier if (r = rev_escape(e->nxt)) /* reversed order */ 56*7dd7cddfSDavid du Colombier return r; 57*7dd7cddfSDavid du Colombier 58*7dd7cddfSDavid du Colombier return eval_sub(e->this->frst); 59*7dd7cddfSDavid du Colombier } 60*7dd7cddfSDavid du Colombier 61*7dd7cddfSDavid du Colombier Element * 62219b2ee8SDavid du Colombier eval_sub(Element *e) 63219b2ee8SDavid du Colombier { Element *f, *g; 64219b2ee8SDavid du Colombier SeqList *z; 65219b2ee8SDavid du Colombier int i, j, k; 66219b2ee8SDavid du Colombier 67219b2ee8SDavid du Colombier if (!e->n) 68219b2ee8SDavid du Colombier return ZE; 69219b2ee8SDavid du Colombier #ifdef DEBUG 70*7dd7cddfSDavid du Colombier printf("\n\teval_sub(%d %s: line %d) ", 71*7dd7cddfSDavid du Colombier e->Seqno, e->esc?"+esc":"", e->n?e->n->ln:0); 72219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 73219b2ee8SDavid du Colombier printf("\n"); 74219b2ee8SDavid du Colombier #endif 75219b2ee8SDavid du Colombier if (e->n->ntyp == GOTO) 76219b2ee8SDavid du Colombier { if (Rvous) return ZE; 77*7dd7cddfSDavid du Colombier LastStep = e; f = get_lab(e->n, 1); 78219b2ee8SDavid du Colombier cross_dsteps(e->n, f->n); 79219b2ee8SDavid du Colombier return f; 80219b2ee8SDavid du Colombier } 81219b2ee8SDavid du Colombier if (e->n->ntyp == UNLESS) 82219b2ee8SDavid du Colombier { /* escapes were distributed into sequence */ 83219b2ee8SDavid du Colombier return eval_sub(e->sub->this->frst); 84219b2ee8SDavid du Colombier } else if (e->sub) /* true for IF, DO, and UNLESS */ 85219b2ee8SDavid du Colombier { Element *has_else = ZE; 86*7dd7cddfSDavid du Colombier Element *bas_else = ZE; 87*7dd7cddfSDavid du Colombier int nr_else, nr_choices = 0; 88219b2ee8SDavid du Colombier 89*7dd7cddfSDavid du Colombier if (interactive 90*7dd7cddfSDavid du Colombier && !MadeChoice && !E_Check 91*7dd7cddfSDavid du Colombier && !Escape_Check 92*7dd7cddfSDavid du Colombier && !(e->status&(D_ATOM)) 93*7dd7cddfSDavid du Colombier && depth >= jumpsteps) 94219b2ee8SDavid du Colombier { printf("Select stmnt ("); 95219b2ee8SDavid du Colombier whoruns(0); printf(")\n"); 96*7dd7cddfSDavid du Colombier if (nproc-nstop > 1) 97219b2ee8SDavid du Colombier printf("\tchoice 0: other process\n"); 98219b2ee8SDavid du Colombier } 99219b2ee8SDavid du Colombier for (z = e->sub, j=0; z; z = z->nxt) 100219b2ee8SDavid du Colombier { j++; 101*7dd7cddfSDavid du Colombier if (interactive 102*7dd7cddfSDavid du Colombier && !MadeChoice && !E_Check 103*7dd7cddfSDavid du Colombier && !Escape_Check 104*7dd7cddfSDavid du Colombier && !(e->status&(D_ATOM)) 105*7dd7cddfSDavid du Colombier && depth >= jumpsteps 106219b2ee8SDavid du Colombier && z->this->frst 107*7dd7cddfSDavid du Colombier && (xspin || (verbose&32) || Enabled0(z->this->frst))) 108*7dd7cddfSDavid du Colombier { if (z->this->frst->n->ntyp == ELSE) 109*7dd7cddfSDavid du Colombier { has_else = (Rvous)?ZE:z->this->frst->nxt; 110*7dd7cddfSDavid du Colombier nr_else = j; 111*7dd7cddfSDavid du Colombier continue; 112*7dd7cddfSDavid du Colombier } 113*7dd7cddfSDavid du Colombier printf("\tchoice %d: ", j); 114*7dd7cddfSDavid du Colombier #if 0 115*7dd7cddfSDavid du Colombier if (z->this->frst->n) 116*7dd7cddfSDavid du Colombier printf("line %d, ", z->this->frst->n->ln); 117*7dd7cddfSDavid du Colombier #endif 118219b2ee8SDavid du Colombier if (!Enabled0(z->this->frst)) 119219b2ee8SDavid du Colombier printf("unexecutable, "); 120*7dd7cddfSDavid du Colombier else 121*7dd7cddfSDavid du Colombier nr_choices++; 122219b2ee8SDavid du Colombier comment(stdout, z->this->frst->n, 0); 123219b2ee8SDavid du Colombier printf("\n"); 124219b2ee8SDavid du Colombier } } 125*7dd7cddfSDavid du Colombier 126*7dd7cddfSDavid du Colombier if (nr_choices == 0 && has_else) 127*7dd7cddfSDavid du Colombier printf("\tchoice %d: (else)\n", nr_else); 128*7dd7cddfSDavid du Colombier 129*7dd7cddfSDavid du Colombier if (interactive && depth >= jumpsteps 130*7dd7cddfSDavid du Colombier && !Escape_Check 131*7dd7cddfSDavid du Colombier && !(e->status&(D_ATOM)) 132*7dd7cddfSDavid du Colombier && !E_Check) 133*7dd7cddfSDavid du Colombier { if (!MadeChoice) 134*7dd7cddfSDavid du Colombier { char buf[256]; 135*7dd7cddfSDavid du Colombier if (xspin) 136219b2ee8SDavid du Colombier printf("Make Selection %d\n\n", j); 137219b2ee8SDavid du Colombier else 138219b2ee8SDavid du Colombier printf("Select [0-%d]: ", j); 139219b2ee8SDavid du Colombier fflush(stdout); 140*7dd7cddfSDavid du Colombier scanf("%s", buf); 141*7dd7cddfSDavid du Colombier if (isdigit(buf[0])) 142*7dd7cddfSDavid du Colombier k = atoi(buf); 143*7dd7cddfSDavid du Colombier else 144*7dd7cddfSDavid du Colombier { if (buf[0] == 'q') 145*7dd7cddfSDavid du Colombier alldone(0); 146*7dd7cddfSDavid du Colombier k = -1; 147*7dd7cddfSDavid du Colombier } 148219b2ee8SDavid du Colombier } else 149*7dd7cddfSDavid du Colombier { k = MadeChoice; 150*7dd7cddfSDavid du Colombier MadeChoice = 0; 151219b2ee8SDavid du Colombier } 152219b2ee8SDavid du Colombier if (k < 1 || k > j) 153*7dd7cddfSDavid du Colombier { if (k != 0) printf("\tchoice outside range\n"); 154219b2ee8SDavid du Colombier return ZE; 155219b2ee8SDavid du Colombier } 156219b2ee8SDavid du Colombier k--; 157219b2ee8SDavid du Colombier } else 158*7dd7cddfSDavid du Colombier { if (e->n && e->n->indstep >= 0) 159*7dd7cddfSDavid du Colombier k = 0; /* select 1st executable guard */ 160*7dd7cddfSDavid du Colombier else 161219b2ee8SDavid du Colombier k = Rand()%j; /* nondeterminism */ 162*7dd7cddfSDavid du Colombier } 163*7dd7cddfSDavid du Colombier has_else = ZE; 164*7dd7cddfSDavid du Colombier bas_else = ZE; 165219b2ee8SDavid du Colombier for (i = 0, z = e->sub; i < j+k; i++) 166219b2ee8SDavid du Colombier { if (z->this->frst 167219b2ee8SDavid du Colombier && z->this->frst->n->ntyp == ELSE) 168*7dd7cddfSDavid du Colombier { bas_else = z->this->frst; 169*7dd7cddfSDavid du Colombier has_else = (Rvous)?ZE:bas_else->nxt; 170*7dd7cddfSDavid du Colombier if (!interactive || depth < jumpsteps 171*7dd7cddfSDavid du Colombier || Escape_Check 172*7dd7cddfSDavid du Colombier || (e->status&(D_ATOM))) 173219b2ee8SDavid du Colombier { z = (z->nxt)?z->nxt:e->sub; 174219b2ee8SDavid du Colombier continue; 175*7dd7cddfSDavid du Colombier } 176*7dd7cddfSDavid du Colombier } 177219b2ee8SDavid du Colombier if (i >= k) 178219b2ee8SDavid du Colombier { if (f = eval_sub(z->this->frst)) 179219b2ee8SDavid du Colombier return f; 180*7dd7cddfSDavid du Colombier else if (interactive && depth >= jumpsteps 181*7dd7cddfSDavid du Colombier && !(e->status&(D_ATOM))) 182*7dd7cddfSDavid du Colombier { if (!E_Check && !Escape_Check) 183*7dd7cddfSDavid du Colombier printf("\tunexecutable\n"); 184219b2ee8SDavid du Colombier return ZE; 185219b2ee8SDavid du Colombier } } 186219b2ee8SDavid du Colombier z = (z->nxt)?z->nxt:e->sub; 187219b2ee8SDavid du Colombier } 188*7dd7cddfSDavid du Colombier LastStep = bas_else; 189219b2ee8SDavid du Colombier return has_else; 190219b2ee8SDavid du Colombier } else 191219b2ee8SDavid du Colombier { if (e->n->ntyp == ATOMIC 192219b2ee8SDavid du Colombier || e->n->ntyp == D_STEP) 193219b2ee8SDavid du Colombier { f = e->n->sl->this->frst; 194219b2ee8SDavid du Colombier g = e->n->sl->this->last; 195219b2ee8SDavid du Colombier g->nxt = e->nxt; 196219b2ee8SDavid du Colombier if (!(g = eval_sub(f))) /* atomic guard */ 197219b2ee8SDavid du Colombier return ZE; 198219b2ee8SDavid du Colombier return g; 199219b2ee8SDavid du Colombier } else if (e->n->ntyp == NON_ATOMIC) 200219b2ee8SDavid du Colombier { f = e->n->sl->this->frst; 201219b2ee8SDavid du Colombier g = e->n->sl->this->last; 202219b2ee8SDavid du Colombier g->nxt = e->nxt; /* close it */ 203219b2ee8SDavid du Colombier return eval_sub(f); 204219b2ee8SDavid du Colombier } else if (e->n->ntyp == '.') 205*7dd7cddfSDavid du Colombier { if (!Rvous) return e->nxt; 206*7dd7cddfSDavid du Colombier return eval_sub(e->nxt); 207219b2ee8SDavid du Colombier } else 208219b2ee8SDavid du Colombier { SeqList *x; 209*7dd7cddfSDavid du Colombier if (!(e->status & (D_ATOM)) 210*7dd7cddfSDavid du Colombier && e->esc && verbose&32) 211*7dd7cddfSDavid du Colombier { printf("Stmnt ["); 212219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 213*7dd7cddfSDavid du Colombier printf("] has escape(s): "); 214219b2ee8SDavid du Colombier for (x = e->esc; x; x = x->nxt) 215*7dd7cddfSDavid du Colombier { printf("["); 216*7dd7cddfSDavid du Colombier g = x->this->frst; 217*7dd7cddfSDavid du Colombier if (g->n->ntyp == ATOMIC 218*7dd7cddfSDavid du Colombier || g->n->ntyp == NON_ATOMIC) 219*7dd7cddfSDavid du Colombier g = g->n->sl->this->frst; 220*7dd7cddfSDavid du Colombier comment(stdout, g->n, 0); 221*7dd7cddfSDavid du Colombier printf("] "); 222*7dd7cddfSDavid du Colombier } 223*7dd7cddfSDavid du Colombier printf("\n"); 224*7dd7cddfSDavid du Colombier } 225*7dd7cddfSDavid du Colombier 226*7dd7cddfSDavid du Colombier if (!(e->status & D_ATOM)) /* escapes don't reach inside d_steps */ 227*7dd7cddfSDavid du Colombier { Escape_Check++; 228*7dd7cddfSDavid du Colombier if (like_java) 229*7dd7cddfSDavid du Colombier { if (g = rev_escape(e->esc)) 230*7dd7cddfSDavid du Colombier { if (verbose&4) 231*7dd7cddfSDavid du Colombier printf("\tEscape taken\n"); 232*7dd7cddfSDavid du Colombier Escape_Check--; 233*7dd7cddfSDavid du Colombier return g; 234*7dd7cddfSDavid du Colombier } 235*7dd7cddfSDavid du Colombier } else 236*7dd7cddfSDavid du Colombier { for (x = e->esc; x; x = x->nxt) 237219b2ee8SDavid du Colombier { if (g = eval_sub(x->this->frst)) 238219b2ee8SDavid du Colombier { if (verbose&4) 239219b2ee8SDavid du Colombier printf("\tEscape taken\n"); 240*7dd7cddfSDavid du Colombier Escape_Check--; 241219b2ee8SDavid du Colombier return g; 242*7dd7cddfSDavid du Colombier } } } 243*7dd7cddfSDavid du Colombier Escape_Check--; 244*7dd7cddfSDavid du Colombier } 245*7dd7cddfSDavid du Colombier 246219b2ee8SDavid du Colombier switch (e->n->ntyp) { 247219b2ee8SDavid du Colombier case TIMEOUT: case RUN: 248*7dd7cddfSDavid du Colombier case PRINT: 249*7dd7cddfSDavid du Colombier case ASGN: case ASSERT: 250219b2ee8SDavid du Colombier case 's': case 'r': case 'c': 251219b2ee8SDavid du Colombier /* toplevel statements only */ 252219b2ee8SDavid du Colombier LastStep = e; 253219b2ee8SDavid du Colombier default: 254219b2ee8SDavid du Colombier break; 255219b2ee8SDavid du Colombier } 256*7dd7cddfSDavid du Colombier if (Rvous) 257*7dd7cddfSDavid du Colombier { 258*7dd7cddfSDavid du Colombier return (eval_sync(e))?e->nxt:ZE; 259*7dd7cddfSDavid du Colombier } 260219b2ee8SDavid du Colombier return (eval(e->n))?e->nxt:ZE; 261219b2ee8SDavid du Colombier } 262219b2ee8SDavid du Colombier } 263*7dd7cddfSDavid du Colombier return ZE; /* not reached */ 264219b2ee8SDavid du Colombier } 265219b2ee8SDavid du Colombier 266*7dd7cddfSDavid du Colombier static int 267219b2ee8SDavid du Colombier eval_sync(Element *e) 268219b2ee8SDavid du Colombier { /* allow only synchronous receives 269*7dd7cddfSDavid du Colombier and related node types */ 270219b2ee8SDavid du Colombier Lextok *now = (e)?e->n:ZN; 271219b2ee8SDavid du Colombier 272219b2ee8SDavid du Colombier if (!now 273219b2ee8SDavid du Colombier || now->ntyp != 'r' 274*7dd7cddfSDavid du Colombier || now->val >= 2 /* no rv with a poll */ 275219b2ee8SDavid du Colombier || !q_is_sync(now)) 276*7dd7cddfSDavid du Colombier { 277219b2ee8SDavid du Colombier return 0; 278*7dd7cddfSDavid du Colombier } 279219b2ee8SDavid du Colombier 280219b2ee8SDavid du Colombier LastStep = e; 281219b2ee8SDavid du Colombier return eval(now); 282219b2ee8SDavid du Colombier } 283219b2ee8SDavid du Colombier 284*7dd7cddfSDavid du Colombier static int 285219b2ee8SDavid du Colombier assign(Lextok *now) 286219b2ee8SDavid du Colombier { int t; 287219b2ee8SDavid du Colombier 288219b2ee8SDavid du Colombier if (TstOnly) return 1; 289219b2ee8SDavid du Colombier 290219b2ee8SDavid du Colombier switch (now->rgt->ntyp) { 291219b2ee8SDavid du Colombier case FULL: case NFULL: 292219b2ee8SDavid du Colombier case EMPTY: case NEMPTY: 293219b2ee8SDavid du Colombier case RUN: case LEN: 294219b2ee8SDavid du Colombier t = BYTE; 295219b2ee8SDavid du Colombier break; 296219b2ee8SDavid du Colombier default: 297219b2ee8SDavid du Colombier t = Sym_typ(now->rgt); 298219b2ee8SDavid du Colombier break; 299219b2ee8SDavid du Colombier } 300219b2ee8SDavid du Colombier typ_ck(Sym_typ(now->lft), t, "assignment"); 301219b2ee8SDavid du Colombier return setval(now->lft, eval(now->rgt)); 302219b2ee8SDavid du Colombier } 303219b2ee8SDavid du Colombier 304*7dd7cddfSDavid du Colombier static int 305*7dd7cddfSDavid du Colombier nonprogress(void) /* np_ */ 306*7dd7cddfSDavid du Colombier { RunList *r; 307*7dd7cddfSDavid du Colombier 308*7dd7cddfSDavid du Colombier for (r = run; r; r = r->nxt) 309*7dd7cddfSDavid du Colombier { if (has_lab(r->pc, 4)) /* 4=progress */ 310*7dd7cddfSDavid du Colombier return 0; 311*7dd7cddfSDavid du Colombier } 312*7dd7cddfSDavid du Colombier return 1; 313*7dd7cddfSDavid du Colombier } 314*7dd7cddfSDavid du Colombier 315219b2ee8SDavid du Colombier int 316219b2ee8SDavid du Colombier eval(Lextok *now) 317219b2ee8SDavid du Colombier { 318219b2ee8SDavid du Colombier if (now) { 319219b2ee8SDavid du Colombier lineno = now->ln; 320219b2ee8SDavid du Colombier Fname = now->fn; 321219b2ee8SDavid du Colombier #ifdef DEBUG 322219b2ee8SDavid du Colombier printf("eval "); 323219b2ee8SDavid du Colombier comment(stdout, now, 0); 324219b2ee8SDavid du Colombier printf("\n"); 325219b2ee8SDavid du Colombier #endif 326219b2ee8SDavid du Colombier switch (now->ntyp) { 327219b2ee8SDavid du Colombier case CONST: return now->val; 328219b2ee8SDavid du Colombier case '!': return !eval(now->lft); 329219b2ee8SDavid du Colombier case UMIN: return -eval(now->lft); 330219b2ee8SDavid du Colombier case '~': return ~eval(now->lft); 331219b2ee8SDavid du Colombier 332219b2ee8SDavid du Colombier case '/': return (eval(now->lft) / eval(now->rgt)); 333219b2ee8SDavid du Colombier case '*': return (eval(now->lft) * eval(now->rgt)); 334219b2ee8SDavid du Colombier case '-': return (eval(now->lft) - eval(now->rgt)); 335219b2ee8SDavid du Colombier case '+': return (eval(now->lft) + eval(now->rgt)); 336219b2ee8SDavid du Colombier case '%': return (eval(now->lft) % eval(now->rgt)); 337219b2ee8SDavid du Colombier case LT: return (eval(now->lft) < eval(now->rgt)); 338219b2ee8SDavid du Colombier case GT: return (eval(now->lft) > eval(now->rgt)); 339219b2ee8SDavid du Colombier case '&': return (eval(now->lft) & eval(now->rgt)); 340*7dd7cddfSDavid du Colombier case '^': return (eval(now->lft) ^ eval(now->rgt)); 341219b2ee8SDavid du Colombier case '|': return (eval(now->lft) | eval(now->rgt)); 342219b2ee8SDavid du Colombier case LE: return (eval(now->lft) <= eval(now->rgt)); 343219b2ee8SDavid du Colombier case GE: return (eval(now->lft) >= eval(now->rgt)); 344219b2ee8SDavid du Colombier case NE: return (eval(now->lft) != eval(now->rgt)); 345219b2ee8SDavid du Colombier case EQ: return (eval(now->lft) == eval(now->rgt)); 346219b2ee8SDavid du Colombier case OR: return (eval(now->lft) || eval(now->rgt)); 347219b2ee8SDavid du Colombier case AND: return (eval(now->lft) && eval(now->rgt)); 348219b2ee8SDavid du Colombier case LSHIFT: return (eval(now->lft) << eval(now->rgt)); 349219b2ee8SDavid du Colombier case RSHIFT: return (eval(now->lft) >> eval(now->rgt)); 350219b2ee8SDavid du Colombier case '?': return (eval(now->lft) ? eval(now->rgt->lft) 351219b2ee8SDavid du Colombier : eval(now->rgt->rgt)); 352219b2ee8SDavid du Colombier 353219b2ee8SDavid du Colombier case 'p': return remotevar(now); /* only _p allowed */ 354219b2ee8SDavid du Colombier case 'q': return remotelab(now); 355219b2ee8SDavid du Colombier case 'R': return qrecv(now, 0); /* test only */ 356219b2ee8SDavid du Colombier case LEN: return qlen(now); 357219b2ee8SDavid du Colombier case FULL: return (qfull(now)); 358219b2ee8SDavid du Colombier case EMPTY: return (qlen(now)==0); 359219b2ee8SDavid du Colombier case NFULL: return (!qfull(now)); 360219b2ee8SDavid du Colombier case NEMPTY: return (qlen(now)>0); 361*7dd7cddfSDavid du Colombier case ENABLED: if (s_trail) return 1; 362*7dd7cddfSDavid du Colombier return pc_enabled(now->lft); 363*7dd7cddfSDavid du Colombier case EVAL: return eval(now->lft); 364219b2ee8SDavid du Colombier case PC_VAL: return pc_value(now->lft); 365*7dd7cddfSDavid du Colombier case NONPROGRESS: return nonprogress(); 366219b2ee8SDavid du Colombier case NAME: return getval(now); 367219b2ee8SDavid du Colombier 368219b2ee8SDavid du Colombier case TIMEOUT: return Tval; 369*7dd7cddfSDavid du Colombier case RUN: return TstOnly?1:enable(now); 370219b2ee8SDavid du Colombier 371219b2ee8SDavid du Colombier case 's': return qsend(now); /* send */ 372*7dd7cddfSDavid du Colombier case 'r': return qrecv(now, 1); /* receive or poll */ 373219b2ee8SDavid du Colombier case 'c': return eval(now->lft); /* condition */ 374*7dd7cddfSDavid du Colombier case PRINT: return TstOnly?1:interprint(stdout, now); 375219b2ee8SDavid du Colombier case ASGN: return assign(now); 376219b2ee8SDavid du Colombier case ASSERT: if (TstOnly || eval(now->lft)) return 1; 377219b2ee8SDavid du Colombier non_fatal("assertion violated", (char *) 0); 378*7dd7cddfSDavid du Colombier printf("spin: text of failed assertion: assert("); 379*7dd7cddfSDavid du Colombier comment(stdout, now->lft, 0); 380*7dd7cddfSDavid du Colombier printf(")\n"); 381*7dd7cddfSDavid du Colombier if (s_trail && !xspin) return 1; 382219b2ee8SDavid du Colombier wrapup(1); /* doesn't return */ 383219b2ee8SDavid du Colombier 384*7dd7cddfSDavid du Colombier case IF: case DO: case BREAK: case UNLESS: /* compound */ 385219b2ee8SDavid du Colombier case '.': return 1; /* return label for compound */ 386219b2ee8SDavid du Colombier case '@': return 0; /* stop state */ 387219b2ee8SDavid du Colombier case ELSE: return 1; /* only hit here in guided trails */ 388219b2ee8SDavid du Colombier default : printf("spin: bad node type %d (run)\n", now->ntyp); 389*7dd7cddfSDavid du Colombier if (s_trail) printf("spin: trail file doesn't match spec?\n"); 390219b2ee8SDavid du Colombier fatal("aborting", 0); 391219b2ee8SDavid du Colombier }} 392219b2ee8SDavid du Colombier return 0; 393219b2ee8SDavid du Colombier } 394219b2ee8SDavid du Colombier 395219b2ee8SDavid du Colombier int 396*7dd7cddfSDavid du Colombier interprint(FILE *fd, Lextok *n) 397219b2ee8SDavid du Colombier { Lextok *tmp = n->lft; 398219b2ee8SDavid du Colombier char c, *s = n->sym->name; 399*7dd7cddfSDavid du Colombier int i, j; char lbuf[16]; 400*7dd7cddfSDavid du Colombier extern char Buf[]; 401*7dd7cddfSDavid du Colombier char tBuf[1024]; 402219b2ee8SDavid du Colombier 403*7dd7cddfSDavid du Colombier Buf[0] = '\0'; 404*7dd7cddfSDavid du Colombier if (!no_print) 405*7dd7cddfSDavid du Colombier if (!s_trail || depth >= jumpsteps) { 406*7dd7cddfSDavid du Colombier for (i = 0; i < (int) strlen(s); i++) 407219b2ee8SDavid du Colombier switch (s[i]) { 408219b2ee8SDavid du Colombier case '\"': break; /* ignore */ 409219b2ee8SDavid du Colombier case '\\': 410219b2ee8SDavid du Colombier switch(s[++i]) { 411*7dd7cddfSDavid du Colombier case 't': strcat(Buf, "\t"); break; 412*7dd7cddfSDavid du Colombier case 'n': strcat(Buf, "\n"); break; 413*7dd7cddfSDavid du Colombier default: goto onechar; 414219b2ee8SDavid du Colombier } 415219b2ee8SDavid du Colombier break; 416219b2ee8SDavid du Colombier case '%': 417219b2ee8SDavid du Colombier if ((c = s[++i]) == '%') 418*7dd7cddfSDavid du Colombier { strcat(Buf, "%"); /* literal */ 419219b2ee8SDavid du Colombier break; 420219b2ee8SDavid du Colombier } 421219b2ee8SDavid du Colombier if (!tmp) 422219b2ee8SDavid du Colombier { non_fatal("too few print args %s", s); 423219b2ee8SDavid du Colombier break; 424219b2ee8SDavid du Colombier } 425219b2ee8SDavid du Colombier j = eval(tmp->lft); 426219b2ee8SDavid du Colombier tmp = tmp->rgt; 427219b2ee8SDavid du Colombier switch(c) { 428*7dd7cddfSDavid du Colombier case 'c': sprintf(lbuf, "%c", j); break; 429*7dd7cddfSDavid du Colombier case 'd': sprintf(lbuf, "%d", j); break; 430*7dd7cddfSDavid du Colombier 431*7dd7cddfSDavid du Colombier case 'e': strcpy(tBuf, Buf); /* event name */ 432*7dd7cddfSDavid du Colombier Buf[0] = '\0'; 433*7dd7cddfSDavid du Colombier sr_buf(j, 1); 434*7dd7cddfSDavid du Colombier strcpy(lbuf, Buf); 435*7dd7cddfSDavid du Colombier strcpy(Buf, tBuf); 436*7dd7cddfSDavid du Colombier break; 437*7dd7cddfSDavid du Colombier 438*7dd7cddfSDavid du Colombier case 'o': sprintf(lbuf, "%o", j); break; 439*7dd7cddfSDavid du Colombier case 'u': sprintf(lbuf, "%u", (unsigned) j); break; 440*7dd7cddfSDavid du Colombier case 'x': sprintf(lbuf, "%x", j); break; 441*7dd7cddfSDavid du Colombier default: non_fatal("bad print cmd: '%s'", &s[i-1]); 442*7dd7cddfSDavid du Colombier lbuf[0] = '\0'; break; 443*7dd7cddfSDavid du Colombier } 444*7dd7cddfSDavid du Colombier goto append; 445*7dd7cddfSDavid du Colombier default: 446*7dd7cddfSDavid du Colombier onechar: lbuf[0] = s[i]; lbuf[1] = '\0'; 447*7dd7cddfSDavid du Colombier append: strcat(Buf, lbuf); 448219b2ee8SDavid du Colombier break; 449219b2ee8SDavid du Colombier } 450*7dd7cddfSDavid du Colombier dotag(fd, Buf); 451219b2ee8SDavid du Colombier } 452*7dd7cddfSDavid du Colombier if (strlen(Buf) > 1024) fatal("printf string too long", 0); 453219b2ee8SDavid du Colombier return 1; 454219b2ee8SDavid du Colombier } 455219b2ee8SDavid du Colombier 456*7dd7cddfSDavid du Colombier static int 457219b2ee8SDavid du Colombier Enabled1(Lextok *n) 458219b2ee8SDavid du Colombier { int i; int v = verbose; 459219b2ee8SDavid du Colombier 460219b2ee8SDavid du Colombier if (n) 461219b2ee8SDavid du Colombier switch (n->ntyp) { 462*7dd7cddfSDavid du Colombier case 'c': 463*7dd7cddfSDavid du Colombier if (has_typ(n->lft, RUN)) 464*7dd7cddfSDavid du Colombier return 1; /* conservative */ 465*7dd7cddfSDavid du Colombier /* else fall through */ 466219b2ee8SDavid du Colombier default: /* side-effect free */ 467219b2ee8SDavid du Colombier verbose = 0; 468*7dd7cddfSDavid du Colombier E_Check++; 469219b2ee8SDavid du Colombier i = eval(n); 470*7dd7cddfSDavid du Colombier E_Check--; 471219b2ee8SDavid du Colombier verbose = v; 472219b2ee8SDavid du Colombier return i; 473219b2ee8SDavid du Colombier 474*7dd7cddfSDavid du Colombier case PRINT: case ASGN: case ASSERT: 475219b2ee8SDavid du Colombier return 1; 476219b2ee8SDavid du Colombier 477*7dd7cddfSDavid du Colombier case 's': 478*7dd7cddfSDavid du Colombier if (q_is_sync(n)) 479*7dd7cddfSDavid du Colombier { if (Rvous) return 0; 480*7dd7cddfSDavid du Colombier TstOnly = 1; verbose = 0; 481*7dd7cddfSDavid du Colombier E_Check++; 482219b2ee8SDavid du Colombier i = eval(n); 483*7dd7cddfSDavid du Colombier E_Check--; 484*7dd7cddfSDavid du Colombier TstOnly = 0; verbose = v; 485*7dd7cddfSDavid du Colombier return i; 486*7dd7cddfSDavid du Colombier } 487*7dd7cddfSDavid du Colombier return (!qfull(n)); 488*7dd7cddfSDavid du Colombier case 'r': 489*7dd7cddfSDavid du Colombier if (q_is_sync(n)) 490*7dd7cddfSDavid du Colombier return 0; /* it's never a user-choice */ 491*7dd7cddfSDavid du Colombier n->ntyp = 'R'; verbose = 0; 492*7dd7cddfSDavid du Colombier E_Check++; 493*7dd7cddfSDavid du Colombier i = eval(n); 494*7dd7cddfSDavid du Colombier E_Check--; 495219b2ee8SDavid du Colombier n->ntyp = 'r'; verbose = v; 496219b2ee8SDavid du Colombier return i; 497219b2ee8SDavid du Colombier } 498219b2ee8SDavid du Colombier return 0; 499219b2ee8SDavid du Colombier } 500219b2ee8SDavid du Colombier 501219b2ee8SDavid du Colombier int 502219b2ee8SDavid du Colombier Enabled0(Element *e) 503219b2ee8SDavid du Colombier { SeqList *z; 504219b2ee8SDavid du Colombier 505219b2ee8SDavid du Colombier if (!e || !e->n) 506219b2ee8SDavid du Colombier return 0; 507219b2ee8SDavid du Colombier 508219b2ee8SDavid du Colombier switch (e->n->ntyp) { 509*7dd7cddfSDavid du Colombier case '@': 510*7dd7cddfSDavid du Colombier return X->pid == (nproc-nstop-1); 511219b2ee8SDavid du Colombier case '.': 512219b2ee8SDavid du Colombier return 1; 513219b2ee8SDavid du Colombier case GOTO: 514219b2ee8SDavid du Colombier if (Rvous) return 0; 515219b2ee8SDavid du Colombier return 1; 516219b2ee8SDavid du Colombier case UNLESS: 517219b2ee8SDavid du Colombier return Enabled0(e->sub->this->frst); 518219b2ee8SDavid du Colombier case ATOMIC: 519219b2ee8SDavid du Colombier case D_STEP: 520219b2ee8SDavid du Colombier case NON_ATOMIC: 521219b2ee8SDavid du Colombier return Enabled0(e->n->sl->this->frst); 522219b2ee8SDavid du Colombier } 523219b2ee8SDavid du Colombier if (e->sub) /* true for IF, DO, and UNLESS */ 524219b2ee8SDavid du Colombier { for (z = e->sub; z; z = z->nxt) 525219b2ee8SDavid du Colombier if (Enabled0(z->this->frst)) 526219b2ee8SDavid du Colombier return 1; 527219b2ee8SDavid du Colombier return 0; 528219b2ee8SDavid du Colombier } 529219b2ee8SDavid du Colombier for (z = e->esc; z; z = z->nxt) 530219b2ee8SDavid du Colombier { if (Enabled0(z->this->frst)) 531219b2ee8SDavid du Colombier return 1; 532219b2ee8SDavid du Colombier } 533*7dd7cddfSDavid du Colombier #if 0 534*7dd7cddfSDavid du Colombier printf("enabled1 "); 535*7dd7cddfSDavid du Colombier comment(stdout, e->n, 0); 536*7dd7cddfSDavid du Colombier printf(" ==> %s\n", Enabled1(e->n)?"yes":"nope"); 537*7dd7cddfSDavid du Colombier #endif 538219b2ee8SDavid du Colombier return Enabled1(e->n); 539219b2ee8SDavid du Colombier } 540*7dd7cddfSDavid du Colombier 541*7dd7cddfSDavid du Colombier int 542*7dd7cddfSDavid du Colombier pc_enabled(Lextok *n) 543*7dd7cddfSDavid du Colombier { int i = nproc - nstop; 544*7dd7cddfSDavid du Colombier int pid = eval(n); 545*7dd7cddfSDavid du Colombier int result = 0; 546*7dd7cddfSDavid du Colombier RunList *Y, *oX; 547*7dd7cddfSDavid du Colombier 548*7dd7cddfSDavid du Colombier for (Y = run; Y; Y = Y->nxt) 549*7dd7cddfSDavid du Colombier if (--i == pid) 550*7dd7cddfSDavid du Colombier { oX = X; X = Y; 551*7dd7cddfSDavid du Colombier result = Enabled0(Y->pc); 552*7dd7cddfSDavid du Colombier X = oX; 553*7dd7cddfSDavid du Colombier break; 554*7dd7cddfSDavid du Colombier } 555*7dd7cddfSDavid du Colombier return result; 556*7dd7cddfSDavid du Colombier } 557