1*219b2ee8SDavid du Colombier /***** spin: sched.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 extern int verbose, s_trail, analyze; 17*219b2ee8SDavid du Colombier extern char *claimproc; 18*219b2ee8SDavid du Colombier extern Symbol *Fname, *context; 19*219b2ee8SDavid du Colombier extern int lineno, nr_errs, dumptab, xspin; 20*219b2ee8SDavid du Colombier extern int has_enabled, u_sync, Elcnt, Interactive; 21*219b2ee8SDavid du Colombier 22*219b2ee8SDavid du Colombier RunList *X = (RunList *) 0; 23*219b2ee8SDavid du Colombier RunList *run = (RunList *) 0; 24*219b2ee8SDavid du Colombier RunList *LastX = (RunList *) 0; /* previous executing proc */ 25*219b2ee8SDavid du Colombier ProcList *rdy = (ProcList *) 0; 26*219b2ee8SDavid du Colombier Element *LastStep = ZE; 27*219b2ee8SDavid du Colombier int Have_claim=0, nproc=0, nstop=0, Tval=0; 28*219b2ee8SDavid du Colombier int Rvous=0, depth=0, nrRdy=0, SubChoice; 29*219b2ee8SDavid du Colombier 30*219b2ee8SDavid du Colombier void 31*219b2ee8SDavid du Colombier runnable(ProcList *p) 32*219b2ee8SDavid du Colombier { RunList *r = (RunList *) emalloc(sizeof(RunList)); 33*219b2ee8SDavid du Colombier 34*219b2ee8SDavid du Colombier r->n = p->n; 35*219b2ee8SDavid du Colombier r->tn = p->tn; 36*219b2ee8SDavid du Colombier r->pid = ++nproc-nstop-1; /* was: nproc++; */ 37*219b2ee8SDavid du Colombier r->pc = huntele(p->s->frst, p->s->frst->status); /* was: s->frst; */ 38*219b2ee8SDavid du Colombier r->ps = p->s; /* was: r->maxseq = s->last->seqno */ 39*219b2ee8SDavid du Colombier r->nxt = run; 40*219b2ee8SDavid du Colombier run = r; 41*219b2ee8SDavid du Colombier } 42*219b2ee8SDavid du Colombier 43*219b2ee8SDavid du Colombier ProcList * 44*219b2ee8SDavid du Colombier ready(Symbol *n, Lextok *p, Sequence *s) /* n=name, p=formals, s=body */ 45*219b2ee8SDavid du Colombier { ProcList *r = (ProcList *) emalloc(sizeof(ProcList)); 46*219b2ee8SDavid du Colombier Lextok *fp, *fpt; int j; extern int Npars; 47*219b2ee8SDavid du Colombier 48*219b2ee8SDavid du Colombier r->n = n; 49*219b2ee8SDavid du Colombier r->p = p; 50*219b2ee8SDavid du Colombier r->s = s; 51*219b2ee8SDavid du Colombier r->tn = nrRdy++; 52*219b2ee8SDavid du Colombier r->nxt = rdy; 53*219b2ee8SDavid du Colombier rdy = r; 54*219b2ee8SDavid du Colombier 55*219b2ee8SDavid du Colombier for (fp = p, j = 0; fp; fp = fp->rgt) 56*219b2ee8SDavid du Colombier for (fpt = fp->lft; fpt; fpt = fpt->rgt) 57*219b2ee8SDavid du Colombier j++; /* count # of parameters */ 58*219b2ee8SDavid du Colombier Npars = max(Npars, j); 59*219b2ee8SDavid du Colombier 60*219b2ee8SDavid du Colombier return rdy; 61*219b2ee8SDavid du Colombier } 62*219b2ee8SDavid du Colombier 63*219b2ee8SDavid du Colombier int 64*219b2ee8SDavid du Colombier find_maxel(Symbol *s) 65*219b2ee8SDavid du Colombier { ProcList *p; 66*219b2ee8SDavid du Colombier 67*219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 68*219b2ee8SDavid du Colombier if (p->n == s) 69*219b2ee8SDavid du Colombier return p->s->maxel++; 70*219b2ee8SDavid du Colombier return Elcnt++; 71*219b2ee8SDavid du Colombier } 72*219b2ee8SDavid du Colombier 73*219b2ee8SDavid du Colombier void 74*219b2ee8SDavid du Colombier formdump(void) 75*219b2ee8SDavid du Colombier { ProcList *p; 76*219b2ee8SDavid du Colombier Lextok *f, *t; 77*219b2ee8SDavid du Colombier int cnt; 78*219b2ee8SDavid du Colombier 79*219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 80*219b2ee8SDavid du Colombier { if (!p->p) continue; 81*219b2ee8SDavid du Colombier cnt = -1; 82*219b2ee8SDavid du Colombier for (f = p->p; f; f = f->rgt) /* types */ 83*219b2ee8SDavid du Colombier for (t = f->lft; t; t = t->rgt) /* formals */ 84*219b2ee8SDavid du Colombier { if (t->ntyp != ',') 85*219b2ee8SDavid du Colombier t->sym->Nid = cnt--; /* overload Nid */ 86*219b2ee8SDavid du Colombier else 87*219b2ee8SDavid du Colombier t->lft->sym->Nid = cnt--; 88*219b2ee8SDavid du Colombier } 89*219b2ee8SDavid du Colombier } 90*219b2ee8SDavid du Colombier } 91*219b2ee8SDavid du Colombier 92*219b2ee8SDavid du Colombier int 93*219b2ee8SDavid du Colombier enable(Symbol *s, Lextok *n) /* s=name, n=actuals */ 94*219b2ee8SDavid du Colombier { ProcList *p; 95*219b2ee8SDavid du Colombier 96*219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 97*219b2ee8SDavid du Colombier if (strcmp(s->name, p->n->name) == 0) 98*219b2ee8SDavid du Colombier { runnable(p); 99*219b2ee8SDavid du Colombier setparams(run, p, n); 100*219b2ee8SDavid du Colombier return (nproc-nstop-1); /* pid */ 101*219b2ee8SDavid du Colombier } 102*219b2ee8SDavid du Colombier return 0; /* process not found */ 103*219b2ee8SDavid du Colombier } 104*219b2ee8SDavid du Colombier 105*219b2ee8SDavid du Colombier void 106*219b2ee8SDavid du Colombier start_claim(int n) 107*219b2ee8SDavid du Colombier { ProcList *p; 108*219b2ee8SDavid du Colombier 109*219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 110*219b2ee8SDavid du Colombier if (p->tn == n 111*219b2ee8SDavid du Colombier && strcmp(p->n->name, ":never:") == 0) 112*219b2ee8SDavid du Colombier { runnable(p); 113*219b2ee8SDavid du Colombier Have_claim = run->pid; /* was 1 */ 114*219b2ee8SDavid du Colombier return; 115*219b2ee8SDavid du Colombier } 116*219b2ee8SDavid du Colombier fatal("couldn't find claim", (char *) 0); 117*219b2ee8SDavid du Colombier } 118*219b2ee8SDavid du Colombier 119*219b2ee8SDavid du Colombier void 120*219b2ee8SDavid du Colombier wrapup(int fini) 121*219b2ee8SDavid du Colombier { 122*219b2ee8SDavid du Colombier if (nproc != nstop) 123*219b2ee8SDavid du Colombier { printf("#processes: %d\n", nproc-nstop); 124*219b2ee8SDavid du Colombier dumpglobals(); 125*219b2ee8SDavid du Colombier verbose &= ~1; /* no more globals */ 126*219b2ee8SDavid du Colombier verbose |= 32; /* add process states */ 127*219b2ee8SDavid du Colombier for (X = run; X; X = X->nxt) 128*219b2ee8SDavid du Colombier talk(X); 129*219b2ee8SDavid du Colombier } 130*219b2ee8SDavid du Colombier printf("%d processes created\n", nproc); 131*219b2ee8SDavid du Colombier 132*219b2ee8SDavid du Colombier if (xspin) exit(0); /* avoid an abort from xspin */ 133*219b2ee8SDavid du Colombier if (fini) exit(1); 134*219b2ee8SDavid du Colombier } 135*219b2ee8SDavid du Colombier 136*219b2ee8SDavid du Colombier static char is_blocked[256]; 137*219b2ee8SDavid du Colombier 138*219b2ee8SDavid du Colombier int 139*219b2ee8SDavid du Colombier p_blocked(int p) 140*219b2ee8SDavid du Colombier { register int i, j; 141*219b2ee8SDavid du Colombier 142*219b2ee8SDavid du Colombier is_blocked[p%256] = 1; 143*219b2ee8SDavid du Colombier for (i = j = 0; i < nproc - nstop; i++) 144*219b2ee8SDavid du Colombier j += is_blocked[i]; 145*219b2ee8SDavid du Colombier if (j >= nproc - nstop) 146*219b2ee8SDavid du Colombier { memset(is_blocked, 0, 256); 147*219b2ee8SDavid du Colombier return 1; 148*219b2ee8SDavid du Colombier } 149*219b2ee8SDavid du Colombier return 0; 150*219b2ee8SDavid du Colombier } 151*219b2ee8SDavid du Colombier 152*219b2ee8SDavid du Colombier Element * 153*219b2ee8SDavid du Colombier silent_moves(Element *e) 154*219b2ee8SDavid du Colombier { Element *f; 155*219b2ee8SDavid du Colombier 156*219b2ee8SDavid du Colombier switch (e->n->ntyp) { 157*219b2ee8SDavid du Colombier case GOTO: 158*219b2ee8SDavid du Colombier if (Rvous) break; 159*219b2ee8SDavid du Colombier f = get_lab(e->n, 1); 160*219b2ee8SDavid du Colombier cross_dsteps(e->n, f->n); 161*219b2ee8SDavid du Colombier return f; /* guard against goto cycles */ 162*219b2ee8SDavid du Colombier case UNLESS: 163*219b2ee8SDavid du Colombier return silent_moves(e->sub->this->frst); 164*219b2ee8SDavid du Colombier case NON_ATOMIC: 165*219b2ee8SDavid du Colombier case ATOMIC: 166*219b2ee8SDavid du Colombier case D_STEP: 167*219b2ee8SDavid du Colombier e->n->sl->this->last->nxt = e->nxt; 168*219b2ee8SDavid du Colombier return silent_moves(e->n->sl->this->frst); 169*219b2ee8SDavid du Colombier case '.': 170*219b2ee8SDavid du Colombier return e->nxt; 171*219b2ee8SDavid du Colombier } 172*219b2ee8SDavid du Colombier return e; 173*219b2ee8SDavid du Colombier } 174*219b2ee8SDavid du Colombier 175*219b2ee8SDavid du Colombier void 176*219b2ee8SDavid du Colombier sched(void) 177*219b2ee8SDavid du Colombier { Element *e; 178*219b2ee8SDavid du Colombier RunList *Y=0; /* previous process in run queue */ 179*219b2ee8SDavid du Colombier RunList *oX; 180*219b2ee8SDavid du Colombier SeqList *z; 181*219b2ee8SDavid du Colombier int j, k; 182*219b2ee8SDavid du Colombier short Choices[256]; 183*219b2ee8SDavid du Colombier 184*219b2ee8SDavid du Colombier if (dumptab) 185*219b2ee8SDavid du Colombier { formdump(); 186*219b2ee8SDavid du Colombier symdump(); 187*219b2ee8SDavid du Colombier dumplabels(); 188*219b2ee8SDavid du Colombier return; 189*219b2ee8SDavid du Colombier } 190*219b2ee8SDavid du Colombier 191*219b2ee8SDavid du Colombier if (has_enabled && u_sync > 0) 192*219b2ee8SDavid du Colombier { printf("spin: error: >> cannot use enabled() in "); 193*219b2ee8SDavid du Colombier printf("models with synchronous channels <<\n"); 194*219b2ee8SDavid du Colombier nr_errs++; 195*219b2ee8SDavid du Colombier } 196*219b2ee8SDavid du Colombier if (analyze) 197*219b2ee8SDavid du Colombier { gensrc(); 198*219b2ee8SDavid du Colombier return; 199*219b2ee8SDavid du Colombier } else if (s_trail) 200*219b2ee8SDavid du Colombier { match_trail(); 201*219b2ee8SDavid du Colombier return; 202*219b2ee8SDavid du Colombier } 203*219b2ee8SDavid du Colombier if (claimproc) 204*219b2ee8SDavid du Colombier printf("warning: claims are ignored in simulations\n"); 205*219b2ee8SDavid du Colombier 206*219b2ee8SDavid du Colombier if (Interactive) Tval = 1; 207*219b2ee8SDavid du Colombier 208*219b2ee8SDavid du Colombier X = run; 209*219b2ee8SDavid du Colombier while (X) 210*219b2ee8SDavid du Colombier { context = X->n; 211*219b2ee8SDavid du Colombier if (X->pc && X->pc->n) 212*219b2ee8SDavid du Colombier { lineno = X->pc->n->ln; 213*219b2ee8SDavid du Colombier Fname = X->pc->n->fn; 214*219b2ee8SDavid du Colombier } 215*219b2ee8SDavid du Colombier depth++; LastStep = ZE; 216*219b2ee8SDavid du Colombier oX = X; /* a rendezvous could change it */ 217*219b2ee8SDavid du Colombier if (e = eval_sub(X->pc)) 218*219b2ee8SDavid du Colombier { if (verbose&32 || verbose&4) 219*219b2ee8SDavid du Colombier { if (X == oX) 220*219b2ee8SDavid du Colombier { p_talk(X->pc, 1); 221*219b2ee8SDavid du Colombier printf(" ["); 222*219b2ee8SDavid du Colombier if (!LastStep) LastStep = X->pc; 223*219b2ee8SDavid du Colombier comment(stdout, LastStep->n, 0); 224*219b2ee8SDavid du Colombier printf("]\n"); 225*219b2ee8SDavid du Colombier } 226*219b2ee8SDavid du Colombier if (verbose&1) dumpglobals(); 227*219b2ee8SDavid du Colombier if (verbose&2) dumplocal(X); 228*219b2ee8SDavid du Colombier if (xspin) printf("\n"); /* xspin looks for these */ 229*219b2ee8SDavid du Colombier } 230*219b2ee8SDavid du Colombier oX->pc = e; LastX = X; 231*219b2ee8SDavid du Colombier if (!Interactive) Tval = 0; 232*219b2ee8SDavid du Colombier memset(is_blocked, 0, 256); 233*219b2ee8SDavid du Colombier 234*219b2ee8SDavid du Colombier /* new implementation of atomic sequences */ 235*219b2ee8SDavid du Colombier if (X->pc->status & (ATOM|L_ATOM)) 236*219b2ee8SDavid du Colombier continue; /* no switch */ 237*219b2ee8SDavid du Colombier } else 238*219b2ee8SDavid du Colombier { depth--; 239*219b2ee8SDavid du Colombier if (X->pc->n->ntyp == '@' 240*219b2ee8SDavid du Colombier && X->pid == (nproc-nstop-1)) 241*219b2ee8SDavid du Colombier { if (X != run) 242*219b2ee8SDavid du Colombier Y->nxt = X->nxt; 243*219b2ee8SDavid du Colombier else 244*219b2ee8SDavid du Colombier run = X->nxt; 245*219b2ee8SDavid du Colombier nstop++; 246*219b2ee8SDavid du Colombier if (verbose&4) 247*219b2ee8SDavid du Colombier { whoruns(1); 248*219b2ee8SDavid du Colombier printf("terminates\n"); 249*219b2ee8SDavid du Colombier } 250*219b2ee8SDavid du Colombier LastX = X; 251*219b2ee8SDavid du Colombier if (!Interactive) Tval = 0; 252*219b2ee8SDavid du Colombier if (nproc == nstop) break; 253*219b2ee8SDavid du Colombier memset(is_blocked, 0, 256); 254*219b2ee8SDavid du Colombier } else 255*219b2ee8SDavid du Colombier { if (!Interactive && p_blocked(X->pid)) 256*219b2ee8SDavid du Colombier { if (Tval) break; 257*219b2ee8SDavid du Colombier Tval = 1; 258*219b2ee8SDavid du Colombier printf("timeout\n"); 259*219b2ee8SDavid du Colombier } } } 260*219b2ee8SDavid du Colombier Y = X; 261*219b2ee8SDavid du Colombier if (Interactive) 262*219b2ee8SDavid du Colombier { 263*219b2ee8SDavid du Colombier try_again: printf("Select a statement\n"); 264*219b2ee8SDavid du Colombier for (X = run, k = 1; X; X = X->nxt) 265*219b2ee8SDavid du Colombier { if (X->pid > 255) break; 266*219b2ee8SDavid du Colombier Choices[X->pid] = 0; 267*219b2ee8SDavid du Colombier if (!X->pc) 268*219b2ee8SDavid du Colombier continue; 269*219b2ee8SDavid du Colombier Choices[X->pid] = k; 270*219b2ee8SDavid du Colombier X->pc = silent_moves(X->pc); 271*219b2ee8SDavid du Colombier if (!X->pc->sub && X->pc->n) 272*219b2ee8SDavid du Colombier { if (!xspin && !Enabled0(X->pc)) 273*219b2ee8SDavid du Colombier { k++; 274*219b2ee8SDavid du Colombier continue; 275*219b2ee8SDavid du Colombier } 276*219b2ee8SDavid du Colombier printf("\tchoice %d: ", k++); 277*219b2ee8SDavid du Colombier p_talk(X->pc, 0); 278*219b2ee8SDavid du Colombier if (!Enabled0(X->pc)) 279*219b2ee8SDavid du Colombier printf(" unexecutable,"); 280*219b2ee8SDavid du Colombier printf(" ["); 281*219b2ee8SDavid du Colombier comment(stdout, X->pc->n, 0); 282*219b2ee8SDavid du Colombier printf("]\n"); 283*219b2ee8SDavid du Colombier } else 284*219b2ee8SDavid du Colombier for (z = X->pc->sub, j=0; z; z = z->nxt) 285*219b2ee8SDavid du Colombier { Element *y = z->this->frst; 286*219b2ee8SDavid du Colombier if (!y) continue; 287*219b2ee8SDavid du Colombier 288*219b2ee8SDavid du Colombier if (!xspin && !Enabled0(y)) 289*219b2ee8SDavid du Colombier { k++; 290*219b2ee8SDavid du Colombier continue; 291*219b2ee8SDavid du Colombier } 292*219b2ee8SDavid du Colombier printf("\tchoice %d: ", k++); 293*219b2ee8SDavid du Colombier p_talk(X->pc, 0); 294*219b2ee8SDavid du Colombier if (!Enabled0(y)) 295*219b2ee8SDavid du Colombier printf(" unexecutable,"); 296*219b2ee8SDavid du Colombier printf(" ["); 297*219b2ee8SDavid du Colombier comment(stdout, y->n, 0); 298*219b2ee8SDavid du Colombier printf("]\n"); 299*219b2ee8SDavid du Colombier } } 300*219b2ee8SDavid du Colombier X = run; 301*219b2ee8SDavid du Colombier if (xspin) 302*219b2ee8SDavid du Colombier printf("Make Selection %d\n\n", k-1); 303*219b2ee8SDavid du Colombier else 304*219b2ee8SDavid du Colombier printf("Select [1-%d]: ", k-1); 305*219b2ee8SDavid du Colombier fflush(stdout); 306*219b2ee8SDavid du Colombier scanf("%d", &j); 307*219b2ee8SDavid du Colombier if (j < 1 || j >= k) 308*219b2ee8SDavid du Colombier { printf("\tchoice is outside range\n"); 309*219b2ee8SDavid du Colombier goto try_again; 310*219b2ee8SDavid du Colombier } 311*219b2ee8SDavid du Colombier SubChoice = 0; 312*219b2ee8SDavid du Colombier for (X = run; X; X = X->nxt) 313*219b2ee8SDavid du Colombier { if (!X->nxt 314*219b2ee8SDavid du Colombier || X->nxt->pid > 255 315*219b2ee8SDavid du Colombier || j < Choices[X->nxt->pid]) 316*219b2ee8SDavid du Colombier { 317*219b2ee8SDavid du Colombier SubChoice = 1+j-Choices[X->pid]; 318*219b2ee8SDavid du Colombier break; 319*219b2ee8SDavid du Colombier } 320*219b2ee8SDavid du Colombier } 321*219b2ee8SDavid du Colombier } else 322*219b2ee8SDavid du Colombier { j = (int) Rand()%(nproc-nstop); 323*219b2ee8SDavid du Colombier while (j-- >= 0) 324*219b2ee8SDavid du Colombier { X = X->nxt; 325*219b2ee8SDavid du Colombier if (!X) X = run; 326*219b2ee8SDavid du Colombier } } 327*219b2ee8SDavid du Colombier } 328*219b2ee8SDavid du Colombier context = ZS; 329*219b2ee8SDavid du Colombier wrapup(0); 330*219b2ee8SDavid du Colombier } 331*219b2ee8SDavid du Colombier 332*219b2ee8SDavid du Colombier int 333*219b2ee8SDavid du Colombier complete_rendez(void) 334*219b2ee8SDavid du Colombier { RunList *orun = X, *tmp; 335*219b2ee8SDavid du Colombier Element *s_was = LastStep; 336*219b2ee8SDavid du Colombier Element *e; 337*219b2ee8SDavid du Colombier 338*219b2ee8SDavid du Colombier if (s_trail) 339*219b2ee8SDavid du Colombier return 1; 340*219b2ee8SDavid du Colombier Rvous = 1; 341*219b2ee8SDavid du Colombier for (X = run; X; X = X->nxt) 342*219b2ee8SDavid du Colombier if (X != orun && (e = eval_sub(X->pc))) 343*219b2ee8SDavid du Colombier { if (verbose&4) 344*219b2ee8SDavid du Colombier { tmp = orun; orun = X; X = tmp; 345*219b2ee8SDavid du Colombier if (!s_was) s_was = X->pc; 346*219b2ee8SDavid du Colombier p_talk(s_was, 1); 347*219b2ee8SDavid du Colombier printf(" ["); 348*219b2ee8SDavid du Colombier comment(stdout, s_was->n, 0); 349*219b2ee8SDavid du Colombier printf("]\n"); 350*219b2ee8SDavid du Colombier tmp = orun; orun = X; X = tmp; 351*219b2ee8SDavid du Colombier /* printf("\t"); */ 352*219b2ee8SDavid du Colombier if (!LastStep) LastStep = X->pc; 353*219b2ee8SDavid du Colombier p_talk(LastStep, 1); 354*219b2ee8SDavid du Colombier printf(" ["); 355*219b2ee8SDavid du Colombier comment(stdout, LastStep->n, 0); 356*219b2ee8SDavid du Colombier printf("]\n"); 357*219b2ee8SDavid du Colombier } 358*219b2ee8SDavid du Colombier X->pc = e; 359*219b2ee8SDavid du Colombier Rvous = 0; 360*219b2ee8SDavid du Colombier return 1; 361*219b2ee8SDavid du Colombier } 362*219b2ee8SDavid du Colombier Rvous = 0; 363*219b2ee8SDavid du Colombier X = orun; 364*219b2ee8SDavid du Colombier return 0; 365*219b2ee8SDavid du Colombier } 366*219b2ee8SDavid du Colombier 367*219b2ee8SDavid du Colombier /***** Runtime - Local Variables *****/ 368*219b2ee8SDavid du Colombier 369*219b2ee8SDavid du Colombier void 370*219b2ee8SDavid du Colombier addsymbol(RunList *r, Symbol *s) 371*219b2ee8SDavid du Colombier { Symbol *t; 372*219b2ee8SDavid du Colombier int i; 373*219b2ee8SDavid du Colombier 374*219b2ee8SDavid du Colombier for (t = r->symtab; t; t = t->next) 375*219b2ee8SDavid du Colombier if (strcmp(t->name, s->name) == 0) 376*219b2ee8SDavid du Colombier return; /* it's already there */ 377*219b2ee8SDavid du Colombier 378*219b2ee8SDavid du Colombier t = (Symbol *) emalloc(sizeof(Symbol)); 379*219b2ee8SDavid du Colombier t->name = s->name; 380*219b2ee8SDavid du Colombier t->type = s->type; 381*219b2ee8SDavid du Colombier t->nel = s->nel; 382*219b2ee8SDavid du Colombier t->ini = s->ini; 383*219b2ee8SDavid du Colombier t->setat = depth; 384*219b2ee8SDavid du Colombier if (s->type != STRUCT) 385*219b2ee8SDavid du Colombier { if (s->val) /* if already initialized, copy info */ 386*219b2ee8SDavid du Colombier { t->val = (int *) emalloc(s->nel*sizeof(int)); 387*219b2ee8SDavid du Colombier for (i = 0; i < s->nel; i++) 388*219b2ee8SDavid du Colombier t->val[i] = s->val[i]; 389*219b2ee8SDavid du Colombier } else 390*219b2ee8SDavid du Colombier (void) checkvar(t, 0); /* initialize it */ 391*219b2ee8SDavid du Colombier } else 392*219b2ee8SDavid du Colombier { if (s->Sval) 393*219b2ee8SDavid du Colombier fatal("saw preinitialized struct %s", s->name); 394*219b2ee8SDavid du Colombier t->Slst = s->Slst; 395*219b2ee8SDavid du Colombier t->Snm = s->Snm; 396*219b2ee8SDavid du Colombier t->owner = s->owner; 397*219b2ee8SDavid du Colombier t->context = r->n; 398*219b2ee8SDavid du Colombier } 399*219b2ee8SDavid du Colombier t->next = r->symtab; /* add it */ 400*219b2ee8SDavid du Colombier r->symtab = t; 401*219b2ee8SDavid du Colombier } 402*219b2ee8SDavid du Colombier 403*219b2ee8SDavid du Colombier void 404*219b2ee8SDavid du Colombier oneparam(RunList *r, Lextok *t, Lextok *a, ProcList *p) 405*219b2ee8SDavid du Colombier { int k; int at, ft; 406*219b2ee8SDavid du Colombier RunList *oX = X; 407*219b2ee8SDavid du Colombier 408*219b2ee8SDavid du Colombier if (!a) 409*219b2ee8SDavid du Colombier fatal("missing actual parameters: '%s'", p->n->name); 410*219b2ee8SDavid du Colombier if (t->sym->nel != 1) 411*219b2ee8SDavid du Colombier fatal("array in parameter list, %s", t->sym->name); 412*219b2ee8SDavid du Colombier k = eval(a->lft); 413*219b2ee8SDavid du Colombier 414*219b2ee8SDavid du Colombier at = Sym_typ(a->lft); 415*219b2ee8SDavid du Colombier X = r; /* switch context */ 416*219b2ee8SDavid du Colombier ft = Sym_typ(t); 417*219b2ee8SDavid du Colombier 418*219b2ee8SDavid du Colombier if (at != ft && (at == CHAN || ft == CHAN)) 419*219b2ee8SDavid du Colombier { char buf[128], tag1[32], tag2[32]; 420*219b2ee8SDavid du Colombier (void) sputtype(tag1, ft); 421*219b2ee8SDavid du Colombier (void) sputtype(tag2, at); 422*219b2ee8SDavid du Colombier sprintf(buf, "type-clash in param-list of %s(..), (%s<-> %s)", 423*219b2ee8SDavid du Colombier p->n->name, tag1, tag2); 424*219b2ee8SDavid du Colombier non_fatal("%s", buf); 425*219b2ee8SDavid du Colombier } 426*219b2ee8SDavid du Colombier t->ntyp = NAME; 427*219b2ee8SDavid du Colombier addsymbol(r, t->sym); 428*219b2ee8SDavid du Colombier (void) setval(t, k); 429*219b2ee8SDavid du Colombier 430*219b2ee8SDavid du Colombier X = oX; 431*219b2ee8SDavid du Colombier } 432*219b2ee8SDavid du Colombier 433*219b2ee8SDavid du Colombier void 434*219b2ee8SDavid du Colombier setparams(RunList *r, ProcList *p, Lextok *q) 435*219b2ee8SDavid du Colombier { Lextok *f, *a; /* formal and actual pars */ 436*219b2ee8SDavid du Colombier Lextok *t; /* list of pars of 1 type */ 437*219b2ee8SDavid du Colombier 438*219b2ee8SDavid du Colombier if (q) 439*219b2ee8SDavid du Colombier { lineno = q->ln; 440*219b2ee8SDavid du Colombier Fname = q->fn; 441*219b2ee8SDavid du Colombier } 442*219b2ee8SDavid du Colombier for (f = p->p, a = q; f; f = f->rgt) /* one type at a time */ 443*219b2ee8SDavid du Colombier for (t = f->lft; t; t = t->rgt, a = (a)?a->rgt:a) 444*219b2ee8SDavid du Colombier { if (t->ntyp != ',') 445*219b2ee8SDavid du Colombier oneparam(r, t, a, p); /* plain var */ 446*219b2ee8SDavid du Colombier else 447*219b2ee8SDavid du Colombier oneparam(r, t->lft, a, p); /* expanded structure */ 448*219b2ee8SDavid du Colombier } 449*219b2ee8SDavid du Colombier } 450*219b2ee8SDavid du Colombier 451*219b2ee8SDavid du Colombier Symbol * 452*219b2ee8SDavid du Colombier findloc(Symbol *s) 453*219b2ee8SDavid du Colombier { Symbol *r; 454*219b2ee8SDavid du Colombier 455*219b2ee8SDavid du Colombier if (!X) 456*219b2ee8SDavid du Colombier { /* fatal("error, cannot eval '%s' (no proc)", s->name); */ 457*219b2ee8SDavid du Colombier return ZS; 458*219b2ee8SDavid du Colombier } 459*219b2ee8SDavid du Colombier for (r = X->symtab; r; r = r->next) 460*219b2ee8SDavid du Colombier if (strcmp(r->name, s->name) == 0) 461*219b2ee8SDavid du Colombier break; 462*219b2ee8SDavid du Colombier if (!r) 463*219b2ee8SDavid du Colombier { addsymbol(X, s); 464*219b2ee8SDavid du Colombier r = X->symtab; 465*219b2ee8SDavid du Colombier } 466*219b2ee8SDavid du Colombier return r; 467*219b2ee8SDavid du Colombier } 468*219b2ee8SDavid du Colombier 469*219b2ee8SDavid du Colombier int 470*219b2ee8SDavid du Colombier getlocal(Lextok *sn) 471*219b2ee8SDavid du Colombier { Symbol *r, *s = sn->sym; 472*219b2ee8SDavid du Colombier int n = eval(sn->lft); 473*219b2ee8SDavid du Colombier 474*219b2ee8SDavid du Colombier r = findloc(s); 475*219b2ee8SDavid du Colombier if (r && r->type == STRUCT) 476*219b2ee8SDavid du Colombier return Rval_struct(sn, r, 1); /* 1 = check init */ 477*219b2ee8SDavid du Colombier if (r) 478*219b2ee8SDavid du Colombier { if (n >= r->nel || n < 0) 479*219b2ee8SDavid du Colombier { printf("spin: indexing %s[%d] - size is %d\n", 480*219b2ee8SDavid du Colombier s->name, n, r->nel); 481*219b2ee8SDavid du Colombier non_fatal("array indexing error %s", s->name); 482*219b2ee8SDavid du Colombier } else 483*219b2ee8SDavid du Colombier { return cast_val(r->type, r->val[n]); 484*219b2ee8SDavid du Colombier } } 485*219b2ee8SDavid du Colombier 486*219b2ee8SDavid du Colombier return 0; 487*219b2ee8SDavid du Colombier } 488*219b2ee8SDavid du Colombier 489*219b2ee8SDavid du Colombier int 490*219b2ee8SDavid du Colombier setlocal(Lextok *p, int m) 491*219b2ee8SDavid du Colombier { Symbol *r = findloc(p->sym); 492*219b2ee8SDavid du Colombier int n = eval(p->lft); 493*219b2ee8SDavid du Colombier 494*219b2ee8SDavid du Colombier if (!r) return 1; 495*219b2ee8SDavid du Colombier 496*219b2ee8SDavid du Colombier if (n >= r->nel || n < 0) 497*219b2ee8SDavid du Colombier { printf("spin: indexing %s[%d] - size is %d\n", 498*219b2ee8SDavid du Colombier r->name, n, r->nel); 499*219b2ee8SDavid du Colombier non_fatal("array indexing error %s", r->name); 500*219b2ee8SDavid du Colombier } else 501*219b2ee8SDavid du Colombier { if (r->type == STRUCT) 502*219b2ee8SDavid du Colombier (void) Lval_struct(p, r, 1, m); /* 1 = check init */ 503*219b2ee8SDavid du Colombier else 504*219b2ee8SDavid du Colombier { r->val[n] = m; 505*219b2ee8SDavid du Colombier r->setat = depth; 506*219b2ee8SDavid du Colombier } } 507*219b2ee8SDavid du Colombier 508*219b2ee8SDavid du Colombier return 1; 509*219b2ee8SDavid du Colombier } 510*219b2ee8SDavid du Colombier 511*219b2ee8SDavid du Colombier void 512*219b2ee8SDavid du Colombier whoruns(int lnr) 513*219b2ee8SDavid du Colombier { if (!X) return; 514*219b2ee8SDavid du Colombier 515*219b2ee8SDavid du Colombier if (lnr) printf("%3d: ", depth); 516*219b2ee8SDavid du Colombier printf("proc "); 517*219b2ee8SDavid du Colombier if (Have_claim) 518*219b2ee8SDavid du Colombier { if (X->pid == Have_claim) 519*219b2ee8SDavid du Colombier printf(" -"); 520*219b2ee8SDavid du Colombier else if (X->pid > Have_claim) 521*219b2ee8SDavid du Colombier printf("%2d", X->pid-1); 522*219b2ee8SDavid du Colombier else 523*219b2ee8SDavid du Colombier printf("%2d", X->pid); 524*219b2ee8SDavid du Colombier } else 525*219b2ee8SDavid du Colombier printf("%2d", X->pid); 526*219b2ee8SDavid du Colombier printf(" (%s) ", X->n->name); 527*219b2ee8SDavid du Colombier } 528*219b2ee8SDavid du Colombier 529*219b2ee8SDavid du Colombier void 530*219b2ee8SDavid du Colombier talk(RunList *r) 531*219b2ee8SDavid du Colombier { 532*219b2ee8SDavid du Colombier if (verbose&32 || verbose&4) 533*219b2ee8SDavid du Colombier { p_talk(r->pc, 1); 534*219b2ee8SDavid du Colombier printf("\n"); 535*219b2ee8SDavid du Colombier if (verbose&1) dumpglobals(); 536*219b2ee8SDavid du Colombier if (verbose&2) dumplocal(r); 537*219b2ee8SDavid du Colombier } 538*219b2ee8SDavid du Colombier } 539*219b2ee8SDavid du Colombier 540*219b2ee8SDavid du Colombier void 541*219b2ee8SDavid du Colombier p_talk(Element *e, int lnr) 542*219b2ee8SDavid du Colombier { 543*219b2ee8SDavid du Colombier whoruns(lnr); 544*219b2ee8SDavid du Colombier if (e) 545*219b2ee8SDavid du Colombier printf("line %3d %s (state %d)", 546*219b2ee8SDavid du Colombier e->n?e->n->ln:-1, 547*219b2ee8SDavid du Colombier e->n?e->n->fn->name:"-", 548*219b2ee8SDavid du Colombier e->seqno); 549*219b2ee8SDavid du Colombier } 550*219b2ee8SDavid du Colombier 551*219b2ee8SDavid du Colombier int 552*219b2ee8SDavid du Colombier remotelab(Lextok *n) 553*219b2ee8SDavid du Colombier { int i; 554*219b2ee8SDavid du Colombier 555*219b2ee8SDavid du Colombier lineno = n->ln; 556*219b2ee8SDavid du Colombier Fname = n->fn; 557*219b2ee8SDavid du Colombier if (n->sym->type) 558*219b2ee8SDavid du Colombier fatal("not a labelname: '%s'", n->sym->name); 559*219b2ee8SDavid du Colombier if ((i = find_lab(n->sym, n->lft->sym)) == 0) 560*219b2ee8SDavid du Colombier fatal("unknown labelname: %s", n->sym->name); 561*219b2ee8SDavid du Colombier return i; 562*219b2ee8SDavid du Colombier } 563*219b2ee8SDavid du Colombier 564*219b2ee8SDavid du Colombier int 565*219b2ee8SDavid du Colombier remotevar(Lextok *n) 566*219b2ee8SDavid du Colombier { int pno, i, trick=0; 567*219b2ee8SDavid du Colombier RunList *Y; 568*219b2ee8SDavid du Colombier 569*219b2ee8SDavid du Colombier lineno = n->ln; 570*219b2ee8SDavid du Colombier Fname = n->fn; 571*219b2ee8SDavid du Colombier if (!n->lft->lft) 572*219b2ee8SDavid du Colombier { non_fatal("missing pid in %s", n->sym->name); 573*219b2ee8SDavid du Colombier return 0; 574*219b2ee8SDavid du Colombier } 575*219b2ee8SDavid du Colombier 576*219b2ee8SDavid du Colombier pno = eval(n->lft->lft); /* pid - can cause recursive call */ 577*219b2ee8SDavid du Colombier TryAgain: 578*219b2ee8SDavid du Colombier i = nproc - nstop; 579*219b2ee8SDavid du Colombier for (Y = run; Y; Y = Y->nxt) 580*219b2ee8SDavid du Colombier if (--i == pno) 581*219b2ee8SDavid du Colombier { if (strcmp(Y->n->name, n->lft->sym->name) != 0) 582*219b2ee8SDavid du Colombier { if (!trick && Have_claim) 583*219b2ee8SDavid du Colombier { trick = 1; pno++; 584*219b2ee8SDavid du Colombier /* assumes user guessed the pid */ 585*219b2ee8SDavid du Colombier goto TryAgain; 586*219b2ee8SDavid du Colombier } 587*219b2ee8SDavid du Colombier printf("remote ref %s[%d] refers to %s\n", 588*219b2ee8SDavid du Colombier n->lft->sym->name, pno, Y->n->name); 589*219b2ee8SDavid du Colombier non_fatal("wrong proctype %s", Y->n->name); 590*219b2ee8SDavid du Colombier } 591*219b2ee8SDavid du Colombier if (strcmp(n->sym->name, "_p") == 0) 592*219b2ee8SDavid du Colombier return Y->pc->seqno; 593*219b2ee8SDavid du Colombier break; 594*219b2ee8SDavid du Colombier } 595*219b2ee8SDavid du Colombier printf("remote ref: %s[%d] ", n->lft->sym->name, pno); 596*219b2ee8SDavid du Colombier non_fatal("%s not found", n->sym->name); 597*219b2ee8SDavid du Colombier 598*219b2ee8SDavid du Colombier return 0; 599*219b2ee8SDavid du Colombier } 600