/***** spin: vars.c *****/ /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */ /* All Rights Reserved. This software is for educational purposes only. */ /* No guarantee whatsoever is expressed or implied by the distribution of */ /* this code. Permission is given to distribute this code provided that */ /* this introductory message is not removed and no monies are exchanged. */ /* Software written by Gerard J. Holzmann. For tool documentation see: */ /* http://spinroot.com/ */ /* Send all bug-reports and/or questions to: bugs@spinroot.com */ #include "spin.h" #include "y.tab.h" extern Ordered *all_names; extern RunList *X, *LastX; extern Symbol *Fname; extern char Buf[]; extern int lineno, depth, verbose, xspin, limited_vis; extern int analyze, jumpsteps, nproc, nstop, columns; extern short no_arrays, Have_claim; extern void sr_mesg(FILE *, int, int); extern void sr_buf(int, int); static int getglobal(Lextok *); static int setglobal(Lextok *, int); static int maxcolnr = 1; int getval(Lextok *sn) { Symbol *s = sn->sym; if (strcmp(s->name, "_") == 0) { non_fatal("attempt to read value of '_'", 0); return 0; } if (strcmp(s->name, "_last") == 0) return (LastX)?LastX->pid:0; if (strcmp(s->name, "_p") == 0) return (X && X->pc)?X->pc->seqno:0; if (strcmp(s->name, "_pid") == 0) { if (!X) return 0; return X->pid - Have_claim; } if (strcmp(s->name, "_nr_pr") == 0) return nproc-nstop; /* new 3.3.10 */ if (s->context && s->type) return getlocal(sn); if (!s->type) /* not declared locally */ { s = lookup(s->name); /* try global */ sn->sym = s; /* fix it */ } return getglobal(sn); } int setval(Lextok *v, int n) { if (v->sym->context && v->sym->type) return setlocal(v, n); if (!v->sym->type) v->sym = lookup(v->sym->name); return setglobal(v, n); } void rm_selfrefs(Symbol *s, Lextok *i) { if (!i) return; if (i->ntyp == NAME && strcmp(i->sym->name, s->name) == 0 && ( (!i->sym->context && !s->context) || ( i->sym->context && s->context && strcmp(i->sym->context->name, s->context->name) == 0))) { lineno = i->ln; Fname = i->fn; non_fatal("self-reference initializing '%s'", s->name); i->ntyp = CONST; i->val = 0; } else { rm_selfrefs(s, i->lft); rm_selfrefs(s, i->rgt); } } int checkvar(Symbol *s, int n) { int i, oln = lineno; /* calls on eval() change it */ Symbol *ofnm = Fname; if (!in_bound(s, n)) return 0; if (s->type == 0) { non_fatal("undecl var %s (assuming int)", s->name); s->type = INT; } /* not a STRUCT */ if (s->val == (int *) 0) /* uninitialized */ { s->val = (int *) emalloc(s->nel*sizeof(int)); for (i = 0; i < s->nel; i++) { if (s->type != CHAN) { rm_selfrefs(s, s->ini); s->val[i] = eval(s->ini); } else if (!analyze) s->val[i] = qmake(s); } } lineno = oln; Fname = ofnm; return 1; } static int getglobal(Lextok *sn) { Symbol *s = sn->sym; int i, n = eval(sn->lft); if (s->type == 0 && X && (i = find_lab(s, X->n, 0))) { printf("findlab through getglobal on %s\n", s->name); return i; /* can this happen? */ } if (s->type == STRUCT) return Rval_struct(sn, s, 1); /* 1 = check init */ if (checkvar(s, n)) return cast_val(s->type, s->val[n], s->nbits); return 0; } int cast_val(int t, int v, int w) { int i=0; short s=0; unsigned int u=0; if (t == PREDEF || t == INT || t == CHAN) i = v; /* predef means _ */ else if (t == SHORT) s = (short) v; else if (t == BYTE || t == MTYPE) u = (unsigned char)v; else if (t == BIT) u = (unsigned char)(v&1); else if (t == UNSIGNED) { if (w == 0) fatal("cannot happen, cast_val", (char *)0); /* u = (unsigned)(v& ((1<>(8*sizeof(unsigned)-w))); /* doug */ } if (v != i+s+ (int) u) { char buf[64]; sprintf(buf, "%d->%d (%d)", v, i+s+u, t); non_fatal("value (%s) truncated in assignment", buf); } return (int)(i+s+u); } static int setglobal(Lextok *v, int m) { if (v->sym->type == STRUCT) (void) Lval_struct(v, v->sym, 1, m); else { int n = eval(v->lft); if (checkvar(v->sym, n)) { int oval = v->sym->val[n]; int nval = cast_val(v->sym->type, m, v->sym->nbits); v->sym->val[n] = nval; if (oval != nval) { v->sym->setat = depth; } } } return 1; } void dumpclaims(FILE *fd, int pid, char *s) { extern Lextok *Xu_List; extern int Pid; extern short terse; Lextok *m; int cnt = 0; int oPid = Pid; for (m = Xu_List; m; m = m->rgt) if (strcmp(m->sym->name, s) == 0) { cnt=1; break; } if (cnt == 0) return; Pid = pid; fprintf(fd, "#ifndef XUSAFE\n"); for (m = Xu_List; m; m = m->rgt) { if (strcmp(m->sym->name, s) != 0) continue; no_arrays = 1; putname(fd, "\t\tsetq_claim(", m->lft, 0, ""); no_arrays = 0; fprintf(fd, ", %d, ", m->val); terse = 1; putname(fd, "\"", m->lft, 0, "\", h, "); terse = 0; fprintf(fd, "\"%s\");\n", s); } fprintf(fd, "#endif\n"); Pid = oPid; } void dumpglobals(void) { Ordered *walk; static Lextok *dummy = ZN; Symbol *sp; int j; if (!dummy) dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN); for (walk = all_names; walk; walk = walk->next) { sp = walk->entry; if (!sp->type || sp->context || sp->owner || sp->type == PROCTYPE || sp->type == PREDEF || sp->type == CODE_FRAG || sp->type == CODE_DECL || (sp->type == MTYPE && ismtype(sp->name))) continue; if (sp->type == STRUCT) { if ((verbose&4) && !(verbose&64) && (sp->setat < depth && jumpsteps != depth)) { continue; } dump_struct(sp, sp->name, 0); continue; } for (j = 0; j < sp->nel; j++) { int prefetch; if (sp->type == CHAN) { doq(sp, j, 0); continue; } if ((verbose&4) && !(verbose&64) && (sp->setat < depth && jumpsteps != depth)) { continue; } dummy->sym = sp; dummy->lft->val = j; /* in case of cast_val warnings, do this first: */ prefetch = getglobal(dummy); printf("\t\t%s", sp->name); if (sp->nel > 1 || sp->isarray) printf("[%d]", j); printf(" = "); sr_mesg(stdout, prefetch, sp->type == MTYPE); printf("\n"); if (limited_vis && (sp->hidden&2)) { int colpos; Buf[0] = '\0'; if (!xspin) { if (columns == 2) sprintf(Buf, "~G%s = ", sp->name); else sprintf(Buf, "%s = ", sp->name); } sr_buf(prefetch, sp->type == MTYPE); if (sp->colnr == 0) { sp->colnr = maxcolnr; maxcolnr = 1+(maxcolnr%10); } colpos = nproc+sp->colnr-1; if (columns == 2) { pstext(colpos, Buf); continue; } if (!xspin) { printf("\t\t%s\n", Buf); continue; } printf("MSC: ~G %s %s\n", sp->name, Buf); printf("%3d:\tproc %3d (TRACK) line 1 \"var\" ", depth, colpos); printf("(state 0)\t[printf('MSC: globvar\\\\n')]\n"); printf("\t\t%s", sp->name); if (sp->nel > 1 || sp->isarray) printf("[%d]", j); printf(" = %s\n", Buf); } } } } void dumplocal(RunList *r) { static Lextok *dummy = ZN; Symbol *z, *s; int i; if (!r) return; s = r->symtab; if (!dummy) dummy = nn(ZN, NAME, nn(ZN,CONST,ZN,ZN), ZN); for (z = s; z; z = z->next) { if (z->type == STRUCT) { dump_struct(z, z->name, r); continue; } for (i = 0; i < z->nel; i++) { if (z->type == CHAN) { doq(z, i, r); continue; } if ((verbose&4) && !(verbose&64) && (z->setat < depth && jumpsteps != depth)) continue; dummy->sym = z; dummy->lft->val = i; printf("\t\t%s(%d):%s", r->n->name, r->pid - Have_claim, z->name); if (z->nel > 1 || z->isarray) printf("[%d]", i); printf(" = "); sr_mesg(stdout, getval(dummy), z->type == MTYPE); printf("\n"); if (limited_vis && (z->hidden&2)) { int colpos; Buf[0] = '\0'; if (!xspin) { if (columns == 2) sprintf(Buf, "~G%s(%d):%s = ", r->n->name, r->pid, z->name); else sprintf(Buf, "%s(%d):%s = ", r->n->name, r->pid, z->name); } sr_buf(getval(dummy), z->type==MTYPE); if (z->colnr == 0) { z->colnr = maxcolnr; maxcolnr = 1+(maxcolnr%10); } colpos = nproc+z->colnr-1; if (columns == 2) { pstext(colpos, Buf); continue; } if (!xspin) { printf("\t\t%s\n", Buf); continue; } printf("MSC: ~G %s(%d):%s %s\n", r->n->name, r->pid, z->name, Buf); printf("%3d:\tproc %3d (TRACK) line 1 \"var\" ", depth, colpos); printf("(state 0)\t[printf('MSC: locvar\\\\n')]\n"); printf("\t\t%s(%d):%s", r->n->name, r->pid, z->name); if (z->nel > 1 || z->isarray) printf("[%d]", i); printf(" = %s\n", Buf); } } } }