1*219b2ee8SDavid du Colombier /***** spin: main.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 <signal.h> 15*219b2ee8SDavid du Colombier #include <stdlib.h> 16*219b2ee8SDavid du Colombier #include <unistd.h> 17*219b2ee8SDavid du Colombier #include "y.tab.h" 18*219b2ee8SDavid du Colombier 19*219b2ee8SDavid du Colombier extern int DstepStart, lineno; 20*219b2ee8SDavid du Colombier extern FILE *yyin; 21*219b2ee8SDavid du Colombier 22*219b2ee8SDavid du Colombier Symbol *Fname, *oFname; 23*219b2ee8SDavid du Colombier 24*219b2ee8SDavid du Colombier int verbose = 0; 25*219b2ee8SDavid du Colombier int analyze = 0; 26*219b2ee8SDavid du Colombier int s_trail = 0; 27*219b2ee8SDavid du Colombier int m_loss = 0; 28*219b2ee8SDavid du Colombier int dumptab = 0; 29*219b2ee8SDavid du Colombier int nr_errs = 0; 30*219b2ee8SDavid du Colombier int dataflow = 0; 31*219b2ee8SDavid du Colombier int has_remote = 0; 32*219b2ee8SDavid du Colombier int Interactive = 0; 33*219b2ee8SDavid du Colombier int Ntimeouts = 0; /* counts those used in never claim */ 34*219b2ee8SDavid du Colombier int Etimeouts = 0; /* counts those used in program */ 35*219b2ee8SDavid du Colombier int xspin = 0; /* set when used with xspin interface */ 36*219b2ee8SDavid du Colombier 37*219b2ee8SDavid du Colombier void 38*219b2ee8SDavid du Colombier main(int argc, char *argv[]) 39*219b2ee8SDavid du Colombier { Symbol *s; 40*219b2ee8SDavid du Colombier int T = (int) time((long *)0); 41*219b2ee8SDavid du Colombier 42*219b2ee8SDavid du Colombier while (argc > 1 && argv[1][0] == '-') 43*219b2ee8SDavid du Colombier { switch (argv[1][1]) { 44*219b2ee8SDavid du Colombier case 'a': analyze = 1; break; 45*219b2ee8SDavid du Colombier case 'd': dumptab = 1; break; 46*219b2ee8SDavid du Colombier case 'D': dataflow++; break; 47*219b2ee8SDavid du Colombier case 'g': verbose += 1; break; 48*219b2ee8SDavid du Colombier case 'i': Interactive = 1; break; 49*219b2ee8SDavid du Colombier case 'l': verbose += 2; break; 50*219b2ee8SDavid du Colombier case 'm': m_loss = 1; break; 51*219b2ee8SDavid du Colombier case 'n': T = atoi(&argv[1][2]); break; 52*219b2ee8SDavid du Colombier case 'p': verbose += 4; break; 53*219b2ee8SDavid du Colombier case 'r': verbose += 8; break; 54*219b2ee8SDavid du Colombier case 's': verbose += 16; break; 55*219b2ee8SDavid du Colombier case 't': s_trail = 1; break; 56*219b2ee8SDavid du Colombier case 'v': verbose += 32; break; 57*219b2ee8SDavid du Colombier case 'V': printf("%s\n", Version); exit(0); 58*219b2ee8SDavid du Colombier case 'X': xspin = 1; 59*219b2ee8SDavid du Colombier signal(SIGPIPE, exit); /* not posix compliant... */ 60*219b2ee8SDavid du Colombier break; 61*219b2ee8SDavid du Colombier default : printf("use: spin [-option] ... [-option] file\n"); 62*219b2ee8SDavid du Colombier printf("\t-a produce an analyzer\n"); 63*219b2ee8SDavid du Colombier printf("\t-d produce symbol-table information\n"); 64*219b2ee8SDavid du Colombier printf("\t-D write/write dataflow\n"); 65*219b2ee8SDavid du Colombier printf("\t-D -D read/write dataflow\n"); 66*219b2ee8SDavid du Colombier printf("\t-g print all global variables\n"); 67*219b2ee8SDavid du Colombier printf("\t-i interactive (random simulation)\n"); 68*219b2ee8SDavid du Colombier printf("\t-l print all local variables\n"); 69*219b2ee8SDavid du Colombier printf("\t-m lose msgs sent to full queues\n"); 70*219b2ee8SDavid du Colombier printf("\t-nN seed for random nr generator\n"); 71*219b2ee8SDavid du Colombier printf("\t-p print all statements\n"); 72*219b2ee8SDavid du Colombier printf("\t-r print receive events\n"); 73*219b2ee8SDavid du Colombier printf("\t-s print send events\n"); 74*219b2ee8SDavid du Colombier printf("\t-v verbose, more warnings\n"); 75*219b2ee8SDavid du Colombier printf("\t-t follow a simulation trail\n"); 76*219b2ee8SDavid du Colombier printf("\t-V print version number and exit\n"); 77*219b2ee8SDavid du Colombier exit(1); 78*219b2ee8SDavid du Colombier } 79*219b2ee8SDavid du Colombier argc--, argv++; 80*219b2ee8SDavid du Colombier } 81*219b2ee8SDavid du Colombier if (argc > 1) 82*219b2ee8SDavid du Colombier { char outfile[32], cmd[128]; 83*219b2ee8SDavid du Colombier extern char *tmpnam(char *); 84*219b2ee8SDavid du Colombier (void) tmpnam(outfile); 85*219b2ee8SDavid du Colombier 86*219b2ee8SDavid du Colombier /* on some systems: "/usr/ccs/lib/cpp" */ 87*219b2ee8SDavid du Colombier sprintf(cmd, "/bin/cpp %s > %s", argv[1], outfile); 88*219b2ee8SDavid du Colombier if (system((const char *)cmd)) 89*219b2ee8SDavid du Colombier { (void) unlink((const char *)outfile); 90*219b2ee8SDavid du Colombier exit(1); 91*219b2ee8SDavid du Colombier } else if (!(yyin = fopen(outfile, "r"))) 92*219b2ee8SDavid du Colombier { printf("cannot open %s\n", outfile); 93*219b2ee8SDavid du Colombier exit(1); 94*219b2ee8SDavid du Colombier } 95*219b2ee8SDavid du Colombier (void) unlink((const char *)outfile); 96*219b2ee8SDavid du Colombier oFname = Fname = lookup(argv[1]); 97*219b2ee8SDavid du Colombier if (oFname->name[0] == '\"') 98*219b2ee8SDavid du Colombier { int i = strlen(oFname->name); 99*219b2ee8SDavid du Colombier oFname->name[i-1] = '\0'; 100*219b2ee8SDavid du Colombier oFname = lookup(&oFname->name[1]); 101*219b2ee8SDavid du Colombier } 102*219b2ee8SDavid du Colombier } else 103*219b2ee8SDavid du Colombier Fname = lookup("<stdin>"); 104*219b2ee8SDavid du Colombier Srand(T); /* defined in run.c */ 105*219b2ee8SDavid du Colombier s = lookup("_p"); s->type = PREDEF; 106*219b2ee8SDavid du Colombier s = lookup("_pid"); s->type = PREDEF; 107*219b2ee8SDavid du Colombier s = lookup("_last"); s->type = PREDEF; 108*219b2ee8SDavid du Colombier yyparse(); 109*219b2ee8SDavid du Colombier exit(nr_errs); 110*219b2ee8SDavid du Colombier } 111*219b2ee8SDavid du Colombier 112*219b2ee8SDavid du Colombier int 113*219b2ee8SDavid du Colombier yywrap(void) /* dummy routine */ 114*219b2ee8SDavid du Colombier { 115*219b2ee8SDavid du Colombier return 1; 116*219b2ee8SDavid du Colombier } 117*219b2ee8SDavid du Colombier 118*219b2ee8SDavid du Colombier void 119*219b2ee8SDavid du Colombier non_fatal(char *s1, char *s2) 120*219b2ee8SDavid du Colombier { extern int yychar; extern char yytext[]; 121*219b2ee8SDavid du Colombier 122*219b2ee8SDavid du Colombier printf("spin: line %3d %s: ", lineno, Fname->name); 123*219b2ee8SDavid du Colombier if (s2) 124*219b2ee8SDavid du Colombier printf(s1, s2); 125*219b2ee8SDavid du Colombier else 126*219b2ee8SDavid du Colombier printf(s1); 127*219b2ee8SDavid du Colombier if (yychar != -1 && yychar != 0) 128*219b2ee8SDavid du Colombier { printf(" saw '"); 129*219b2ee8SDavid du Colombier explain(yychar); 130*219b2ee8SDavid du Colombier printf("'"); 131*219b2ee8SDavid du Colombier } 132*219b2ee8SDavid du Colombier if (yytext && strlen(yytext)>1) 133*219b2ee8SDavid du Colombier printf(" near '%s'", yytext); 134*219b2ee8SDavid du Colombier printf("\n"); fflush(stdout); 135*219b2ee8SDavid du Colombier nr_errs++; 136*219b2ee8SDavid du Colombier } 137*219b2ee8SDavid du Colombier 138*219b2ee8SDavid du Colombier void 139*219b2ee8SDavid du Colombier fatal(char *s1, char *s2) 140*219b2ee8SDavid du Colombier { 141*219b2ee8SDavid du Colombier non_fatal(s1, s2); 142*219b2ee8SDavid du Colombier exit(1); 143*219b2ee8SDavid du Colombier } 144*219b2ee8SDavid du Colombier 145*219b2ee8SDavid du Colombier char * 146*219b2ee8SDavid du Colombier emalloc(int n) 147*219b2ee8SDavid du Colombier { char *tmp; 148*219b2ee8SDavid du Colombier 149*219b2ee8SDavid du Colombier if (!(tmp = (char *) malloc(n))) 150*219b2ee8SDavid du Colombier fatal("not enough memory", (char *)0); 151*219b2ee8SDavid du Colombier memset(tmp, 0, n); 152*219b2ee8SDavid du Colombier return tmp; 153*219b2ee8SDavid du Colombier } 154*219b2ee8SDavid du Colombier 155*219b2ee8SDavid du Colombier Lextok * 156*219b2ee8SDavid du Colombier nn(Lextok *s, int t, Lextok *ll, Lextok *rl) 157*219b2ee8SDavid du Colombier { Lextok *n = (Lextok *) emalloc(sizeof(Lextok)); 158*219b2ee8SDavid du Colombier extern char *claimproc; 159*219b2ee8SDavid du Colombier extern Symbol *context; 160*219b2ee8SDavid du Colombier 161*219b2ee8SDavid du Colombier n->ntyp = t; 162*219b2ee8SDavid du Colombier if (s && s->fn) 163*219b2ee8SDavid du Colombier { n->ln = s->ln; 164*219b2ee8SDavid du Colombier n->fn = s->fn; 165*219b2ee8SDavid du Colombier } else if (rl && rl->fn) 166*219b2ee8SDavid du Colombier { n->ln = rl->ln; 167*219b2ee8SDavid du Colombier n->fn = rl->fn; 168*219b2ee8SDavid du Colombier } else if (ll && ll->fn) 169*219b2ee8SDavid du Colombier { n->ln = ll->ln; 170*219b2ee8SDavid du Colombier n->fn = ll->fn; 171*219b2ee8SDavid du Colombier } else 172*219b2ee8SDavid du Colombier { n->ln = lineno; 173*219b2ee8SDavid du Colombier n->fn = Fname; 174*219b2ee8SDavid du Colombier } 175*219b2ee8SDavid du Colombier if (s) n->sym = s->sym; 176*219b2ee8SDavid du Colombier n->lft = ll; 177*219b2ee8SDavid du Colombier n->rgt = rl; 178*219b2ee8SDavid du Colombier n->indstep = DstepStart; 179*219b2ee8SDavid du Colombier 180*219b2ee8SDavid du Colombier if (t == TIMEOUT) Etimeouts++; 181*219b2ee8SDavid du Colombier 182*219b2ee8SDavid du Colombier if (!context) 183*219b2ee8SDavid du Colombier return n; 184*219b2ee8SDavid du Colombier if (context->name == claimproc) 185*219b2ee8SDavid du Colombier { switch (t) { 186*219b2ee8SDavid du Colombier case ASGN: case 'r': case 's': 187*219b2ee8SDavid du Colombier non_fatal("never claim has side-effect",(char *)0); 188*219b2ee8SDavid du Colombier break; 189*219b2ee8SDavid du Colombier case TIMEOUT: 190*219b2ee8SDavid du Colombier /* never claim polls timeout */ 191*219b2ee8SDavid du Colombier Ntimeouts++; Etimeouts--; 192*219b2ee8SDavid du Colombier break; 193*219b2ee8SDavid du Colombier case LEN: case EMPTY: case FULL: 194*219b2ee8SDavid du Colombier case 'R': case NFULL: case NEMPTY: 195*219b2ee8SDavid du Colombier /* status bumped to non-exclusive */ 196*219b2ee8SDavid du Colombier if (n->sym) n->sym->xu |= XX; 197*219b2ee8SDavid du Colombier break; 198*219b2ee8SDavid du Colombier default: 199*219b2ee8SDavid du Colombier break; 200*219b2ee8SDavid du Colombier } 201*219b2ee8SDavid du Colombier } else if (t == ENABLED) 202*219b2ee8SDavid du Colombier fatal("using enabled() outside never-claim",(char *)0); 203*219b2ee8SDavid du Colombier /* this affects how enabled is implemented in run.c */ 204*219b2ee8SDavid du Colombier 205*219b2ee8SDavid du Colombier return n; 206*219b2ee8SDavid du Colombier } 207*219b2ee8SDavid du Colombier 208*219b2ee8SDavid du Colombier Lextok * 209*219b2ee8SDavid du Colombier rem_lab(Symbol *a, Lextok *b, Symbol *c) 210*219b2ee8SDavid du Colombier { Lextok *tmp1, *tmp2, *tmp3; 211*219b2ee8SDavid du Colombier 212*219b2ee8SDavid du Colombier has_remote++; 213*219b2ee8SDavid du Colombier fix_dest(c, a); /* in case target is jump */ 214*219b2ee8SDavid du Colombier tmp1 = nn(ZN, '?', b, ZN); tmp1->sym = a; 215*219b2ee8SDavid du Colombier tmp1 = nn(ZN, 'p', tmp1, ZN); 216*219b2ee8SDavid du Colombier tmp1->sym = lookup("_p"); 217*219b2ee8SDavid du Colombier tmp2 = nn(ZN, NAME, ZN, ZN); tmp2->sym = a; 218*219b2ee8SDavid du Colombier tmp3 = nn(ZN, 'q', tmp2, ZN); tmp3->sym = c; 219*219b2ee8SDavid du Colombier return nn(ZN, EQ, tmp1, tmp3); 220*219b2ee8SDavid du Colombier } 221*219b2ee8SDavid du Colombier 222*219b2ee8SDavid du Colombier char Operator[] = "operator: "; 223*219b2ee8SDavid du Colombier char Keyword[] = "keyword: "; 224*219b2ee8SDavid du Colombier char Function[] = "function-name: "; 225*219b2ee8SDavid du Colombier 226*219b2ee8SDavid du Colombier void 227*219b2ee8SDavid du Colombier explain(int n) 228*219b2ee8SDavid du Colombier { 229*219b2ee8SDavid du Colombier switch (n) { 230*219b2ee8SDavid du Colombier default: if (n > 0 && n < 256) 231*219b2ee8SDavid du Colombier printf("%c' = '", n); 232*219b2ee8SDavid du Colombier printf("%d", n); 233*219b2ee8SDavid du Colombier break; 234*219b2ee8SDavid du Colombier case '\b': printf("\\b"); break; 235*219b2ee8SDavid du Colombier case '\t': printf("\\t"); break; 236*219b2ee8SDavid du Colombier case '\f': printf("\\f"); break; 237*219b2ee8SDavid du Colombier case '\n': printf("\\n"); break; 238*219b2ee8SDavid du Colombier case '\r': printf("\\r"); break; 239*219b2ee8SDavid du Colombier case 'c': printf("condition"); break; 240*219b2ee8SDavid du Colombier case 's': printf("send"); break; 241*219b2ee8SDavid du Colombier case 'r': printf("recv"); break; 242*219b2ee8SDavid du Colombier case '@': printf("delproc"); break; 243*219b2ee8SDavid du Colombier case '?': printf("(x->y:z)"); break; 244*219b2ee8SDavid du Colombier case ACTIVE: printf("%sactive", Keyword); break; 245*219b2ee8SDavid du Colombier case AND: printf("%s&&", Operator); break; 246*219b2ee8SDavid du Colombier case ASGN: printf("%s=", Operator); break; 247*219b2ee8SDavid du Colombier case ASSERT: printf("%sassert", Function); break; 248*219b2ee8SDavid du Colombier case ATOMIC: printf("%satomic", Keyword); break; 249*219b2ee8SDavid du Colombier case BREAK: printf("%sbreak", Keyword); break; 250*219b2ee8SDavid du Colombier case CLAIM: printf("%snever", Keyword); break; 251*219b2ee8SDavid du Colombier case CONST: printf("a constant"); break; 252*219b2ee8SDavid du Colombier case DECR: printf("%s--", Operator); break; 253*219b2ee8SDavid du Colombier case D_STEP: printf("%sd_step", Keyword); break; 254*219b2ee8SDavid du Colombier case DO: printf("%sdo", Keyword); break; 255*219b2ee8SDavid du Colombier case DOT: printf("."); break; 256*219b2ee8SDavid du Colombier case ELSE: printf("%selse", Keyword); break; 257*219b2ee8SDavid du Colombier case EMPTY: printf("%sempty", Function); break; 258*219b2ee8SDavid du Colombier case ENABLED: printf("%senabled", Function); break; 259*219b2ee8SDavid du Colombier case EQ: printf("%s==", Operator); break; 260*219b2ee8SDavid du Colombier case FI: printf("%sfi", Keyword); break; 261*219b2ee8SDavid du Colombier case FULL: printf("%sfull", Function); break; 262*219b2ee8SDavid du Colombier case GE: printf("%s>=", Operator); break; 263*219b2ee8SDavid du Colombier case GOTO: printf("%sgoto", Keyword); break; 264*219b2ee8SDavid du Colombier case GT: printf("%s>", Operator); break; 265*219b2ee8SDavid du Colombier case IF: printf("%sif", Keyword); break; 266*219b2ee8SDavid du Colombier case INCR: printf("%s++", Operator); break; 267*219b2ee8SDavid du Colombier case INIT: printf("%sinit", Keyword); break; 268*219b2ee8SDavid du Colombier case LABEL: printf("a label-name"); break; 269*219b2ee8SDavid du Colombier case LE: printf("%s<=", Operator); break; 270*219b2ee8SDavid du Colombier case LEN: printf("%slen", Function); break; 271*219b2ee8SDavid du Colombier case LSHIFT: printf("%s<<", Operator); break; 272*219b2ee8SDavid du Colombier case LT: printf("%s<", Operator); break; 273*219b2ee8SDavid du Colombier case MTYPE: printf("%smtype", Keyword); break; 274*219b2ee8SDavid du Colombier case NAME: printf("an identifier"); break; 275*219b2ee8SDavid du Colombier case NE: printf("%s!=", Operator); break; 276*219b2ee8SDavid du Colombier case NEG: printf("%s! (not)", Operator); break; 277*219b2ee8SDavid du Colombier case NEMPTY: printf("%snempty", Function); break; 278*219b2ee8SDavid du Colombier case NFULL: printf("%snfull", Function); break; 279*219b2ee8SDavid du Colombier case NON_ATOMIC: printf("sub-sequence"); break; 280*219b2ee8SDavid du Colombier case OD: printf("%sod", Keyword); break; 281*219b2ee8SDavid du Colombier case OF: printf("%sof", Keyword); break; 282*219b2ee8SDavid du Colombier case OR: printf("%s||", Operator); break; 283*219b2ee8SDavid du Colombier case O_SND: printf("%s!!", Operator); break; 284*219b2ee8SDavid du Colombier case PC_VAL: printf("%spc_value", Function); break; 285*219b2ee8SDavid du Colombier case PNAME: printf("process name"); break; 286*219b2ee8SDavid du Colombier case PRINT: printf("%sprintf", Function); break; 287*219b2ee8SDavid du Colombier case PROCTYPE: printf("%sproctype", Keyword); break; 288*219b2ee8SDavid du Colombier case RCV: printf("%s?", Operator); break; 289*219b2ee8SDavid du Colombier case R_RCV: printf("%s??", Operator); break; 290*219b2ee8SDavid du Colombier case RSHIFT: printf("%s>>", Operator); break; 291*219b2ee8SDavid du Colombier case RUN: printf("%srun", Operator); break; 292*219b2ee8SDavid du Colombier case SEP: printf("token: ::"); break; 293*219b2ee8SDavid du Colombier case SEMI: printf(";"); break; 294*219b2ee8SDavid du Colombier case SND: printf("%s!", Operator); break; 295*219b2ee8SDavid du Colombier case STRING: printf("a string"); break; 296*219b2ee8SDavid du Colombier case TIMEOUT: printf("%stimeout", Keyword); break; 297*219b2ee8SDavid du Colombier case TYPE: printf("data typename"); break; 298*219b2ee8SDavid du Colombier case TYPEDEF: printf("%stypedef", Keyword); break; 299*219b2ee8SDavid du Colombier case XU: printf("%sx[rs]", Keyword); break; 300*219b2ee8SDavid du Colombier case UMIN: printf("%s- (unary minus)", Operator); break; 301*219b2ee8SDavid du Colombier case UNAME: printf("a typename"); break; 302*219b2ee8SDavid du Colombier case UNLESS: printf("%sunless", Keyword); break; 303*219b2ee8SDavid du Colombier } 304*219b2ee8SDavid du Colombier } 305*219b2ee8SDavid du Colombier 306*219b2ee8SDavid du Colombier static int IsAsgn = 0, OrIsAsgn = 0; 307*219b2ee8SDavid du Colombier static Element *Same; 308*219b2ee8SDavid du Colombier 309*219b2ee8SDavid du Colombier int 310*219b2ee8SDavid du Colombier used_here(Symbol *s, Lextok *n) 311*219b2ee8SDavid du Colombier { extern Symbol *context; 312*219b2ee8SDavid du Colombier int res = 0; 313*219b2ee8SDavid du Colombier 314*219b2ee8SDavid du Colombier if (!n) return 0; 315*219b2ee8SDavid du Colombier #ifdef DEBUG 316*219b2ee8SDavid du Colombier { int oln; Symbol *ofn; 317*219b2ee8SDavid du Colombier printf(" used_here %s -- ", context->name); 318*219b2ee8SDavid du Colombier oln = lineno; ofn = Fname; 319*219b2ee8SDavid du Colombier comment(stdout, n, 0); 320*219b2ee8SDavid du Colombier lineno = oln; Fname = ofn; 321*219b2ee8SDavid du Colombier printf(" -- %d:%s\n", n->ln,n->fn->name); 322*219b2ee8SDavid du Colombier } 323*219b2ee8SDavid du Colombier #endif 324*219b2ee8SDavid du Colombier if (n->sym == s) res = (IsAsgn || n->ntyp == ASGN)?2:1; 325*219b2ee8SDavid du Colombier if (n->ntyp == ASGN) 326*219b2ee8SDavid du Colombier res |= used_here(s, n->lft->lft); 327*219b2ee8SDavid du Colombier else 328*219b2ee8SDavid du Colombier res |= used_here(s, n->lft); 329*219b2ee8SDavid du Colombier if (n->ntyp == 'r') 330*219b2ee8SDavid du Colombier IsAsgn = 1; 331*219b2ee8SDavid du Colombier res |= used_here(s, n->rgt); 332*219b2ee8SDavid du Colombier if (n->ntyp == 'r') 333*219b2ee8SDavid du Colombier IsAsgn = 0; 334*219b2ee8SDavid du Colombier return res; 335*219b2ee8SDavid du Colombier } 336*219b2ee8SDavid du Colombier 337*219b2ee8SDavid du Colombier int 338*219b2ee8SDavid du Colombier used_later(Symbol *s, Element *t) 339*219b2ee8SDavid du Colombier { extern Symbol *context; 340*219b2ee8SDavid du Colombier int res = 0; 341*219b2ee8SDavid du Colombier 342*219b2ee8SDavid du Colombier if (!t || !s) 343*219b2ee8SDavid du Colombier return 0; 344*219b2ee8SDavid du Colombier if (t->status&CHECK2) 345*219b2ee8SDavid du Colombier { 346*219b2ee8SDavid du Colombier #ifdef DEBUG 347*219b2ee8SDavid du Colombier printf("\t%d used_later: done before\n", t->Seqno); 348*219b2ee8SDavid du Colombier #endif 349*219b2ee8SDavid du Colombier return (t->Seqno == Same->Seqno) ? 4 : 0; 350*219b2ee8SDavid du Colombier } 351*219b2ee8SDavid du Colombier 352*219b2ee8SDavid du Colombier t->status |= CHECK2; 353*219b2ee8SDavid du Colombier 354*219b2ee8SDavid du Colombier #ifdef DEBUG 355*219b2ee8SDavid du Colombier { int oln; Symbol *ofn; 356*219b2ee8SDavid du Colombier printf("\t%d %u ->%d %u used_later %s -- ", 357*219b2ee8SDavid du Colombier t->seqno, 358*219b2ee8SDavid du Colombier t, (t->nxt)?t->nxt->seqno:-1, 359*219b2ee8SDavid du Colombier t->nxt, context->name); 360*219b2ee8SDavid du Colombier oln = lineno; ofn = Fname; 361*219b2ee8SDavid du Colombier comment(stdout, t->n, 0); 362*219b2ee8SDavid du Colombier lineno = oln; Fname = ofn; 363*219b2ee8SDavid du Colombier printf(" -- %d:%s\n", t->n->ln, t->n->fn->name); 364*219b2ee8SDavid du Colombier } 365*219b2ee8SDavid du Colombier #endif 366*219b2ee8SDavid du Colombier if (t->n->ntyp == GOTO) 367*219b2ee8SDavid du Colombier { Element *j = target(t); 368*219b2ee8SDavid du Colombier #ifdef DEBUG 369*219b2ee8SDavid du Colombier printf("\t\tjump to %d\n", j?j->Seqno:-1); 370*219b2ee8SDavid du Colombier #endif 371*219b2ee8SDavid du Colombier res |= used_later(s, j); 372*219b2ee8SDavid du Colombier goto done; 373*219b2ee8SDavid du Colombier } 374*219b2ee8SDavid du Colombier 375*219b2ee8SDavid du Colombier if (t->n->sl && ! t->sub) /* d_step or (non-) atomic */ 376*219b2ee8SDavid du Colombier { SeqList *f; 377*219b2ee8SDavid du Colombier for (f = t->n->sl; f; f = f->nxt) 378*219b2ee8SDavid du Colombier { f->this->last->nxt = t->nxt; 379*219b2ee8SDavid du Colombier #ifdef DEBUG 380*219b2ee8SDavid du Colombier printf("\tPatch2 %d->%d (%d)\n", 381*219b2ee8SDavid du Colombier f->this->last->seqno, t->nxt?t->nxt->seqno:-1, t->n->ntyp); 382*219b2ee8SDavid du Colombier #endif 383*219b2ee8SDavid du Colombier res |= used_later(s, f->this->frst); 384*219b2ee8SDavid du Colombier } 385*219b2ee8SDavid du Colombier } else if (t->sub) /* IF or DO */ 386*219b2ee8SDavid du Colombier { SeqList *f; 387*219b2ee8SDavid du Colombier for (f = t->sub; f; f = f->nxt) 388*219b2ee8SDavid du Colombier res |= used_later(s, f->this->frst); 389*219b2ee8SDavid du Colombier } else 390*219b2ee8SDavid du Colombier { res |= used_here(s, t->n); 391*219b2ee8SDavid du Colombier } 392*219b2ee8SDavid du Colombier if (!(res&3)) res |= used_later(s, t->nxt); 393*219b2ee8SDavid du Colombier done: 394*219b2ee8SDavid du Colombier t->status &= ~CHECK2; 395*219b2ee8SDavid du Colombier return res; 396*219b2ee8SDavid du Colombier } 397*219b2ee8SDavid du Colombier 398*219b2ee8SDavid du Colombier void 399*219b2ee8SDavid du Colombier varused(Lextok *t, Element *u, int isread) 400*219b2ee8SDavid du Colombier { int res = 0; 401*219b2ee8SDavid du Colombier 402*219b2ee8SDavid du Colombier if (!t || !t->sym) return; 403*219b2ee8SDavid du Colombier if (dataflow == 1 && isread) return; 404*219b2ee8SDavid du Colombier 405*219b2ee8SDavid du Colombier res = used_later(t->sym, u); 406*219b2ee8SDavid du Colombier 407*219b2ee8SDavid du Colombier if ((res&1) 408*219b2ee8SDavid du Colombier || (isread && res&4)) 409*219b2ee8SDavid du Colombier return; /* followed by at least one read */ 410*219b2ee8SDavid du Colombier 411*219b2ee8SDavid du Colombier printf("%s:%3d: ", 412*219b2ee8SDavid du Colombier Same->n->fn->name, 413*219b2ee8SDavid du Colombier Same->n->ln); 414*219b2ee8SDavid du Colombier if (t->sym->owner) printf("%s.", t->sym->owner->name); 415*219b2ee8SDavid du Colombier printf("%s -- (%s)", 416*219b2ee8SDavid du Colombier t->sym->name, 417*219b2ee8SDavid du Colombier (isread)?"read":"write"); 418*219b2ee8SDavid du Colombier 419*219b2ee8SDavid du Colombier if (!res) { printf(" none"); printf("\n");exit(0); } 420*219b2ee8SDavid du Colombier if (res&2) printf(" write"); 421*219b2ee8SDavid du Colombier if (res&4) printf(" same"); 422*219b2ee8SDavid du Colombier printf("\n"); 423*219b2ee8SDavid du Colombier 424*219b2ee8SDavid du Colombier } 425*219b2ee8SDavid du Colombier 426*219b2ee8SDavid du Colombier void 427*219b2ee8SDavid du Colombier varprobe(Element *parent, Lextok *n, Element *q) 428*219b2ee8SDavid du Colombier { 429*219b2ee8SDavid du Colombier if (!n) return; 430*219b2ee8SDavid du Colombier 431*219b2ee8SDavid du Colombier Same = parent; 432*219b2ee8SDavid du Colombier 433*219b2ee8SDavid du Colombier /* can't deal with globals, structs, or arrays */ 434*219b2ee8SDavid du Colombier if (n->sym 435*219b2ee8SDavid du Colombier && n->sym->context 436*219b2ee8SDavid du Colombier && n->sym->nel == 1 437*219b2ee8SDavid du Colombier && n->sym->type != STRUCT 438*219b2ee8SDavid du Colombier && n->ntyp != PRINT) 439*219b2ee8SDavid du Colombier varused(n, q, (!OrIsAsgn && n->ntyp != ASGN)); 440*219b2ee8SDavid du Colombier 441*219b2ee8SDavid du Colombier if (n->ntyp == ASGN) 442*219b2ee8SDavid du Colombier varprobe(parent, n->lft->lft, q); 443*219b2ee8SDavid du Colombier else 444*219b2ee8SDavid du Colombier varprobe(parent, n->lft, q); 445*219b2ee8SDavid du Colombier 446*219b2ee8SDavid du Colombier if (n->ntyp == 'r') 447*219b2ee8SDavid du Colombier OrIsAsgn = 1; 448*219b2ee8SDavid du Colombier 449*219b2ee8SDavid du Colombier varprobe(parent, n->rgt, q); 450*219b2ee8SDavid du Colombier 451*219b2ee8SDavid du Colombier if (n->ntyp == 'r') 452*219b2ee8SDavid du Colombier OrIsAsgn = 0; 453*219b2ee8SDavid du Colombier } 454*219b2ee8SDavid du Colombier 455*219b2ee8SDavid du Colombier #if 0 456*219b2ee8SDavid du Colombier #define walkprog varcheck 457*219b2ee8SDavid du Colombier #else 458*219b2ee8SDavid du Colombier #define Varcheck varcheck 459*219b2ee8SDavid du Colombier #endif 460*219b2ee8SDavid du Colombier 461*219b2ee8SDavid du Colombier void 462*219b2ee8SDavid du Colombier Varcheck(Element *e, Element *nx) 463*219b2ee8SDavid du Colombier { SeqList *f; extern Symbol *context; 464*219b2ee8SDavid du Colombier 465*219b2ee8SDavid du Colombier if (!dataflow || !e || e->status&CHECK1) 466*219b2ee8SDavid du Colombier return; 467*219b2ee8SDavid du Colombier #ifdef DEBUG 468*219b2ee8SDavid du Colombier { int oln; Symbol *ofn; 469*219b2ee8SDavid du Colombier printf("%s:%d -- ", context->name, e->Seqno); 470*219b2ee8SDavid du Colombier oln = lineno; ofn = Fname; 471*219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 472*219b2ee8SDavid du Colombier lineno = oln; Fname = ofn; 473*219b2ee8SDavid du Colombier printf(" -- %d:%s\n", e->n->ln, e->n->fn->name); 474*219b2ee8SDavid du Colombier } 475*219b2ee8SDavid du Colombier #endif 476*219b2ee8SDavid du Colombier e->status |= CHECK1; 477*219b2ee8SDavid du Colombier 478*219b2ee8SDavid du Colombier if (e->n->ntyp == GOTO) 479*219b2ee8SDavid du Colombier { Element *ef = target(e); 480*219b2ee8SDavid du Colombier if (ef) varcheck(ef, ef->nxt); 481*219b2ee8SDavid du Colombier goto done; 482*219b2ee8SDavid du Colombier } else if (e->n->sl && !e->sub) /* d_step or (non)-atomic */ 483*219b2ee8SDavid du Colombier { for (f = e->n->sl; f; f = f->nxt) 484*219b2ee8SDavid du Colombier { f->this->last->nxt = nx; 485*219b2ee8SDavid du Colombier #ifdef DEBUG 486*219b2ee8SDavid du Colombier printf("\tPatch1 %d->%d\n", 487*219b2ee8SDavid du Colombier f->this->last->seqno, nx?nx->seqno:-1); 488*219b2ee8SDavid du Colombier varcheck(f->this->frst, nx); 489*219b2ee8SDavid du Colombier #endif 490*219b2ee8SDavid du Colombier f->this->last->nxt = 0; 491*219b2ee8SDavid du Colombier } 492*219b2ee8SDavid du Colombier } else if (e->sub && e->n->ntyp == IF) /* if */ 493*219b2ee8SDavid du Colombier { for (f = e->sub; f; f = f->nxt) 494*219b2ee8SDavid du Colombier varcheck(f->this->frst, nx); 495*219b2ee8SDavid du Colombier } else if (e->sub && e->n->ntyp == DO) /* do */ 496*219b2ee8SDavid du Colombier { for (f = e->sub; f; f = f->nxt) 497*219b2ee8SDavid du Colombier varcheck(f->this->frst, e); 498*219b2ee8SDavid du Colombier } else 499*219b2ee8SDavid du Colombier { varprobe(e, e->n, e->nxt); 500*219b2ee8SDavid du Colombier } 501*219b2ee8SDavid du Colombier { Element *ef = huntele(e->nxt, e->status); 502*219b2ee8SDavid du Colombier if (ef) varcheck(ef, ef->nxt); 503*219b2ee8SDavid du Colombier } 504*219b2ee8SDavid du Colombier done: 505*219b2ee8SDavid du Colombier /* e->status &= ~CHECK1 */ ; 506*219b2ee8SDavid du Colombier } 507*219b2ee8SDavid du Colombier 508*219b2ee8SDavid du Colombier void 509*219b2ee8SDavid du Colombier nested(int n) 510*219b2ee8SDavid du Colombier { int i; 511*219b2ee8SDavid du Colombier for (i = 0; i < n; i++) 512*219b2ee8SDavid du Colombier printf("\t"); 513*219b2ee8SDavid du Colombier } 514*219b2ee8SDavid du Colombier 515*219b2ee8SDavid du Colombier void 516*219b2ee8SDavid du Colombier walkprog(Element *e, Element *nx) 517*219b2ee8SDavid du Colombier { SeqList *f; extern Symbol *context; 518*219b2ee8SDavid du Colombier static int Nest=0; int oln; 519*219b2ee8SDavid du Colombier 520*219b2ee8SDavid du Colombier if (!dataflow) return; 521*219b2ee8SDavid du Colombier if (!e) 522*219b2ee8SDavid du Colombier { nested(Nest); 523*219b2ee8SDavid du Colombier printf("nil\n"); 524*219b2ee8SDavid du Colombier return; 525*219b2ee8SDavid du Colombier } 526*219b2ee8SDavid du Colombier 527*219b2ee8SDavid du Colombier nested(Nest); 528*219b2ee8SDavid du Colombier printf("%4d,%4d, %s:%d(%u) -- ", 529*219b2ee8SDavid du Colombier e->status, lineno, 530*219b2ee8SDavid du Colombier context->name, e->Seqno, e); 531*219b2ee8SDavid du Colombier oln = lineno; 532*219b2ee8SDavid du Colombier comment(stdout, e->n, 0); 533*219b2ee8SDavid du Colombier lineno = oln; 534*219b2ee8SDavid du Colombier printf(" -- %d:%s\n", e->n->ln, e->n->fn->name); 535*219b2ee8SDavid du Colombier 536*219b2ee8SDavid du Colombier if (e->status&CHECK1) 537*219b2ee8SDavid du Colombier { nested(Nest); 538*219b2ee8SDavid du Colombier printf("seenbefore\n"); 539*219b2ee8SDavid du Colombier return; 540*219b2ee8SDavid du Colombier } 541*219b2ee8SDavid du Colombier 542*219b2ee8SDavid du Colombier e->status |= CHECK1; 543*219b2ee8SDavid du Colombier 544*219b2ee8SDavid du Colombier if (e->n->ntyp == GOTO) 545*219b2ee8SDavid du Colombier { Element *ef = target(e); 546*219b2ee8SDavid du Colombier if (ef) walkprog(ef, ef->nxt); 547*219b2ee8SDavid du Colombier } else if (e->n->sl && !e->sub) /* ATOMIC, NON_ATOMIC, D_STEP */ 548*219b2ee8SDavid du Colombier { int cnt; 549*219b2ee8SDavid du Colombier 550*219b2ee8SDavid du Colombier for (f = e->n->sl, cnt=1; f; f = f->nxt, cnt++) 551*219b2ee8SDavid du Colombier { Nest++; 552*219b2ee8SDavid du Colombier nested(Nest); 553*219b2ee8SDavid du Colombier printf("---a>%d:\n", cnt); 554*219b2ee8SDavid du Colombier #ifdef DEBUG 555*219b2ee8SDavid du Colombier printf("\tPatch0 %d->%d\n", 556*219b2ee8SDavid du Colombier f->this->last->seqno, nx?nx->seqno:-1); 557*219b2ee8SDavid du Colombier f->this->last->nxt = nx; 558*219b2ee8SDavid du Colombier walkprog(f->this->frst, nx); 559*219b2ee8SDavid du Colombier #endif 560*219b2ee8SDavid du Colombier /* f->this->last->nxt = 0; */ 561*219b2ee8SDavid du Colombier Nest--; 562*219b2ee8SDavid du Colombier } 563*219b2ee8SDavid du Colombier } else if (e->sub && e->n->ntyp == IF) 564*219b2ee8SDavid du Colombier { int cnt; 565*219b2ee8SDavid du Colombier for (f = e->sub, cnt=1; f; f = f->nxt, cnt++) 566*219b2ee8SDavid du Colombier { Nest++; 567*219b2ee8SDavid du Colombier nested(Nest); 568*219b2ee8SDavid du Colombier printf("---s>%d:\n", cnt); 569*219b2ee8SDavid du Colombier walkprog(f->this->frst, nx); 570*219b2ee8SDavid du Colombier Nest--; 571*219b2ee8SDavid du Colombier } 572*219b2ee8SDavid du Colombier } else if (e->sub && e->n->ntyp == DO) 573*219b2ee8SDavid du Colombier { int cnt; 574*219b2ee8SDavid du Colombier for (f = e->sub, cnt=1; f; f = f->nxt, cnt++) 575*219b2ee8SDavid du Colombier { Nest++; 576*219b2ee8SDavid du Colombier nested(Nest); 577*219b2ee8SDavid du Colombier printf("---s>%d:\n", cnt); 578*219b2ee8SDavid du Colombier walkprog(f->this->frst, e); 579*219b2ee8SDavid du Colombier Nest--; 580*219b2ee8SDavid du Colombier } 581*219b2ee8SDavid du Colombier } 582*219b2ee8SDavid du Colombier { Element *ef = huntele(e->nxt, e->status); 583*219b2ee8SDavid du Colombier if (ef) walkprog(ef, ef->nxt); 584*219b2ee8SDavid du Colombier } 585*219b2ee8SDavid du Colombier e->status &= ~CHECK1; 586*219b2ee8SDavid du Colombier } 587