1219b2ee8SDavid du Colombier /***** spin: sched.c *****/ 2219b2ee8SDavid du Colombier 3312a1df1SDavid du Colombier /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ 47dd7cddfSDavid du Colombier /* All Rights Reserved. This software is for educational purposes only. */ 5312a1df1SDavid du Colombier /* No guarantee whatsoever is expressed or implied by the distribution of */ 6312a1df1SDavid du Colombier /* this code. Permission is given to distribute this code provided that */ 7312a1df1SDavid du Colombier /* this introductory message is not removed and no monies are exchanged. */ 8312a1df1SDavid du Colombier /* Software written by Gerard J. Holzmann. For tool documentation see: */ 9312a1df1SDavid du Colombier /* http://spinroot.com/ */ 10312a1df1SDavid du Colombier /* Send all bug-reports and/or questions to: bugs@spinroot.com */ 11219b2ee8SDavid du Colombier 127dd7cddfSDavid du Colombier #include <stdlib.h> 13219b2ee8SDavid du Colombier #include "spin.h" 14219b2ee8SDavid du Colombier #include "y.tab.h" 15219b2ee8SDavid du Colombier 167dd7cddfSDavid du Colombier extern int verbose, s_trail, analyze, no_wrapup; 177dd7cddfSDavid du Colombier extern char *claimproc, *eventmap, Buf[]; 187dd7cddfSDavid du Colombier extern Ordered *all_names; 19219b2ee8SDavid du Colombier extern Symbol *Fname, *context; 207dd7cddfSDavid du Colombier extern int lineno, nr_errs, dumptab, xspin, jumpsteps, columns; 21312a1df1SDavid du Colombier extern int u_sync, Elcnt, interactive, TstOnly, cutoff; 22312a1df1SDavid du Colombier extern short has_enabled; 23*00d97012SDavid du Colombier extern int limited_vis, old_scope_rules, product, nclaims; 24219b2ee8SDavid du Colombier 25219b2ee8SDavid du Colombier RunList *X = (RunList *) 0; 26219b2ee8SDavid du Colombier RunList *run = (RunList *) 0; 27219b2ee8SDavid du Colombier RunList *LastX = (RunList *) 0; /* previous executing proc */ 28219b2ee8SDavid du Colombier ProcList *rdy = (ProcList *) 0; 29219b2ee8SDavid du Colombier Element *LastStep = ZE; 307dd7cddfSDavid du Colombier int nproc=0, nstop=0, Tval=0; 317dd7cddfSDavid du Colombier int Rvous=0, depth=0, nrRdy=0, MadeChoice; 327dd7cddfSDavid du Colombier short Have_claim=0, Skip_claim=0; 337dd7cddfSDavid du Colombier 347dd7cddfSDavid du Colombier static int Priority_Sum = 0; 357dd7cddfSDavid du Colombier static void setlocals(RunList *); 367dd7cddfSDavid du Colombier static void setparams(RunList *, ProcList *, Lextok *); 377dd7cddfSDavid du Colombier static void talk(RunList *); 38219b2ee8SDavid du Colombier 39219b2ee8SDavid du Colombier void 407dd7cddfSDavid du Colombier runnable(ProcList *p, int weight, int noparams) 41219b2ee8SDavid du Colombier { RunList *r = (RunList *) emalloc(sizeof(RunList)); 42219b2ee8SDavid du Colombier 43219b2ee8SDavid du Colombier r->n = p->n; 44219b2ee8SDavid du Colombier r->tn = p->tn; 45*00d97012SDavid du Colombier r->b = p->b; 46312a1df1SDavid du Colombier r->pid = nproc++ - nstop + Skip_claim; 47312a1df1SDavid du Colombier 48*00d97012SDavid du Colombier if (!noparams && ((verbose&4) || (verbose&32))) 49*00d97012SDavid du Colombier printf("Starting %s with pid %d\n", 50*00d97012SDavid du Colombier p->n?p->n->name:"--", r->pid); 51312a1df1SDavid du Colombier 52312a1df1SDavid du Colombier if (!p->s) 53*00d97012SDavid du Colombier fatal("parsing error, no sequence %s", 54*00d97012SDavid du Colombier p->n?p->n->name:"--"); 55312a1df1SDavid du Colombier 56312a1df1SDavid du Colombier r->pc = huntele(p->s->frst, p->s->frst->status, -1); 577dd7cddfSDavid du Colombier r->ps = p->s; 58312a1df1SDavid du Colombier 59312a1df1SDavid du Colombier if (p->s->last) 607dd7cddfSDavid du Colombier p->s->last->status |= ENDSTATE; /* normal end state */ 61312a1df1SDavid du Colombier 62219b2ee8SDavid du Colombier r->nxt = run; 637dd7cddfSDavid du Colombier r->prov = p->prov; 647dd7cddfSDavid du Colombier r->priority = weight; 65*00d97012SDavid du Colombier 667dd7cddfSDavid du Colombier if (noparams) setlocals(r); 677dd7cddfSDavid du Colombier Priority_Sum += weight; 68*00d97012SDavid du Colombier 69219b2ee8SDavid du Colombier run = r; 70219b2ee8SDavid du Colombier } 71219b2ee8SDavid du Colombier 72219b2ee8SDavid du Colombier ProcList * 73*00d97012SDavid du Colombier ready(Symbol *n, Lextok *p, Sequence *s, int det, Lextok *prov, enum btypes b) 747dd7cddfSDavid du Colombier /* n=name, p=formals, s=body det=deterministic prov=provided */ 75219b2ee8SDavid du Colombier { ProcList *r = (ProcList *) emalloc(sizeof(ProcList)); 76219b2ee8SDavid du Colombier Lextok *fp, *fpt; int j; extern int Npars; 77219b2ee8SDavid du Colombier 78219b2ee8SDavid du Colombier r->n = n; 79219b2ee8SDavid du Colombier r->p = p; 80219b2ee8SDavid du Colombier r->s = s; 81*00d97012SDavid du Colombier r->b = b; 827dd7cddfSDavid du Colombier r->prov = prov; 83219b2ee8SDavid du Colombier r->tn = nrRdy++; 84*00d97012SDavid du Colombier if (det != 0 && det != 1) 85*00d97012SDavid du Colombier { fprintf(stderr, "spin: bad value for det (cannot happen)\n"); 86*00d97012SDavid du Colombier } 877dd7cddfSDavid du Colombier r->det = (short) det; 88219b2ee8SDavid du Colombier r->nxt = rdy; 89219b2ee8SDavid du Colombier rdy = r; 90219b2ee8SDavid du Colombier 91219b2ee8SDavid du Colombier for (fp = p, j = 0; fp; fp = fp->rgt) 92219b2ee8SDavid du Colombier for (fpt = fp->lft; fpt; fpt = fpt->rgt) 93219b2ee8SDavid du Colombier j++; /* count # of parameters */ 94219b2ee8SDavid du Colombier Npars = max(Npars, j); 95219b2ee8SDavid du Colombier 96219b2ee8SDavid du Colombier return rdy; 97219b2ee8SDavid du Colombier } 98219b2ee8SDavid du Colombier 99219b2ee8SDavid du Colombier int 100219b2ee8SDavid du Colombier find_maxel(Symbol *s) 101219b2ee8SDavid du Colombier { ProcList *p; 102219b2ee8SDavid du Colombier 103219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 104219b2ee8SDavid du Colombier if (p->n == s) 105219b2ee8SDavid du Colombier return p->s->maxel++; 106219b2ee8SDavid du Colombier return Elcnt++; 107219b2ee8SDavid du Colombier } 108219b2ee8SDavid du Colombier 1097dd7cddfSDavid du Colombier static void 110219b2ee8SDavid du Colombier formdump(void) 111219b2ee8SDavid du Colombier { ProcList *p; 112219b2ee8SDavid du Colombier Lextok *f, *t; 113219b2ee8SDavid du Colombier int cnt; 114219b2ee8SDavid du Colombier 115219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 116219b2ee8SDavid du Colombier { if (!p->p) continue; 117219b2ee8SDavid du Colombier cnt = -1; 118219b2ee8SDavid du Colombier for (f = p->p; f; f = f->rgt) /* types */ 119219b2ee8SDavid du Colombier for (t = f->lft; t; t = t->rgt) /* formals */ 120219b2ee8SDavid du Colombier { if (t->ntyp != ',') 121219b2ee8SDavid du Colombier t->sym->Nid = cnt--; /* overload Nid */ 122219b2ee8SDavid du Colombier else 123219b2ee8SDavid du Colombier t->lft->sym->Nid = cnt--; 124219b2ee8SDavid du Colombier } 125219b2ee8SDavid du Colombier } 126219b2ee8SDavid du Colombier } 127219b2ee8SDavid du Colombier 1287dd7cddfSDavid du Colombier void 1297dd7cddfSDavid du Colombier announce(char *w) 1307dd7cddfSDavid du Colombier { 1317dd7cddfSDavid du Colombier if (columns) 1327dd7cddfSDavid du Colombier { extern char Buf[]; 1337dd7cddfSDavid du Colombier extern int firstrow; 1347dd7cddfSDavid du Colombier firstrow = 1; 1357dd7cddfSDavid du Colombier if (columns == 2) 1367dd7cddfSDavid du Colombier { sprintf(Buf, "%d:%s", 137312a1df1SDavid du Colombier run->pid - Have_claim, run->n->name); 138312a1df1SDavid du Colombier pstext(run->pid - Have_claim, Buf); 1397dd7cddfSDavid du Colombier } else 1407dd7cddfSDavid du Colombier printf("proc %d = %s\n", 1417dd7cddfSDavid du Colombier run->pid - Have_claim, run->n->name); 1427dd7cddfSDavid du Colombier return; 1437dd7cddfSDavid du Colombier } 144312a1df1SDavid du Colombier 1457dd7cddfSDavid du Colombier if (dumptab 1467dd7cddfSDavid du Colombier || analyze 147*00d97012SDavid du Colombier || product 1487dd7cddfSDavid du Colombier || s_trail 1497dd7cddfSDavid du Colombier || !(verbose&4)) 1507dd7cddfSDavid du Colombier return; 151312a1df1SDavid du Colombier 1527dd7cddfSDavid du Colombier if (w) 1537dd7cddfSDavid du Colombier printf(" 0: proc - (%s) ", w); 1547dd7cddfSDavid du Colombier else 1557dd7cddfSDavid du Colombier whoruns(1); 1567dd7cddfSDavid du Colombier printf("creates proc %2d (%s)", 1577dd7cddfSDavid du Colombier run->pid - Have_claim, 1587dd7cddfSDavid du Colombier run->n->name); 1597dd7cddfSDavid du Colombier if (run->priority > 1) 1607dd7cddfSDavid du Colombier printf(" priority %d", run->priority); 1617dd7cddfSDavid du Colombier printf("\n"); 1627dd7cddfSDavid du Colombier } 163219b2ee8SDavid du Colombier 164312a1df1SDavid du Colombier #ifndef MAXP 165312a1df1SDavid du Colombier #define MAXP 255 /* matches max nr of processes in verifier */ 166312a1df1SDavid du Colombier #endif 167312a1df1SDavid du Colombier 1687dd7cddfSDavid du Colombier int 1697dd7cddfSDavid du Colombier enable(Lextok *m) 1707dd7cddfSDavid du Colombier { ProcList *p; 1717dd7cddfSDavid du Colombier Symbol *s = m->sym; /* proctype name */ 1727dd7cddfSDavid du Colombier Lextok *n = m->lft; /* actual parameters */ 1737dd7cddfSDavid du Colombier 1747dd7cddfSDavid du Colombier if (m->val < 1) m->val = 1; /* minimum priority */ 175219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 176219b2ee8SDavid du Colombier if (strcmp(s->name, p->n->name) == 0) 177312a1df1SDavid du Colombier { if (nproc-nstop >= MAXP) 178312a1df1SDavid du Colombier { printf("spin: too many processes (%d max)\n", MAXP); 179312a1df1SDavid du Colombier break; 180312a1df1SDavid du Colombier } 181312a1df1SDavid du Colombier runnable(p, m->val, 0); 1827dd7cddfSDavid du Colombier announce((char *) 0); 183219b2ee8SDavid du Colombier setparams(run, p, n); 1847dd7cddfSDavid du Colombier setlocals(run); /* after setparams */ 185312a1df1SDavid du Colombier return run->pid - Have_claim + Skip_claim; /* effective simu pid */ 186219b2ee8SDavid du Colombier } 187219b2ee8SDavid du Colombier return 0; /* process not found */ 188219b2ee8SDavid du Colombier } 189219b2ee8SDavid du Colombier 190219b2ee8SDavid du Colombier void 191f3793cddSDavid du Colombier check_param_count(int i, Lextok *m) 192f3793cddSDavid du Colombier { ProcList *p; 193f3793cddSDavid du Colombier Symbol *s = m->sym; /* proctype name */ 194f3793cddSDavid du Colombier Lextok *f, *t; /* formal pars */ 195f3793cddSDavid du Colombier int cnt = 0; 196f3793cddSDavid du Colombier 197f3793cddSDavid du Colombier for (p = rdy; p; p = p->nxt) 198f3793cddSDavid du Colombier { if (strcmp(s->name, p->n->name) == 0) 199f3793cddSDavid du Colombier { if (m->lft) /* actual param list */ 200f3793cddSDavid du Colombier { lineno = m->lft->ln; 201f3793cddSDavid du Colombier Fname = m->lft->fn; 202f3793cddSDavid du Colombier } 203f3793cddSDavid du Colombier for (f = p->p; f; f = f->rgt) /* one type at a time */ 204f3793cddSDavid du Colombier for (t = f->lft; t; t = t->rgt) /* count formal params */ 205f3793cddSDavid du Colombier { cnt++; 206f3793cddSDavid du Colombier } 207f3793cddSDavid du Colombier if (i != cnt) 208f3793cddSDavid du Colombier { printf("spin: saw %d parameters, expected %d\n", i, cnt); 209f3793cddSDavid du Colombier non_fatal("wrong number of parameters", ""); 210f3793cddSDavid du Colombier } 211f3793cddSDavid du Colombier break; 212f3793cddSDavid du Colombier } } 213f3793cddSDavid du Colombier } 214f3793cddSDavid du Colombier 215f3793cddSDavid du Colombier void 216219b2ee8SDavid du Colombier start_claim(int n) 217219b2ee8SDavid du Colombier { ProcList *p; 2187dd7cddfSDavid du Colombier RunList *r, *q = (RunList *) 0; 219219b2ee8SDavid du Colombier 220219b2ee8SDavid du Colombier for (p = rdy; p; p = p->nxt) 221*00d97012SDavid du Colombier if (p->tn == n && p->b == N_CLAIM) 2227dd7cddfSDavid du Colombier { runnable(p, 1, 1); 2237dd7cddfSDavid du Colombier goto found; 224219b2ee8SDavid du Colombier } 225*00d97012SDavid du Colombier printf("spin: couldn't find claim %d (ignored)\n", n); 226*00d97012SDavid du Colombier if (verbose&32) 227*00d97012SDavid du Colombier for (p = rdy; p; p = p->nxt) 228*00d97012SDavid du Colombier printf("\t%d = %s\n", p->tn, p->n->name); 229*00d97012SDavid du Colombier 2307dd7cddfSDavid du Colombier Skip_claim = 1; 2317dd7cddfSDavid du Colombier goto done; 2327dd7cddfSDavid du Colombier found: 233312a1df1SDavid du Colombier /* move claim to far end of runlist, and reassign it pid 0 */ 2347dd7cddfSDavid du Colombier if (columns == 2) 235*00d97012SDavid du Colombier { extern char Buf[]; 236*00d97012SDavid du Colombier depth = 0; 237*00d97012SDavid du Colombier sprintf(Buf, "%d:%s", 0, p->n->name); 238*00d97012SDavid du Colombier pstext(0, Buf); 2397dd7cddfSDavid du Colombier for (r = run; r; r = r->nxt) 240*00d97012SDavid du Colombier { if (r->b != N_CLAIM) 241*00d97012SDavid du Colombier { sprintf(Buf, "%d:%s", r->pid+1, r->n->name); 2427dd7cddfSDavid du Colombier pstext(r->pid+1, Buf); 243*00d97012SDavid du Colombier } } } 244312a1df1SDavid du Colombier 245312a1df1SDavid du Colombier if (run->pid == 0) return; /* it is the first process started */ 2467dd7cddfSDavid du Colombier 2477dd7cddfSDavid du Colombier q = run; run = run->nxt; 248312a1df1SDavid du Colombier q->pid = 0; q->nxt = (RunList *) 0; /* remove */ 2497dd7cddfSDavid du Colombier done: 250312a1df1SDavid du Colombier Have_claim = 1; 2517dd7cddfSDavid du Colombier for (r = run; r; r = r->nxt) 252312a1df1SDavid du Colombier { r->pid = r->pid+Have_claim; /* adjust */ 2537dd7cddfSDavid du Colombier if (!r->nxt) 2547dd7cddfSDavid du Colombier { r->nxt = q; 2557dd7cddfSDavid du Colombier break; 2567dd7cddfSDavid du Colombier } } 257312a1df1SDavid du Colombier } 258312a1df1SDavid du Colombier 259312a1df1SDavid du Colombier int 260312a1df1SDavid du Colombier f_pid(char *n) 261312a1df1SDavid du Colombier { RunList *r; 262312a1df1SDavid du Colombier int rval = -1; 263312a1df1SDavid du Colombier 264312a1df1SDavid du Colombier for (r = run; r; r = r->nxt) 265312a1df1SDavid du Colombier if (strcmp(n, r->n->name) == 0) 266312a1df1SDavid du Colombier { if (rval >= 0) 267312a1df1SDavid du Colombier { printf("spin: remote ref to proctype %s, ", n); 268312a1df1SDavid du Colombier printf("has more than one match: %d and %d\n", 269312a1df1SDavid du Colombier rval, r->pid); 270312a1df1SDavid du Colombier } else 271312a1df1SDavid du Colombier rval = r->pid; 272312a1df1SDavid du Colombier } 273312a1df1SDavid du Colombier return rval; 274219b2ee8SDavid du Colombier } 275219b2ee8SDavid du Colombier 276219b2ee8SDavid du Colombier void 277219b2ee8SDavid du Colombier wrapup(int fini) 278219b2ee8SDavid du Colombier { 279312a1df1SDavid du Colombier limited_vis = 0; 2807dd7cddfSDavid du Colombier if (columns) 2817dd7cddfSDavid du Colombier { extern void putpostlude(void); 2827dd7cddfSDavid du Colombier if (columns == 2) putpostlude(); 2837dd7cddfSDavid du Colombier if (!no_wrapup) 2847dd7cddfSDavid du Colombier printf("-------------\nfinal state:\n-------------\n"); 2857dd7cddfSDavid du Colombier } 2867dd7cddfSDavid du Colombier if (no_wrapup) 2877dd7cddfSDavid du Colombier goto short_cut; 288219b2ee8SDavid du Colombier if (nproc != nstop) 2897dd7cddfSDavid du Colombier { int ov = verbose; 290312a1df1SDavid du Colombier printf("#processes: %d\n", nproc-nstop - Have_claim + Skip_claim); 2917dd7cddfSDavid du Colombier verbose &= ~4; 292219b2ee8SDavid du Colombier dumpglobals(); 2937dd7cddfSDavid du Colombier verbose = ov; 294219b2ee8SDavid du Colombier verbose &= ~1; /* no more globals */ 295219b2ee8SDavid du Colombier verbose |= 32; /* add process states */ 296219b2ee8SDavid du Colombier for (X = run; X; X = X->nxt) 297219b2ee8SDavid du Colombier talk(X); 2987dd7cddfSDavid du Colombier verbose = ov; /* restore */ 299219b2ee8SDavid du Colombier } 300312a1df1SDavid du Colombier printf("%d process%s created\n", 301312a1df1SDavid du Colombier nproc - Have_claim + Skip_claim, 302312a1df1SDavid du Colombier (xspin || nproc!=1)?"es":""); 3037dd7cddfSDavid du Colombier short_cut: 3047dd7cddfSDavid du Colombier if (xspin) alldone(0); /* avoid an abort from xspin */ 3057dd7cddfSDavid du Colombier if (fini) alldone(1); 306219b2ee8SDavid du Colombier } 307219b2ee8SDavid du Colombier 308219b2ee8SDavid du Colombier static char is_blocked[256]; 309219b2ee8SDavid du Colombier 3107dd7cddfSDavid du Colombier static int 311219b2ee8SDavid du Colombier p_blocked(int p) 312312a1df1SDavid du Colombier { int i, j; 313219b2ee8SDavid du Colombier 314219b2ee8SDavid du Colombier is_blocked[p%256] = 1; 315219b2ee8SDavid du Colombier for (i = j = 0; i < nproc - nstop; i++) 316219b2ee8SDavid du Colombier j += is_blocked[i]; 317219b2ee8SDavid du Colombier if (j >= nproc - nstop) 318219b2ee8SDavid du Colombier { memset(is_blocked, 0, 256); 319219b2ee8SDavid du Colombier return 1; 320219b2ee8SDavid du Colombier } 321219b2ee8SDavid du Colombier return 0; 322219b2ee8SDavid du Colombier } 323219b2ee8SDavid du Colombier 3247dd7cddfSDavid du Colombier static Element * 325219b2ee8SDavid du Colombier silent_moves(Element *e) 326219b2ee8SDavid du Colombier { Element *f; 327219b2ee8SDavid du Colombier 328f3793cddSDavid du Colombier if (e->n) 329219b2ee8SDavid du Colombier switch (e->n->ntyp) { 330219b2ee8SDavid du Colombier case GOTO: 331219b2ee8SDavid du Colombier if (Rvous) break; 332219b2ee8SDavid du Colombier f = get_lab(e->n, 1); 333219b2ee8SDavid du Colombier cross_dsteps(e->n, f->n); 334219b2ee8SDavid du Colombier return f; /* guard against goto cycles */ 335219b2ee8SDavid du Colombier case UNLESS: 336219b2ee8SDavid du Colombier return silent_moves(e->sub->this->frst); 337219b2ee8SDavid du Colombier case NON_ATOMIC: 338219b2ee8SDavid du Colombier case ATOMIC: 339219b2ee8SDavid du Colombier case D_STEP: 340219b2ee8SDavid du Colombier e->n->sl->this->last->nxt = e->nxt; 341219b2ee8SDavid du Colombier return silent_moves(e->n->sl->this->frst); 342219b2ee8SDavid du Colombier case '.': 3437dd7cddfSDavid du Colombier return silent_moves(e->nxt); 344219b2ee8SDavid du Colombier } 345219b2ee8SDavid du Colombier return e; 346219b2ee8SDavid du Colombier } 347219b2ee8SDavid du Colombier 348f3793cddSDavid du Colombier static RunList * 349f3793cddSDavid du Colombier pickproc(RunList *Y) 3507dd7cddfSDavid du Colombier { SeqList *z; Element *has_else; 3517dd7cddfSDavid du Colombier short Choices[256]; 352312a1df1SDavid du Colombier int j, k, nr_else = 0; 3537dd7cddfSDavid du Colombier 3547dd7cddfSDavid du Colombier if (nproc <= nstop+1) 3557dd7cddfSDavid du Colombier { X = run; 356f3793cddSDavid du Colombier return NULL; 3577dd7cddfSDavid du Colombier } 3587dd7cddfSDavid du Colombier if (!interactive || depth < jumpsteps) 3597dd7cddfSDavid du Colombier { /* was: j = (int) Rand()%(nproc-nstop); */ 3607dd7cddfSDavid du Colombier if (Priority_Sum < nproc-nstop) 3617dd7cddfSDavid du Colombier fatal("cannot happen - weights", (char *)0); 3627dd7cddfSDavid du Colombier j = (int) Rand()%Priority_Sum; 363f3793cddSDavid du Colombier 3647dd7cddfSDavid du Colombier while (j - X->priority >= 0) 3657dd7cddfSDavid du Colombier { j -= X->priority; 366f3793cddSDavid du Colombier Y = X; 3677dd7cddfSDavid du Colombier X = X->nxt; 368f3793cddSDavid du Colombier if (!X) { Y = NULL; X = run; } 3697dd7cddfSDavid du Colombier } 3707dd7cddfSDavid du Colombier } else 3717dd7cddfSDavid du Colombier { int only_choice = -1; 3727dd7cddfSDavid du Colombier int no_choice = 0, proc_no_ch, proc_k; 373f3793cddSDavid du Colombier 374f3793cddSDavid du Colombier Tval = 0; /* new 4.2.6 */ 3757dd7cddfSDavid du Colombier try_again: printf("Select a statement\n"); 3767dd7cddfSDavid du Colombier try_more: for (X = run, k = 1; X; X = X->nxt) 3777dd7cddfSDavid du Colombier { if (X->pid > 255) break; 3787dd7cddfSDavid du Colombier 3797dd7cddfSDavid du Colombier Choices[X->pid] = (short) k; 3807dd7cddfSDavid du Colombier 3817dd7cddfSDavid du Colombier if (!X->pc 3827dd7cddfSDavid du Colombier || (X->prov && !eval(X->prov))) 3837dd7cddfSDavid du Colombier { if (X == run) 3847dd7cddfSDavid du Colombier Choices[X->pid] = 0; 3857dd7cddfSDavid du Colombier continue; 3867dd7cddfSDavid du Colombier } 3877dd7cddfSDavid du Colombier X->pc = silent_moves(X->pc); 3887dd7cddfSDavid du Colombier if (!X->pc->sub && X->pc->n) 3897dd7cddfSDavid du Colombier { int unex; 3907dd7cddfSDavid du Colombier unex = !Enabled0(X->pc); 3917dd7cddfSDavid du Colombier if (unex) 3927dd7cddfSDavid du Colombier no_choice++; 3937dd7cddfSDavid du Colombier else 3947dd7cddfSDavid du Colombier only_choice = k; 3957dd7cddfSDavid du Colombier if (!xspin && unex && !(verbose&32)) 3967dd7cddfSDavid du Colombier { k++; 3977dd7cddfSDavid du Colombier continue; 3987dd7cddfSDavid du Colombier } 3997dd7cddfSDavid du Colombier printf("\tchoice %d: ", k++); 4007dd7cddfSDavid du Colombier p_talk(X->pc, 0); 4017dd7cddfSDavid du Colombier if (unex) 4027dd7cddfSDavid du Colombier printf(" unexecutable,"); 4037dd7cddfSDavid du Colombier printf(" ["); 4047dd7cddfSDavid du Colombier comment(stdout, X->pc->n, 0); 4057dd7cddfSDavid du Colombier if (X->pc->esc) printf(" + Escape"); 4067dd7cddfSDavid du Colombier printf("]\n"); 4077dd7cddfSDavid du Colombier } else { 4087dd7cddfSDavid du Colombier has_else = ZE; 4097dd7cddfSDavid du Colombier proc_no_ch = no_choice; 4107dd7cddfSDavid du Colombier proc_k = k; 4117dd7cddfSDavid du Colombier for (z = X->pc->sub, j=0; z; z = z->nxt) 4127dd7cddfSDavid du Colombier { Element *y = silent_moves(z->this->frst); 4137dd7cddfSDavid du Colombier int unex; 4147dd7cddfSDavid du Colombier if (!y) continue; 4157dd7cddfSDavid du Colombier 4167dd7cddfSDavid du Colombier if (y->n->ntyp == ELSE) 4177dd7cddfSDavid du Colombier { has_else = (Rvous)?ZE:y; 4187dd7cddfSDavid du Colombier nr_else = k++; 4197dd7cddfSDavid du Colombier continue; 4207dd7cddfSDavid du Colombier } 4217dd7cddfSDavid du Colombier 4227dd7cddfSDavid du Colombier unex = !Enabled0(y); 4237dd7cddfSDavid du Colombier if (unex) 4247dd7cddfSDavid du Colombier no_choice++; 4257dd7cddfSDavid du Colombier else 4267dd7cddfSDavid du Colombier only_choice = k; 4277dd7cddfSDavid du Colombier if (!xspin && unex && !(verbose&32)) 4287dd7cddfSDavid du Colombier { k++; 4297dd7cddfSDavid du Colombier continue; 4307dd7cddfSDavid du Colombier } 4317dd7cddfSDavid du Colombier printf("\tchoice %d: ", k++); 4327dd7cddfSDavid du Colombier p_talk(X->pc, 0); 4337dd7cddfSDavid du Colombier if (unex) 4347dd7cddfSDavid du Colombier printf(" unexecutable,"); 4357dd7cddfSDavid du Colombier printf(" ["); 4367dd7cddfSDavid du Colombier comment(stdout, y->n, 0); 4377dd7cddfSDavid du Colombier printf("]\n"); 4387dd7cddfSDavid du Colombier } 4397dd7cddfSDavid du Colombier if (has_else) 4407dd7cddfSDavid du Colombier { if (no_choice-proc_no_ch >= (k-proc_k)-1) 4417dd7cddfSDavid du Colombier { only_choice = nr_else; 4427dd7cddfSDavid du Colombier printf("\tchoice %d: ", nr_else); 4437dd7cddfSDavid du Colombier p_talk(X->pc, 0); 4447dd7cddfSDavid du Colombier printf(" [else]\n"); 4457dd7cddfSDavid du Colombier } else 4467dd7cddfSDavid du Colombier { no_choice++; 4477dd7cddfSDavid du Colombier printf("\tchoice %d: ", nr_else); 4487dd7cddfSDavid du Colombier p_talk(X->pc, 0); 4497dd7cddfSDavid du Colombier printf(" unexecutable, [else]\n"); 4507dd7cddfSDavid du Colombier } } 4517dd7cddfSDavid du Colombier } } 4527dd7cddfSDavid du Colombier X = run; 4537dd7cddfSDavid du Colombier if (k - no_choice < 2 && Tval == 0) 4547dd7cddfSDavid du Colombier { Tval = 1; 4557dd7cddfSDavid du Colombier no_choice = 0; only_choice = -1; 4567dd7cddfSDavid du Colombier goto try_more; 4577dd7cddfSDavid du Colombier } 4587dd7cddfSDavid du Colombier if (xspin) 4597dd7cddfSDavid du Colombier printf("Make Selection %d\n\n", k-1); 4607dd7cddfSDavid du Colombier else 4617dd7cddfSDavid du Colombier { if (k - no_choice < 2) 4627dd7cddfSDavid du Colombier { printf("no executable choices\n"); 4637dd7cddfSDavid du Colombier alldone(0); 4647dd7cddfSDavid du Colombier } 4657dd7cddfSDavid du Colombier printf("Select [1-%d]: ", k-1); 4667dd7cddfSDavid du Colombier } 4677dd7cddfSDavid du Colombier if (!xspin && k - no_choice == 2) 4687dd7cddfSDavid du Colombier { printf("%d\n", only_choice); 4697dd7cddfSDavid du Colombier j = only_choice; 4707dd7cddfSDavid du Colombier } else 4717dd7cddfSDavid du Colombier { char buf[256]; 4727dd7cddfSDavid du Colombier fflush(stdout); 473*00d97012SDavid du Colombier if (scanf("%64s", buf) == 0) 474*00d97012SDavid du Colombier { printf("\tno input\n"); 475*00d97012SDavid du Colombier goto try_again; 476*00d97012SDavid du Colombier } 4777dd7cddfSDavid du Colombier j = -1; 478*00d97012SDavid du Colombier if (isdigit((int) buf[0])) 4797dd7cddfSDavid du Colombier j = atoi(buf); 4807dd7cddfSDavid du Colombier else 4817dd7cddfSDavid du Colombier { if (buf[0] == 'q') 4827dd7cddfSDavid du Colombier alldone(0); 4837dd7cddfSDavid du Colombier } 4847dd7cddfSDavid du Colombier if (j < 1 || j >= k) 4857dd7cddfSDavid du Colombier { printf("\tchoice is outside range\n"); 4867dd7cddfSDavid du Colombier goto try_again; 4877dd7cddfSDavid du Colombier } } 4887dd7cddfSDavid du Colombier MadeChoice = 0; 489f3793cddSDavid du Colombier Y = NULL; 490f3793cddSDavid du Colombier for (X = run; X; Y = X, X = X->nxt) 4917dd7cddfSDavid du Colombier { if (!X->nxt 4927dd7cddfSDavid du Colombier || X->nxt->pid > 255 4937dd7cddfSDavid du Colombier || j < Choices[X->nxt->pid]) 4947dd7cddfSDavid du Colombier { 4957dd7cddfSDavid du Colombier MadeChoice = 1+j-Choices[X->pid]; 4967dd7cddfSDavid du Colombier break; 4977dd7cddfSDavid du Colombier } } 4987dd7cddfSDavid du Colombier } 499f3793cddSDavid du Colombier return Y; 5007dd7cddfSDavid du Colombier } 5017dd7cddfSDavid du Colombier 502219b2ee8SDavid du Colombier void 503*00d97012SDavid du Colombier multi_claims(void) 504*00d97012SDavid du Colombier { ProcList *p, *q = NULL; 505*00d97012SDavid du Colombier 506*00d97012SDavid du Colombier if (nclaims > 1) 507*00d97012SDavid du Colombier { printf(" the model contains %d never claims:", nclaims); 508*00d97012SDavid du Colombier for (p = rdy; p; p = p->nxt) 509*00d97012SDavid du Colombier { if (p->b == N_CLAIM) 510*00d97012SDavid du Colombier { printf("%s%s", q?", ":" ", p->n->name); 511*00d97012SDavid du Colombier q = p; 512*00d97012SDavid du Colombier } } 513*00d97012SDavid du Colombier printf("\n"); 514*00d97012SDavid du Colombier printf(" only one claim is used in a verification run\n"); 515*00d97012SDavid du Colombier printf(" choose which one with ./pan -N name (defaults to -N %s)\n", 516*00d97012SDavid du Colombier q?q->n->name:"--"); 517*00d97012SDavid du Colombier } 518*00d97012SDavid du Colombier } 519*00d97012SDavid du Colombier 520*00d97012SDavid du Colombier void 521219b2ee8SDavid du Colombier sched(void) 522219b2ee8SDavid du Colombier { Element *e; 523f3793cddSDavid du Colombier RunList *Y = NULL; /* previous process in run queue */ 524219b2ee8SDavid du Colombier RunList *oX; 525312a1df1SDavid du Colombier int go, notbeyond = 0; 5267dd7cddfSDavid du Colombier #ifdef PC 5277dd7cddfSDavid du Colombier int bufmax = 100; 5287dd7cddfSDavid du Colombier #endif 529219b2ee8SDavid du Colombier if (dumptab) 530219b2ee8SDavid du Colombier { formdump(); 531219b2ee8SDavid du Colombier symdump(); 532219b2ee8SDavid du Colombier dumplabels(); 533219b2ee8SDavid du Colombier return; 534219b2ee8SDavid du Colombier } 535219b2ee8SDavid du Colombier 536219b2ee8SDavid du Colombier if (has_enabled && u_sync > 0) 5377dd7cddfSDavid du Colombier { printf("spin: error, cannot use 'enabled()' in "); 5387dd7cddfSDavid du Colombier printf("models with synchronous channels.\n"); 539219b2ee8SDavid du Colombier nr_errs++; 540219b2ee8SDavid du Colombier } 541*00d97012SDavid du Colombier if (product) 542*00d97012SDavid du Colombier { sync_product(); 543*00d97012SDavid du Colombier alldone(0); 544*00d97012SDavid du Colombier } 545219b2ee8SDavid du Colombier if (analyze) 546219b2ee8SDavid du Colombier { gensrc(); 547*00d97012SDavid du Colombier multi_claims(); 548219b2ee8SDavid du Colombier return; 549*00d97012SDavid du Colombier } 550*00d97012SDavid du Colombier if (s_trail) 551219b2ee8SDavid du Colombier { match_trail(); 552219b2ee8SDavid du Colombier return; 553219b2ee8SDavid du Colombier } 554219b2ee8SDavid du Colombier if (claimproc) 5557dd7cddfSDavid du Colombier printf("warning: never claim not used in random simulation\n"); 5567dd7cddfSDavid du Colombier if (eventmap) 5577dd7cddfSDavid du Colombier printf("warning: trace assertion not used in random simulation\n"); 558219b2ee8SDavid du Colombier 559219b2ee8SDavid du Colombier X = run; 560f3793cddSDavid du Colombier Y = pickproc(Y); 5617dd7cddfSDavid du Colombier 562219b2ee8SDavid du Colombier while (X) 563219b2ee8SDavid du Colombier { context = X->n; 564219b2ee8SDavid du Colombier if (X->pc && X->pc->n) 565219b2ee8SDavid du Colombier { lineno = X->pc->n->ln; 566219b2ee8SDavid du Colombier Fname = X->pc->n->fn; 567219b2ee8SDavid du Colombier } 568312a1df1SDavid du Colombier if (cutoff > 0 && depth >= cutoff) 569312a1df1SDavid du Colombier { printf("-------------\n"); 570312a1df1SDavid du Colombier printf("depth-limit (-u%d steps) reached\n", cutoff); 571312a1df1SDavid du Colombier break; 572312a1df1SDavid du Colombier } 5737dd7cddfSDavid du Colombier #ifdef PC 5747dd7cddfSDavid du Colombier if (xspin && !interactive && --bufmax <= 0) 575312a1df1SDavid du Colombier { int c; /* avoid buffer overflow on pc's */ 5767dd7cddfSDavid du Colombier printf("spin: type return to proceed\n"); 5777dd7cddfSDavid du Colombier fflush(stdout); 578312a1df1SDavid du Colombier c = getc(stdin); 579312a1df1SDavid du Colombier if (c == 'q') wrapup(0); 5807dd7cddfSDavid du Colombier bufmax = 100; 5817dd7cddfSDavid du Colombier } 5827dd7cddfSDavid du Colombier #endif 583219b2ee8SDavid du Colombier depth++; LastStep = ZE; 584219b2ee8SDavid du Colombier oX = X; /* a rendezvous could change it */ 5857dd7cddfSDavid du Colombier go = 1; 586*00d97012SDavid du Colombier if (X->prov && X->pc 5877dd7cddfSDavid du Colombier && !(X->pc->status & D_ATOM) 5887dd7cddfSDavid du Colombier && !eval(X->prov)) 5897dd7cddfSDavid du Colombier { if (!xspin && ((verbose&32) || (verbose&4))) 5907dd7cddfSDavid du Colombier { p_talk(X->pc, 1); 5917dd7cddfSDavid du Colombier printf("\t<<Not Enabled>>\n"); 5927dd7cddfSDavid du Colombier } 5937dd7cddfSDavid du Colombier go = 0; 5947dd7cddfSDavid du Colombier } 5957dd7cddfSDavid du Colombier if (go && (e = eval_sub(X->pc))) 5967dd7cddfSDavid du Colombier { if (depth >= jumpsteps 5977dd7cddfSDavid du Colombier && ((verbose&32) || (verbose&4))) 598219b2ee8SDavid du Colombier { if (X == oX) 599312a1df1SDavid du Colombier if (!(e->status & D_ATOM) || (verbose&32)) /* no talking in d_steps */ 600219b2ee8SDavid du Colombier { p_talk(X->pc, 1); 601219b2ee8SDavid du Colombier printf(" ["); 602219b2ee8SDavid du Colombier if (!LastStep) LastStep = X->pc; 603219b2ee8SDavid du Colombier comment(stdout, LastStep->n, 0); 604219b2ee8SDavid du Colombier printf("]\n"); 605219b2ee8SDavid du Colombier } 606219b2ee8SDavid du Colombier if (verbose&1) dumpglobals(); 607219b2ee8SDavid du Colombier if (verbose&2) dumplocal(X); 608312a1df1SDavid du Colombier 609312a1df1SDavid du Colombier if (!(e->status & D_ATOM)) 610312a1df1SDavid du Colombier if (xspin) 611312a1df1SDavid du Colombier printf("\n"); 612219b2ee8SDavid du Colombier } 613*00d97012SDavid du Colombier if (oX != X 614*00d97012SDavid du Colombier || (X->pc->status & (ATOM|D_ATOM))) /* new 5.0 */ 615312a1df1SDavid du Colombier { e = silent_moves(e); 616312a1df1SDavid du Colombier notbeyond = 0; 617312a1df1SDavid du Colombier } 618219b2ee8SDavid du Colombier oX->pc = e; LastX = X; 6197dd7cddfSDavid du Colombier 6207dd7cddfSDavid du Colombier if (!interactive) Tval = 0; 621219b2ee8SDavid du Colombier memset(is_blocked, 0, 256); 622219b2ee8SDavid du Colombier 623312a1df1SDavid du Colombier if (X->pc && (X->pc->status & (ATOM|L_ATOM)) 624312a1df1SDavid du Colombier && (notbeyond == 0 || oX != X)) 625312a1df1SDavid du Colombier { if ((X->pc->status & L_ATOM)) 6267dd7cddfSDavid du Colombier notbeyond = 1; 6277dd7cddfSDavid du Colombier continue; /* no process switch */ 6287dd7cddfSDavid du Colombier } 629219b2ee8SDavid du Colombier } else 630219b2ee8SDavid du Colombier { depth--; 631*00d97012SDavid du Colombier if (oX->pc && (oX->pc->status & D_ATOM)) 632*00d97012SDavid du Colombier { non_fatal("stmnt in d_step blocks", (char *)0); 633*00d97012SDavid du Colombier } 634*00d97012SDavid du Colombier if (X->pc 635*00d97012SDavid du Colombier && X->pc->n 636*00d97012SDavid du Colombier && X->pc->n->ntyp == '@' 637219b2ee8SDavid du Colombier && X->pid == (nproc-nstop-1)) 638f3793cddSDavid du Colombier { if (X != run && Y != NULL) 639219b2ee8SDavid du Colombier Y->nxt = X->nxt; 640219b2ee8SDavid du Colombier else 641219b2ee8SDavid du Colombier run = X->nxt; 642219b2ee8SDavid du Colombier nstop++; 6437dd7cddfSDavid du Colombier Priority_Sum -= X->priority; 644219b2ee8SDavid du Colombier if (verbose&4) 645219b2ee8SDavid du Colombier { whoruns(1); 6467dd7cddfSDavid du Colombier dotag(stdout, "terminates\n"); 647219b2ee8SDavid du Colombier } 648219b2ee8SDavid du Colombier LastX = X; 6497dd7cddfSDavid du Colombier if (!interactive) Tval = 0; 650219b2ee8SDavid du Colombier if (nproc == nstop) break; 651219b2ee8SDavid du Colombier memset(is_blocked, 0, 256); 652f3793cddSDavid du Colombier /* proc X is no longer in runlist */ 653f3793cddSDavid du Colombier X = (X->nxt) ? X->nxt : run; 654219b2ee8SDavid du Colombier } else 6557dd7cddfSDavid du Colombier { if (p_blocked(X->pid)) 656219b2ee8SDavid du Colombier { if (Tval) break; 657219b2ee8SDavid du Colombier Tval = 1; 6587dd7cddfSDavid du Colombier if (depth >= jumpsteps) 659312a1df1SDavid du Colombier { oX = X; 660312a1df1SDavid du Colombier X = (RunList *) 0; /* to suppress indent */ 6617dd7cddfSDavid du Colombier dotag(stdout, "timeout\n"); 662312a1df1SDavid du Colombier X = oX; 663312a1df1SDavid du Colombier } } } } 664*00d97012SDavid du Colombier 665*00d97012SDavid du Colombier if (!run || !X) break; /* new 5.0 */ 666*00d97012SDavid du Colombier 667f3793cddSDavid du Colombier Y = pickproc(X); 6687dd7cddfSDavid du Colombier notbeyond = 0; 669219b2ee8SDavid du Colombier } 670219b2ee8SDavid du Colombier context = ZS; 671219b2ee8SDavid du Colombier wrapup(0); 672219b2ee8SDavid du Colombier } 673219b2ee8SDavid du Colombier 674219b2ee8SDavid du Colombier int 675219b2ee8SDavid du Colombier complete_rendez(void) 676219b2ee8SDavid du Colombier { RunList *orun = X, *tmp; 677219b2ee8SDavid du Colombier Element *s_was = LastStep; 678219b2ee8SDavid du Colombier Element *e; 6797dd7cddfSDavid du Colombier int j, ointer = interactive; 680219b2ee8SDavid du Colombier 681219b2ee8SDavid du Colombier if (s_trail) 682219b2ee8SDavid du Colombier return 1; 6837dd7cddfSDavid du Colombier if (orun->pc->status & D_ATOM) 6847dd7cddfSDavid du Colombier fatal("rv-attempt in d_step sequence", (char *)0); 685219b2ee8SDavid du Colombier Rvous = 1; 6867dd7cddfSDavid du Colombier interactive = 0; 6877dd7cddfSDavid du Colombier 6887dd7cddfSDavid du Colombier j = (int) Rand()%Priority_Sum; /* randomize start point */ 6897dd7cddfSDavid du Colombier X = run; 6907dd7cddfSDavid du Colombier while (j - X->priority >= 0) 6917dd7cddfSDavid du Colombier { j -= X->priority; 6927dd7cddfSDavid du Colombier X = X->nxt; 6937dd7cddfSDavid du Colombier if (!X) X = run; 6947dd7cddfSDavid du Colombier } 6957dd7cddfSDavid du Colombier for (j = nproc - nstop; j > 0; j--) 6967dd7cddfSDavid du Colombier { if (X != orun 6977dd7cddfSDavid du Colombier && (!X->prov || eval(X->prov)) 6987dd7cddfSDavid du Colombier && (e = eval_sub(X->pc))) 6997dd7cddfSDavid du Colombier { if (TstOnly) 7007dd7cddfSDavid du Colombier { X = orun; 7017dd7cddfSDavid du Colombier Rvous = 0; 7027dd7cddfSDavid du Colombier goto out; 7037dd7cddfSDavid du Colombier } 7047dd7cddfSDavid du Colombier if ((verbose&32) || (verbose&4)) 705219b2ee8SDavid du Colombier { tmp = orun; orun = X; X = tmp; 706219b2ee8SDavid du Colombier if (!s_was) s_was = X->pc; 707219b2ee8SDavid du Colombier p_talk(s_was, 1); 708219b2ee8SDavid du Colombier printf(" ["); 709219b2ee8SDavid du Colombier comment(stdout, s_was->n, 0); 710219b2ee8SDavid du Colombier printf("]\n"); 711219b2ee8SDavid du Colombier tmp = orun; orun = X; X = tmp; 712219b2ee8SDavid du Colombier if (!LastStep) LastStep = X->pc; 713219b2ee8SDavid du Colombier p_talk(LastStep, 1); 714219b2ee8SDavid du Colombier printf(" ["); 715219b2ee8SDavid du Colombier comment(stdout, LastStep->n, 0); 716219b2ee8SDavid du Colombier printf("]\n"); 717219b2ee8SDavid du Colombier } 7187dd7cddfSDavid du Colombier Rvous = 0; /* before silent_moves */ 7197dd7cddfSDavid du Colombier X->pc = silent_moves(e); 7207dd7cddfSDavid du Colombier out: interactive = ointer; 721219b2ee8SDavid du Colombier return 1; 722219b2ee8SDavid du Colombier } 7237dd7cddfSDavid du Colombier 7247dd7cddfSDavid du Colombier X = X->nxt; 7257dd7cddfSDavid du Colombier if (!X) X = run; 7267dd7cddfSDavid du Colombier } 727219b2ee8SDavid du Colombier Rvous = 0; 728219b2ee8SDavid du Colombier X = orun; 7297dd7cddfSDavid du Colombier interactive = ointer; 730219b2ee8SDavid du Colombier return 0; 731219b2ee8SDavid du Colombier } 732219b2ee8SDavid du Colombier 733219b2ee8SDavid du Colombier /***** Runtime - Local Variables *****/ 734219b2ee8SDavid du Colombier 7357dd7cddfSDavid du Colombier static void 736219b2ee8SDavid du Colombier addsymbol(RunList *r, Symbol *s) 737219b2ee8SDavid du Colombier { Symbol *t; 738219b2ee8SDavid du Colombier int i; 739219b2ee8SDavid du Colombier 740219b2ee8SDavid du Colombier for (t = r->symtab; t; t = t->next) 741*00d97012SDavid du Colombier if (strcmp(t->name, s->name) == 0 742*00d97012SDavid du Colombier && (old_scope_rules 743*00d97012SDavid du Colombier || strcmp((const char *)t->bscp, (const char *)s->bscp) == 0)) 744219b2ee8SDavid du Colombier return; /* it's already there */ 745219b2ee8SDavid du Colombier 746219b2ee8SDavid du Colombier t = (Symbol *) emalloc(sizeof(Symbol)); 747219b2ee8SDavid du Colombier t->name = s->name; 748219b2ee8SDavid du Colombier t->type = s->type; 7497dd7cddfSDavid du Colombier t->hidden = s->hidden; 7507dd7cddfSDavid du Colombier t->nbits = s->nbits; 751219b2ee8SDavid du Colombier t->nel = s->nel; 752219b2ee8SDavid du Colombier t->ini = s->ini; 753219b2ee8SDavid du Colombier t->setat = depth; 7547dd7cddfSDavid du Colombier t->context = r->n; 755*00d97012SDavid du Colombier 756*00d97012SDavid du Colombier t->bscp = (unsigned char *) emalloc(strlen((const char *)s->bscp)+1); 757*00d97012SDavid du Colombier strcpy((char *)t->bscp, (const char *)s->bscp); 758*00d97012SDavid du Colombier 759219b2ee8SDavid du Colombier if (s->type != STRUCT) 760219b2ee8SDavid du Colombier { if (s->val) /* if already initialized, copy info */ 761219b2ee8SDavid du Colombier { t->val = (int *) emalloc(s->nel*sizeof(int)); 762219b2ee8SDavid du Colombier for (i = 0; i < s->nel; i++) 763219b2ee8SDavid du Colombier t->val[i] = s->val[i]; 764219b2ee8SDavid du Colombier } else 765*00d97012SDavid du Colombier { (void) checkvar(t, 0); /* initialize it */ 766*00d97012SDavid du Colombier } 767219b2ee8SDavid du Colombier } else 768219b2ee8SDavid du Colombier { if (s->Sval) 769219b2ee8SDavid du Colombier fatal("saw preinitialized struct %s", s->name); 770219b2ee8SDavid du Colombier t->Slst = s->Slst; 771219b2ee8SDavid du Colombier t->Snm = s->Snm; 772219b2ee8SDavid du Colombier t->owner = s->owner; 7737dd7cddfSDavid du Colombier /* t->context = r->n; */ 774219b2ee8SDavid du Colombier } 775219b2ee8SDavid du Colombier t->next = r->symtab; /* add it */ 776219b2ee8SDavid du Colombier r->symtab = t; 777219b2ee8SDavid du Colombier } 778219b2ee8SDavid du Colombier 7797dd7cddfSDavid du Colombier static void 7807dd7cddfSDavid du Colombier setlocals(RunList *r) 7817dd7cddfSDavid du Colombier { Ordered *walk; 7827dd7cddfSDavid du Colombier Symbol *sp; 7837dd7cddfSDavid du Colombier RunList *oX = X; 7847dd7cddfSDavid du Colombier 7857dd7cddfSDavid du Colombier X = r; 7867dd7cddfSDavid du Colombier for (walk = all_names; walk; walk = walk->next) 7877dd7cddfSDavid du Colombier { sp = walk->entry; 7887dd7cddfSDavid du Colombier if (sp 7897dd7cddfSDavid du Colombier && sp->context 7907dd7cddfSDavid du Colombier && strcmp(sp->context->name, r->n->name) == 0 7917dd7cddfSDavid du Colombier && sp->Nid >= 0 7927dd7cddfSDavid du Colombier && (sp->type == UNSIGNED 7937dd7cddfSDavid du Colombier || sp->type == BIT 7947dd7cddfSDavid du Colombier || sp->type == MTYPE 7957dd7cddfSDavid du Colombier || sp->type == BYTE 7967dd7cddfSDavid du Colombier || sp->type == CHAN 7977dd7cddfSDavid du Colombier || sp->type == SHORT 7987dd7cddfSDavid du Colombier || sp->type == INT 7997dd7cddfSDavid du Colombier || sp->type == STRUCT)) 8007dd7cddfSDavid du Colombier { if (!findloc(sp)) 8017dd7cddfSDavid du Colombier non_fatal("setlocals: cannot happen '%s'", 8027dd7cddfSDavid du Colombier sp->name); 8037dd7cddfSDavid du Colombier } 8047dd7cddfSDavid du Colombier } 8057dd7cddfSDavid du Colombier X = oX; 8067dd7cddfSDavid du Colombier } 8077dd7cddfSDavid du Colombier 8087dd7cddfSDavid du Colombier static void 809219b2ee8SDavid du Colombier oneparam(RunList *r, Lextok *t, Lextok *a, ProcList *p) 810219b2ee8SDavid du Colombier { int k; int at, ft; 811219b2ee8SDavid du Colombier RunList *oX = X; 812219b2ee8SDavid du Colombier 813219b2ee8SDavid du Colombier if (!a) 814219b2ee8SDavid du Colombier fatal("missing actual parameters: '%s'", p->n->name); 815*00d97012SDavid du Colombier if (t->sym->nel > 1 || t->sym->isarray) 816219b2ee8SDavid du Colombier fatal("array in parameter list, %s", t->sym->name); 817219b2ee8SDavid du Colombier k = eval(a->lft); 818219b2ee8SDavid du Colombier 819219b2ee8SDavid du Colombier at = Sym_typ(a->lft); 820219b2ee8SDavid du Colombier X = r; /* switch context */ 821219b2ee8SDavid du Colombier ft = Sym_typ(t); 822219b2ee8SDavid du Colombier 823219b2ee8SDavid du Colombier if (at != ft && (at == CHAN || ft == CHAN)) 824*00d97012SDavid du Colombier { char buf[256], tag1[64], tag2[64]; 825219b2ee8SDavid du Colombier (void) sputtype(tag1, ft); 826219b2ee8SDavid du Colombier (void) sputtype(tag2, at); 8277dd7cddfSDavid du Colombier sprintf(buf, "type-clash in params of %s(..), (%s<-> %s)", 828219b2ee8SDavid du Colombier p->n->name, tag1, tag2); 829219b2ee8SDavid du Colombier non_fatal("%s", buf); 830219b2ee8SDavid du Colombier } 831219b2ee8SDavid du Colombier t->ntyp = NAME; 832219b2ee8SDavid du Colombier addsymbol(r, t->sym); 833219b2ee8SDavid du Colombier (void) setval(t, k); 834219b2ee8SDavid du Colombier 835219b2ee8SDavid du Colombier X = oX; 836219b2ee8SDavid du Colombier } 837219b2ee8SDavid du Colombier 8387dd7cddfSDavid du Colombier static void 839219b2ee8SDavid du Colombier setparams(RunList *r, ProcList *p, Lextok *q) 840219b2ee8SDavid du Colombier { Lextok *f, *a; /* formal and actual pars */ 841219b2ee8SDavid du Colombier Lextok *t; /* list of pars of 1 type */ 842219b2ee8SDavid du Colombier 843219b2ee8SDavid du Colombier if (q) 844219b2ee8SDavid du Colombier { lineno = q->ln; 845219b2ee8SDavid du Colombier Fname = q->fn; 846219b2ee8SDavid du Colombier } 847219b2ee8SDavid du Colombier for (f = p->p, a = q; f; f = f->rgt) /* one type at a time */ 848219b2ee8SDavid du Colombier for (t = f->lft; t; t = t->rgt, a = (a)?a->rgt:a) 849219b2ee8SDavid du Colombier { if (t->ntyp != ',') 850219b2ee8SDavid du Colombier oneparam(r, t, a, p); /* plain var */ 851219b2ee8SDavid du Colombier else 8527dd7cddfSDavid du Colombier oneparam(r, t->lft, a, p); /* expanded struct */ 853219b2ee8SDavid du Colombier } 854219b2ee8SDavid du Colombier } 855219b2ee8SDavid du Colombier 856219b2ee8SDavid du Colombier Symbol * 857219b2ee8SDavid du Colombier findloc(Symbol *s) 858219b2ee8SDavid du Colombier { Symbol *r; 859219b2ee8SDavid du Colombier 860219b2ee8SDavid du Colombier if (!X) 861219b2ee8SDavid du Colombier { /* fatal("error, cannot eval '%s' (no proc)", s->name); */ 862219b2ee8SDavid du Colombier return ZS; 863219b2ee8SDavid du Colombier } 864219b2ee8SDavid du Colombier for (r = X->symtab; r; r = r->next) 865*00d97012SDavid du Colombier if (strcmp(r->name, s->name) == 0 866*00d97012SDavid du Colombier && (old_scope_rules || strcmp((const char *)r->bscp, (const char *)s->bscp) == 0)) 867219b2ee8SDavid du Colombier break; 868219b2ee8SDavid du Colombier if (!r) 869219b2ee8SDavid du Colombier { addsymbol(X, s); 870219b2ee8SDavid du Colombier r = X->symtab; 871219b2ee8SDavid du Colombier } 872219b2ee8SDavid du Colombier return r; 873219b2ee8SDavid du Colombier } 874219b2ee8SDavid du Colombier 875219b2ee8SDavid du Colombier int 876312a1df1SDavid du Colombier in_bound(Symbol *r, int n) 877312a1df1SDavid du Colombier { 878312a1df1SDavid du Colombier if (!r) return 0; 879312a1df1SDavid du Colombier 880312a1df1SDavid du Colombier if (n >= r->nel || n < 0) 881312a1df1SDavid du Colombier { printf("spin: indexing %s[%d] - size is %d\n", 882312a1df1SDavid du Colombier r->name, n, r->nel); 883312a1df1SDavid du Colombier non_fatal("indexing array \'%s\'", r->name); 884312a1df1SDavid du Colombier return 0; 885312a1df1SDavid du Colombier } 886312a1df1SDavid du Colombier return 1; 887312a1df1SDavid du Colombier } 888312a1df1SDavid du Colombier 889312a1df1SDavid du Colombier int 890219b2ee8SDavid du Colombier getlocal(Lextok *sn) 891219b2ee8SDavid du Colombier { Symbol *r, *s = sn->sym; 892219b2ee8SDavid du Colombier int n = eval(sn->lft); 893219b2ee8SDavid du Colombier 894219b2ee8SDavid du Colombier r = findloc(s); 895219b2ee8SDavid du Colombier if (r && r->type == STRUCT) 896219b2ee8SDavid du Colombier return Rval_struct(sn, r, 1); /* 1 = check init */ 897312a1df1SDavid du Colombier if (in_bound(r, n)) 898312a1df1SDavid du Colombier return cast_val(r->type, r->val[n], r->nbits); 899219b2ee8SDavid du Colombier return 0; 900219b2ee8SDavid du Colombier } 901219b2ee8SDavid du Colombier 902219b2ee8SDavid du Colombier int 903219b2ee8SDavid du Colombier setlocal(Lextok *p, int m) 904219b2ee8SDavid du Colombier { Symbol *r = findloc(p->sym); 905219b2ee8SDavid du Colombier int n = eval(p->lft); 906219b2ee8SDavid du Colombier 907312a1df1SDavid du Colombier if (in_bound(r, n)) 908219b2ee8SDavid du Colombier { if (r->type == STRUCT) 909219b2ee8SDavid du Colombier (void) Lval_struct(p, r, 1, m); /* 1 = check init */ 910219b2ee8SDavid du Colombier else 911312a1df1SDavid du Colombier { 912312a1df1SDavid du Colombier #if 0 913312a1df1SDavid du Colombier if (r->nbits > 0) 9147dd7cddfSDavid du Colombier m = (m & ((1<<r->nbits)-1)); 9157dd7cddfSDavid du Colombier r->val[n] = m; 916312a1df1SDavid du Colombier #else 917312a1df1SDavid du Colombier r->val[n] = cast_val(r->type, m, r->nbits); 918312a1df1SDavid du Colombier #endif 919219b2ee8SDavid du Colombier r->setat = depth; 920219b2ee8SDavid du Colombier } } 921219b2ee8SDavid du Colombier 922219b2ee8SDavid du Colombier return 1; 923219b2ee8SDavid du Colombier } 924219b2ee8SDavid du Colombier 925219b2ee8SDavid du Colombier void 926219b2ee8SDavid du Colombier whoruns(int lnr) 927219b2ee8SDavid du Colombier { if (!X) return; 928219b2ee8SDavid du Colombier 929219b2ee8SDavid du Colombier if (lnr) printf("%3d: ", depth); 930219b2ee8SDavid du Colombier printf("proc "); 9317dd7cddfSDavid du Colombier if (Have_claim && X->pid == 0) 932219b2ee8SDavid du Colombier printf(" -"); 933219b2ee8SDavid du Colombier else 9347dd7cddfSDavid du Colombier printf("%2d", X->pid - Have_claim); 935219b2ee8SDavid du Colombier printf(" (%s) ", X->n->name); 936219b2ee8SDavid du Colombier } 937219b2ee8SDavid du Colombier 9387dd7cddfSDavid du Colombier static void 939219b2ee8SDavid du Colombier talk(RunList *r) 940219b2ee8SDavid du Colombier { 9417dd7cddfSDavid du Colombier if ((verbose&32) || (verbose&4)) 942219b2ee8SDavid du Colombier { p_talk(r->pc, 1); 943219b2ee8SDavid du Colombier printf("\n"); 944219b2ee8SDavid du Colombier if (verbose&1) dumpglobals(); 945219b2ee8SDavid du Colombier if (verbose&2) dumplocal(r); 946219b2ee8SDavid du Colombier } 947219b2ee8SDavid du Colombier } 948219b2ee8SDavid du Colombier 949219b2ee8SDavid du Colombier void 950219b2ee8SDavid du Colombier p_talk(Element *e, int lnr) 9517dd7cddfSDavid du Colombier { static int lastnever = -1; 952*00d97012SDavid du Colombier static char nbuf[128]; 9537dd7cddfSDavid du Colombier int newnever = -1; 9547dd7cddfSDavid du Colombier 9557dd7cddfSDavid du Colombier if (e && e->n) 9567dd7cddfSDavid du Colombier newnever = e->n->ln; 9577dd7cddfSDavid du Colombier 9587dd7cddfSDavid du Colombier if (Have_claim && X && X->pid == 0 9597dd7cddfSDavid du Colombier && lastnever != newnever && e) 9607dd7cddfSDavid du Colombier { if (xspin) 9617dd7cddfSDavid du Colombier { printf("MSC: ~G line %d\n", newnever); 962312a1df1SDavid du Colombier #if 0 963312a1df1SDavid du Colombier printf("%3d: proc - (NEVER) line %d \"never\" ", 9647dd7cddfSDavid du Colombier depth, newnever); 9657dd7cddfSDavid du Colombier printf("(state 0)\t[printf('MSC: never\\\\n')]\n"); 9667dd7cddfSDavid du Colombier } else 967312a1df1SDavid du Colombier { printf("%3d: proc - (NEVER) line %d \"never\"\n", 9687dd7cddfSDavid du Colombier depth, newnever); 969312a1df1SDavid du Colombier #endif 9707dd7cddfSDavid du Colombier } 9717dd7cddfSDavid du Colombier lastnever = newnever; 9727dd7cddfSDavid du Colombier } 9737dd7cddfSDavid du Colombier 974219b2ee8SDavid du Colombier whoruns(lnr); 975219b2ee8SDavid du Colombier if (e) 976*00d97012SDavid du Colombier { if (e->n) 977*00d97012SDavid du Colombier { char *ptr = e->n->fn->name; 978*00d97012SDavid du Colombier char *qtr = nbuf; 979*00d97012SDavid du Colombier while (*ptr != '\0') 980*00d97012SDavid du Colombier { if (*ptr != '"') 981*00d97012SDavid du Colombier { *qtr++ = *ptr; 982*00d97012SDavid du Colombier } 983*00d97012SDavid du Colombier ptr++; 984*00d97012SDavid du Colombier } 985*00d97012SDavid du Colombier *qtr = '\0'; 986*00d97012SDavid du Colombier } else 987*00d97012SDavid du Colombier { strcpy(nbuf, "-"); 988*00d97012SDavid du Colombier } 989*00d97012SDavid du Colombier printf("%s:%d (state %d)", 990*00d97012SDavid du Colombier nbuf, 991219b2ee8SDavid du Colombier e->n?e->n->ln:-1, 992219b2ee8SDavid du Colombier e->seqno); 9937dd7cddfSDavid du Colombier if (!xspin 9947dd7cddfSDavid du Colombier && ((e->status&ENDSTATE) || has_lab(e, 2))) /* 2=end */ 9957dd7cddfSDavid du Colombier { printf(" <valid end state>"); 9967dd7cddfSDavid du Colombier } 9977dd7cddfSDavid du Colombier } 998219b2ee8SDavid du Colombier } 999219b2ee8SDavid du Colombier 1000219b2ee8SDavid du Colombier int 1001219b2ee8SDavid du Colombier remotelab(Lextok *n) 1002219b2ee8SDavid du Colombier { int i; 1003219b2ee8SDavid du Colombier 1004219b2ee8SDavid du Colombier lineno = n->ln; 1005219b2ee8SDavid du Colombier Fname = n->fn; 1006312a1df1SDavid du Colombier if (n->sym->type != 0 && n->sym->type != LABEL) 1007312a1df1SDavid du Colombier { printf("spin: error, type: %d\n", n->sym->type); 1008219b2ee8SDavid du Colombier fatal("not a labelname: '%s'", n->sym->name); 1009312a1df1SDavid du Colombier } 10107dd7cddfSDavid du Colombier if (n->indstep >= 0) 10117dd7cddfSDavid du Colombier { fatal("remote ref to label '%s' inside d_step", 10127dd7cddfSDavid du Colombier n->sym->name); 10137dd7cddfSDavid du Colombier } 10147dd7cddfSDavid du Colombier if ((i = find_lab(n->sym, n->lft->sym, 1)) == 0) 1015219b2ee8SDavid du Colombier fatal("unknown labelname: %s", n->sym->name); 1016219b2ee8SDavid du Colombier return i; 1017219b2ee8SDavid du Colombier } 1018219b2ee8SDavid du Colombier 1019219b2ee8SDavid du Colombier int 1020219b2ee8SDavid du Colombier remotevar(Lextok *n) 1021312a1df1SDavid du Colombier { int prno, i, added=0; 1022312a1df1SDavid du Colombier RunList *Y, *oX; 1023312a1df1SDavid du Colombier Lextok *onl; 1024312a1df1SDavid du Colombier Symbol *os; 1025219b2ee8SDavid du Colombier 1026219b2ee8SDavid du Colombier lineno = n->ln; 1027219b2ee8SDavid du Colombier Fname = n->fn; 1028219b2ee8SDavid du Colombier 1029312a1df1SDavid du Colombier if (!n->lft->lft) 1030312a1df1SDavid du Colombier prno = f_pid(n->lft->sym->name); 1031312a1df1SDavid du Colombier else 1032312a1df1SDavid du Colombier { prno = eval(n->lft->lft); /* pid - can cause recursive call */ 1033312a1df1SDavid du Colombier #if 0 1034312a1df1SDavid du Colombier if (n->lft->lft->ntyp == CONST) /* user-guessed pid */ 1035312a1df1SDavid du Colombier #endif 1036312a1df1SDavid du Colombier { prno += Have_claim; 1037312a1df1SDavid du Colombier added = Have_claim; 1038312a1df1SDavid du Colombier } } 1039312a1df1SDavid du Colombier 1040312a1df1SDavid du Colombier if (prno < 0) 1041312a1df1SDavid du Colombier return 0; /* non-existing process */ 1042312a1df1SDavid du Colombier #if 0 1043312a1df1SDavid du Colombier i = nproc - nstop; 1044312a1df1SDavid du Colombier for (Y = run; Y; Y = Y->nxt) 1045312a1df1SDavid du Colombier { --i; 1046312a1df1SDavid du Colombier printf(" %s: i=%d, prno=%d, ->pid=%d\n", Y->n->name, i, prno, Y->pid); 1047312a1df1SDavid du Colombier } 1048312a1df1SDavid du Colombier #endif 1049*00d97012SDavid du Colombier i = nproc - nstop + Skip_claim; /* 6.0: added Skip_claim */ 1050219b2ee8SDavid du Colombier for (Y = run; Y; Y = Y->nxt) 10517dd7cddfSDavid du Colombier if (--i == prno) 1052219b2ee8SDavid du Colombier { if (strcmp(Y->n->name, n->lft->sym->name) != 0) 1053312a1df1SDavid du Colombier { printf("spin: remote reference error on '%s[%d]'\n", 1054312a1df1SDavid du Colombier n->lft->sym->name, prno-added); 10557dd7cddfSDavid du Colombier non_fatal("refers to wrong proctype '%s'", Y->n->name); 1056219b2ee8SDavid du Colombier } 1057219b2ee8SDavid du Colombier if (strcmp(n->sym->name, "_p") == 0) 10587dd7cddfSDavid du Colombier { if (Y->pc) 1059219b2ee8SDavid du Colombier return Y->pc->seqno; 10607dd7cddfSDavid du Colombier /* harmless, can only happen with -t */ 10617dd7cddfSDavid du Colombier return 0; 10627dd7cddfSDavid du Colombier } 1063312a1df1SDavid du Colombier #if 1 1064312a1df1SDavid du Colombier /* new 4.0 allow remote variables */ 1065312a1df1SDavid du Colombier oX = X; 1066312a1df1SDavid du Colombier X = Y; 1067312a1df1SDavid du Colombier 1068312a1df1SDavid du Colombier onl = n->lft; 1069312a1df1SDavid du Colombier n->lft = n->rgt; 1070312a1df1SDavid du Colombier 1071312a1df1SDavid du Colombier os = n->sym; 1072312a1df1SDavid du Colombier n->sym = findloc(n->sym); 1073312a1df1SDavid du Colombier 1074312a1df1SDavid du Colombier i = getval(n); 1075312a1df1SDavid du Colombier 1076312a1df1SDavid du Colombier n->sym = os; 1077312a1df1SDavid du Colombier n->lft = onl; 1078312a1df1SDavid du Colombier X = oX; 1079312a1df1SDavid du Colombier return i; 1080312a1df1SDavid du Colombier #else 1081219b2ee8SDavid du Colombier break; 1082312a1df1SDavid du Colombier #endif 1083219b2ee8SDavid du Colombier } 1084312a1df1SDavid du Colombier printf("remote ref: %s[%d] ", n->lft->sym->name, prno-added); 1085219b2ee8SDavid du Colombier non_fatal("%s not found", n->sym->name); 10867dd7cddfSDavid du Colombier printf("have only:\n"); 10877dd7cddfSDavid du Colombier i = nproc - nstop - 1; 10887dd7cddfSDavid du Colombier for (Y = run; Y; Y = Y->nxt, i--) 10897dd7cddfSDavid du Colombier if (!strcmp(Y->n->name, n->lft->sym->name)) 10907dd7cddfSDavid du Colombier printf("\t%d\t%s\n", i, Y->n->name); 1091219b2ee8SDavid du Colombier 1092219b2ee8SDavid du Colombier return 0; 1093219b2ee8SDavid du Colombier } 1094