move everything out of trunk
[lttv.git] / verif / Spin / Src5.1.6 / mesg.c
1 /***** spin: mesg.c *****/
2
3 /* Copyright (c) 1989-2003 by Lucent Technologies, Bell Laboratories. */
4 /* All Rights Reserved. This software is for educational purposes only. */
5 /* No guarantee whatsoever is expressed or implied by the distribution of */
6 /* this code. Permission is given to distribute this code provided that */
7 /* this introductory message is not removed and no monies are exchanged. */
8 /* Software written by Gerard J. Holzmann. For tool documentation see: */
9 /* http://spinroot.com/ */
10 /* Send all bug-reports and/or questions to: bugs@spinroot.com */
11
12 #include "spin.h"
13 #include "y.tab.h"
14
15 #ifndef MAXQ
16 #define MAXQ 2500 /* default max # queues */
17 #endif
18
19 extern RunList *X;
20 extern Symbol *Fname;
21 extern Lextok *Mtype;
22 extern int verbose, TstOnly, s_trail, analyze, columns;
23 extern int lineno, depth, xspin, m_loss, jumpsteps;
24 extern int nproc, nstop;
25 extern short Have_claim;
26
27 Queue *qtab = (Queue *) 0; /* linked list of queues */
28 Queue *ltab[MAXQ]; /* linear list of queues */
29 int nqs = 0, firstrow = 1;
30 char Buf[4096];
31
32 static Lextok *n_rem = (Lextok *) 0;
33 static Queue *q_rem = (Queue *) 0;
34
35 static int a_rcv(Queue *, Lextok *, int);
36 static int a_snd(Queue *, Lextok *);
37 static int sa_snd(Queue *, Lextok *);
38 static int s_snd(Queue *, Lextok *);
39 extern void sr_buf(int, int);
40 extern void sr_mesg(FILE *, int, int);
41 extern void putarrow(int, int);
42 static void sr_talk(Lextok *, int, char *, char *, int, Queue *);
43
44 int
45 cnt_mpars(Lextok *n)
46 { Lextok *m;
47 int i=0;
48
49 for (m = n; m; m = m->rgt)
50 i += Cnt_flds(m);
51 return i;
52 }
53
54 int
55 qmake(Symbol *s)
56 { Lextok *m;
57 Queue *q;
58 int i;
59
60 if (!s->ini)
61 return 0;
62
63 if (nqs >= MAXQ)
64 { lineno = s->ini->ln;
65 Fname = s->ini->fn;
66 fatal("too many queues (%s)", s->name);
67 }
68 if (analyze && nqs >= 255)
69 { fatal("too many channel types", (char *)0);
70 }
71
72 if (s->ini->ntyp != CHAN)
73 return eval(s->ini);
74
75 q = (Queue *) emalloc(sizeof(Queue));
76 q->qid = ++nqs;
77 q->nslots = s->ini->val;
78 q->nflds = cnt_mpars(s->ini->rgt);
79 q->setat = depth;
80
81 i = max(1, q->nslots); /* 0-slot qs get 1 slot minimum */
82
83 q->contents = (int *) emalloc(q->nflds*i*sizeof(int));
84 q->fld_width = (int *) emalloc(q->nflds*sizeof(int));
85 q->stepnr = (int *) emalloc(i*sizeof(int));
86
87 for (m = s->ini->rgt, i = 0; m; m = m->rgt)
88 { if (m->sym && m->ntyp == STRUCT)
89 i = Width_set(q->fld_width, i, getuname(m->sym));
90 else
91 q->fld_width[i++] = m->ntyp;
92 }
93 q->nxt = qtab;
94 qtab = q;
95 ltab[q->qid-1] = q;
96
97 return q->qid;
98 }
99
100 int
101 qfull(Lextok *n)
102 { int whichq = eval(n->lft)-1;
103
104 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
105 return (ltab[whichq]->qlen >= ltab[whichq]->nslots);
106 return 0;
107 }
108
109 int
110 qlen(Lextok *n)
111 { int whichq = eval(n->lft)-1;
112
113 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
114 return ltab[whichq]->qlen;
115 return 0;
116 }
117
118 int
119 q_is_sync(Lextok *n)
120 { int whichq = eval(n->lft)-1;
121
122 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
123 return (ltab[whichq]->nslots == 0);
124 return 0;
125 }
126
127 int
128 qsend(Lextok *n)
129 { int whichq = eval(n->lft)-1;
130
131 if (whichq == -1)
132 { printf("Error: sending to an uninitialized chan\n");
133 whichq = 0;
134 return 0;
135 }
136 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
137 { ltab[whichq]->setat = depth;
138 if (ltab[whichq]->nslots > 0)
139 return a_snd(ltab[whichq], n);
140 else
141 return s_snd(ltab[whichq], n);
142 }
143 return 0;
144 }
145
146 int
147 qrecv(Lextok *n, int full)
148 { int whichq = eval(n->lft)-1;
149
150 if (whichq == -1)
151 { if (n->sym && !strcmp(n->sym->name, "STDIN"))
152 { Lextok *m;
153
154 if (TstOnly) return 1;
155
156 for (m = n->rgt; m; m = m->rgt)
157 if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
158 { int c = getchar();
159 (void) setval(m->lft, c);
160 } else
161 fatal("invalid use of STDIN", (char *)0);
162
163 whichq = 0;
164 return 1;
165 }
166 printf("Error: receiving from an uninitialized chan %s\n",
167 n->sym?n->sym->name:"");
168 whichq = 0;
169 return 0;
170 }
171 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
172 { ltab[whichq]->setat = depth;
173 return a_rcv(ltab[whichq], n, full);
174 }
175 return 0;
176 }
177
178 static int
179 sa_snd(Queue *q, Lextok *n) /* sorted asynchronous */
180 { Lextok *m;
181 int i, j, k;
182 int New, Old;
183
184 for (i = 0; i < q->qlen; i++)
185 for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
186 { New = cast_val(q->fld_width[j], eval(m->lft), 0);
187 Old = q->contents[i*q->nflds+j];
188 if (New == Old)
189 continue;
190 if (New > Old)
191 break; /* inner loop */
192 goto found; /* New < Old */
193 }
194 found:
195 for (j = q->qlen-1; j >= i; j--)
196 for (k = 0; k < q->nflds; k++)
197 { q->contents[(j+1)*q->nflds+k] =
198 q->contents[j*q->nflds+k]; /* shift up */
199 if (k == 0)
200 q->stepnr[j+1] = q->stepnr[j];
201 }
202 return i*q->nflds; /* new q offset */
203 }
204
205 void
206 typ_ck(int ft, int at, char *s)
207 {
208 if ((verbose&32) && ft != at
209 && (ft == CHAN || at == CHAN))
210 { char buf[128], tag1[64], tag2[64];
211 (void) sputtype(tag1, ft);
212 (void) sputtype(tag2, at);
213 sprintf(buf, "type-clash in %s, (%s<-> %s)", s, tag1, tag2);
214 non_fatal("%s", buf);
215 }
216 }
217
218 static int
219 a_snd(Queue *q, Lextok *n)
220 { Lextok *m;
221 int i = q->qlen*q->nflds; /* q offset */
222 int j = 0; /* q field# */
223
224 if (q->nslots > 0 && q->qlen >= q->nslots)
225 return m_loss; /* q is full */
226
227 if (TstOnly) return 1;
228
229 if (n->val) i = sa_snd(q, n); /* sorted insert */
230
231 q->stepnr[i/q->nflds] = depth;
232
233 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
234 { int New = eval(m->lft);
235 q->contents[i+j] = cast_val(q->fld_width[j], New, 0);
236 if ((verbose&16) && depth >= jumpsteps)
237 sr_talk(n, New, "Send ", "->", j, q);
238 typ_ck(q->fld_width[j], Sym_typ(m->lft), "send");
239 }
240 if ((verbose&16) && depth >= jumpsteps)
241 { for (i = j; i < q->nflds; i++)
242 sr_talk(n, 0, "Send ", "->", i, q);
243 if (j < q->nflds)
244 printf("%3d: warning: missing params in send\n",
245 depth);
246 if (m)
247 printf("%3d: warning: too many params in send\n",
248 depth);
249 }
250 q->qlen++;
251 return 1;
252 }
253
254 static int
255 a_rcv(Queue *q, Lextok *n, int full)
256 { Lextok *m;
257 int i=0, oi, j, k;
258 extern int Rvous;
259
260 if (q->qlen == 0)
261 return 0; /* q is empty */
262 try_slot:
263 /* test executability */
264 for (m = n->rgt, j=0; m && j < q->nflds; m = m->rgt, j++)
265 if ((m->lft->ntyp == CONST
266 && q->contents[i*q->nflds+j] != m->lft->val)
267 || (m->lft->ntyp == EVAL
268 && q->contents[i*q->nflds+j] != eval(m->lft->lft)))
269 { if (n->val == 0 /* fifo recv */
270 || n->val == 2 /* fifo poll */
271 || ++i >= q->qlen) /* last slot */
272 return 0; /* no match */
273 goto try_slot;
274 }
275 if (TstOnly) return 1;
276
277 if (verbose&8)
278 { if (j < q->nflds)
279 printf("%3d: warning: missing params in next recv\n",
280 depth);
281 else if (m)
282 printf("%3d: warning: too many params in next recv\n",
283 depth);
284 }
285
286 /* set the fields */
287 if (Rvous)
288 { n_rem = n;
289 q_rem = q;
290 }
291
292 oi = q->stepnr[i];
293 for (m = n->rgt, j = 0; m && j < q->nflds; m = m->rgt, j++)
294 { if (columns && !full) /* was columns == 1 */
295 continue;
296 if ((verbose&8) && !Rvous && depth >= jumpsteps)
297 { sr_talk(n, q->contents[i*q->nflds+j],
298 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", j, q);
299 }
300 if (!full)
301 continue; /* test */
302 if (m && m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
303 { (void) setval(m->lft, q->contents[i*q->nflds+j]);
304 typ_ck(q->fld_width[j], Sym_typ(m->lft), "recv");
305 }
306 if (n->val < 2) /* not a poll */
307 for (k = i; k < q->qlen-1; k++)
308 { q->contents[k*q->nflds+j] =
309 q->contents[(k+1)*q->nflds+j];
310 if (j == 0)
311 q->stepnr[k] = q->stepnr[k+1];
312 }
313 }
314
315 if ((!columns || full)
316 && (verbose&8) && !Rvous && depth >= jumpsteps)
317 for (i = j; i < q->nflds; i++)
318 { sr_talk(n, 0,
319 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", i, q);
320 }
321 if (columns == 2 && full && !Rvous && depth >= jumpsteps)
322 putarrow(oi, depth);
323
324 if (full && n->val < 2)
325 q->qlen--;
326 return 1;
327 }
328
329 static int
330 s_snd(Queue *q, Lextok *n)
331 { Lextok *m;
332 RunList *rX, *sX = X; /* rX=recvr, sX=sendr */
333 int i, j = 0; /* q field# */
334
335 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
336 { q->contents[j] = cast_val(q->fld_width[j], eval(m->lft), 0);
337 typ_ck(q->fld_width[j], Sym_typ(m->lft), "rv-send");
338 }
339 q->qlen = 1;
340 if (!complete_rendez())
341 { q->qlen = 0;
342 return 0;
343 }
344 if (TstOnly)
345 { q->qlen = 0;
346 return 1;
347 }
348 q->stepnr[0] = depth;
349 if ((verbose&16) && depth >= jumpsteps)
350 { m = n->rgt;
351 rX = X; X = sX;
352 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
353 sr_talk(n, eval(m->lft), "Sent ", "->", j, q);
354 for (i = j; i < q->nflds; i++)
355 sr_talk(n, 0, "Sent ", "->", i, q);
356 if (j < q->nflds)
357 printf("%3d: warning: missing params in rv-send\n",
358 depth);
359 else if (m)
360 printf("%3d: warning: too many params in rv-send\n",
361 depth);
362 X = rX; /* restore receiver's context */
363 if (!s_trail)
364 { if (!n_rem || !q_rem)
365 fatal("cannot happen, s_snd", (char *) 0);
366 m = n_rem->rgt;
367 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
368 { if (m->lft->ntyp != NAME
369 || strcmp(m->lft->sym->name, "_") != 0)
370 i = eval(m->lft);
371 else i = 0;
372
373 if (verbose&8)
374 sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
375 }
376 if (verbose&8)
377 for (i = j; i < q->nflds; i++)
378 sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
379 if (columns == 2)
380 putarrow(depth, depth);
381 }
382 n_rem = (Lextok *) 0;
383 q_rem = (Queue *) 0;
384 }
385 return 1;
386 }
387
388 static void
389 channm(Lextok *n)
390 { char lbuf[512];
391
392 if (n->sym->type == CHAN)
393 strcat(Buf, n->sym->name);
394 else if (n->sym->type == NAME)
395 strcat(Buf, lookup(n->sym->name)->name);
396 else if (n->sym->type == STRUCT)
397 { Symbol *r = n->sym;
398 if (r->context)
399 { r = findloc(r);
400 if (!r)
401 { strcat(Buf, "*?*");
402 return;
403 } }
404 ini_struct(r);
405 printf("%s", r->name);
406 strcpy(lbuf, "");
407 struct_name(n->lft, r, 1, lbuf);
408 strcat(Buf, lbuf);
409 } else
410 strcat(Buf, "-");
411 if (n->lft->lft)
412 { sprintf(lbuf, "[%d]", eval(n->lft->lft));
413 strcat(Buf, lbuf);
414 }
415 }
416
417 static void
418 difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
419 { extern int pno;
420
421 if (j == 0)
422 { Buf[0] = '\0';
423 channm(n);
424 strcat(Buf, (strncmp(tr, "Sen", 3))?"?":"!");
425 } else
426 strcat(Buf, ",");
427 if (tr[0] == '[') strcat(Buf, "[");
428 sr_buf(v, q->fld_width[j] == MTYPE);
429 if (j == q->nflds - 1)
430 { int cnr;
431 if (s_trail) cnr = pno; else cnr = X?X->pid - Have_claim:0;
432 if (tr[0] == '[') strcat(Buf, "]");
433 pstext(cnr, Buf);
434 }
435 }
436
437 static void
438 docolumns(Lextok *n, char *tr, int v, int j, Queue *q)
439 { int i;
440
441 if (firstrow)
442 { printf("q\\p");
443 for (i = 0; i < nproc-nstop - Have_claim; i++)
444 printf(" %3d", i);
445 printf("\n");
446 firstrow = 0;
447 }
448 if (j == 0)
449 { printf("%3d", q->qid);
450 if (X)
451 for (i = 0; i < X->pid - Have_claim; i++)
452 printf(" .");
453 printf(" ");
454 Buf[0] = '\0';
455 channm(n);
456 printf("%s%c", Buf, (strncmp(tr, "Sen", 3))?'?':'!');
457 } else
458 printf(",");
459 if (tr[0] == '[') printf("[");
460 sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
461 if (j == q->nflds - 1)
462 { if (tr[0] == '[') printf("]");
463 printf("\n");
464 }
465 }
466
467 typedef struct QH {
468 int n;
469 struct QH *nxt;
470 } QH;
471 static QH *qh;
472
473 void
474 qhide(int q)
475 { QH *p = (QH *) emalloc(sizeof(QH));
476 p->n = q;
477 p->nxt = qh;
478 qh = p;
479 }
480
481 int
482 qishidden(int q)
483 { QH *p;
484 for (p = qh; p; p = p->nxt)
485 if (p->n == q)
486 return 1;
487 return 0;
488 }
489
490 static void
491 sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
492 { char s[128];
493
494 if (qishidden(eval(n->lft)))
495 return;
496
497 if (columns)
498 { if (columns == 2)
499 difcolumns(n, tr, v, j, q);
500 else
501 docolumns(n, tr, v, j, q);
502 return;
503 }
504 if (xspin)
505 { if ((verbose&4) && tr[0] != '[')
506 sprintf(s, "(state -)\t[values: %d",
507 eval(n->lft));
508 else
509 sprintf(s, "(state -)\t[%d", eval(n->lft));
510 if (strncmp(tr, "Sen", 3) == 0)
511 strcat(s, "!");
512 else
513 strcat(s, "?");
514 } else
515 { strcpy(s, tr);
516 }
517
518 if (j == 0)
519 { whoruns(1);
520 printf("line %3d %s %s",
521 n->ln, n->fn->name, s);
522 } else
523 printf(",");
524 sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
525
526 if (j == q->nflds - 1)
527 { if (xspin)
528 { printf("]\n");
529 if (!(verbose&4)) printf("\n");
530 return;
531 }
532 printf("\t%s queue %d (", a, eval(n->lft));
533 Buf[0] = '\0';
534 channm(n);
535 printf("%s)\n", Buf);
536 }
537 fflush(stdout);
538 }
539
540 void
541 sr_buf(int v, int j)
542 { int cnt = 1; Lextok *n;
543 char lbuf[512];
544
545 for (n = Mtype; n && j; n = n->rgt, cnt++)
546 if (cnt == v)
547 { if(strlen(n->lft->sym->name) >= sizeof(lbuf))
548 { non_fatal("mtype name %s too long", n->lft->sym->name);
549 break;
550 }
551 sprintf(lbuf, "%s", n->lft->sym->name);
552 strcat(Buf, lbuf);
553 return;
554 }
555 sprintf(lbuf, "%d", v);
556 strcat(Buf, lbuf);
557 }
558
559 void
560 sr_mesg(FILE *fd, int v, int j)
561 { Buf[0] ='\0';
562 sr_buf(v, j);
563 fprintf(fd, Buf);
564 }
565
566 void
567 doq(Symbol *s, int n, RunList *r)
568 { Queue *q;
569 int j, k;
570
571 if (!s->val) /* uninitialized queue */
572 return;
573 for (q = qtab; q; q = q->nxt)
574 if (q->qid == s->val[n])
575 { if (xspin > 0
576 && (verbose&4)
577 && q->setat < depth)
578 continue;
579 if (q->nslots == 0)
580 continue; /* rv q always empty */
581 printf("\t\tqueue %d (", q->qid);
582 if (r)
583 printf("%s(%d):", r->n->name, r->pid - Have_claim);
584 if (s->nel != 1)
585 printf("%s[%d]): ", s->name, n);
586 else
587 printf("%s): ", s->name);
588 for (k = 0; k < q->qlen; k++)
589 { printf("[");
590 for (j = 0; j < q->nflds; j++)
591 { if (j > 0) printf(",");
592 sr_mesg(stdout, q->contents[k*q->nflds+j],
593 q->fld_width[j] == MTYPE);
594 }
595 printf("]");
596 }
597 printf("\n");
598 break;
599 }
600 }
601
602 void
603 nochan_manip(Lextok *p, Lextok *n, int d)
604 { int e = 1;
605
606 if (d == 0 && p->sym && p->sym->type == CHAN)
607 { setaccess(p->sym, ZS, 0, 'L');
608
609 if (n && n->ntyp == CONST)
610 fatal("invalid asgn to chan", (char *) 0);
611
612 if (n && n->sym && n->sym->type == CHAN)
613 { setaccess(n->sym, ZS, 0, 'V');
614 return;
615 }
616 }
617
618 if (!n || n->ntyp == LEN || n->ntyp == RUN)
619 return;
620
621 if (n->sym && n->sym->type == CHAN)
622 { if (d == 1)
623 fatal("invalid use of chan name", (char *) 0);
624 else
625 setaccess(n->sym, ZS, 0, 'V');
626 }
627
628 if (n->ntyp == NAME
629 || n->ntyp == '.')
630 e = 0; /* array index or struct element */
631
632 nochan_manip(p, n->lft, e);
633 nochan_manip(p, n->rgt, 1);
634 }
635
636 void
637 no_internals(Lextok *n)
638 { char *sp;
639
640 if (!n->sym
641 || !n->sym->name)
642 return;
643
644 sp = n->sym->name;
645
646 if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
647 || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
648 { fatal("attempt to assign value to system variable %s", sp);
649 }
650 }
This page took 0.043465 seconds and 4 git commands to generate.