1 /***** spin: mesg.c *****/
4 * This file is part of the public release of Spin. It is subject to the
5 * terms in the LICENSE file that is included in this source directory.
6 * Tool documentation is available at http://spinroot.com
14 #define MAXQ 2500 /* default max # queues */
20 extern int verbose, TstOnly, s_trail, analyze, columns;
21 extern int lineno, depth, xspin, m_loss, jumpsteps;
22 extern int nproc, nstop;
23 extern short Have_claim;
26 Queue *qtab = (Queue *) 0; /* linked list of queues */
27 Queue *ltab[MAXQ]; /* linear list of queues */
28 int nqs = 0, firstrow = 1, has_stdin = 0;
31 static Lextok *n_rem = (Lextok *) 0;
32 static Queue *q_rem = (Queue *) 0;
34 static int a_rcv(Queue *, Lextok *, int);
35 static int a_snd(Queue *, Lextok *);
36 static int sa_snd(Queue *, Lextok *);
37 static int s_snd(Queue *, Lextok *);
38 extern void sr_buf(int, int);
39 extern void sr_mesg(FILE *, int, int);
40 extern void putarrow(int, int);
41 static void sr_talk(Lextok *, int, char *, char *, int, Queue *);
48 for (m = n; m; m = m->rgt)
63 { lineno = s->ini->ln;
65 fatal("too many queues (%s)", s->name);
67 if (analyze && nqs >= 255)
68 { fatal("too many channel types", (char *)0);
71 if (s->ini->ntyp != CHAN)
74 q = (Queue *) emalloc(sizeof(Queue));
75 q->qid = (short) ++nqs;
76 q->nslots = s->ini->val;
77 q->nflds = cnt_mpars(s->ini->rgt);
80 i = max(1, q->nslots); /* 0-slot qs get 1 slot minimum */
82 q->contents = (int *) emalloc(q->nflds*i*sizeof(int));
83 q->fld_width = (int *) emalloc(q->nflds*sizeof(int));
84 q->stepnr = (int *) emalloc(i*sizeof(int));
86 for (m = s->ini->rgt, i = 0; m; m = m->rgt)
87 { if (m->sym && m->ntyp == STRUCT)
88 i = Width_set(q->fld_width, i, getuname(m->sym));
90 q->fld_width[i++] = m->ntyp;
101 { int whichq = eval(n->lft)-1;
103 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
104 return (ltab[whichq]->qlen >= ltab[whichq]->nslots);
110 { int whichq = eval(n->lft)-1;
112 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
113 return ltab[whichq]->qlen;
119 { int whichq = eval(n->lft)-1;
121 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
122 return (ltab[whichq]->nslots == 0);
128 { int whichq = eval(n->lft)-1;
131 { printf("Error: sending to an uninitialized chan\n");
135 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
136 { ltab[whichq]->setat = depth;
137 if (ltab[whichq]->nslots > 0)
138 return a_snd(ltab[whichq], n);
140 return s_snd(ltab[whichq], n);
147 static struct termios initial_settings, new_settings;
152 tcgetattr(0,&initial_settings);
154 new_settings = initial_settings;
155 new_settings.c_lflag &= ~ICANON;
156 new_settings.c_lflag &= ~ECHO;
157 new_settings.c_lflag &= ~ISIG;
158 new_settings.c_cc[VMIN] = 0;
159 new_settings.c_cc[VTIME] = 0;
168 tcsetattr(0, TCSANOW, &new_settings);
170 tcsetattr(0, TCSANOW, &initial_settings);
177 qrecv(Lextok *n, int full)
178 { int whichq = eval(n->lft)-1;
181 { if (n->sym && !strcmp(n->sym->name, "STDIN"))
184 static int did_once = 0;
185 if (!did_once) /* 6.2.4 */
190 if (TstOnly) return 1;
192 for (m = n->rgt; m; m = m->rgt)
193 if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
198 int c = peek_ch(); /* 6.2.4, was getchar(); */
200 if (c == 27 || c == 3) /* escape or control-c */
203 } /* else: non-blocking */
204 if (c == EOF) return 0; /* no char available */
205 (void) setval(m->lft, c);
207 { fatal("invalid use of STDIN", (char *)0);
211 printf("Error: receiving from an uninitialized chan %s\n",
212 n->sym?n->sym->name:"");
216 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
217 { ltab[whichq]->setat = depth;
218 return a_rcv(ltab[whichq], n, full);
224 sa_snd(Queue *q, Lextok *n) /* sorted asynchronous */
229 for (i = 0; i < q->qlen; i++)
230 for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
231 { New = cast_val(q->fld_width[j], eval(m->lft), 0);
232 Old = q->contents[i*q->nflds+j];
236 break; /* inner loop */
237 goto found; /* New < Old */
240 for (j = q->qlen-1; j >= i; j--)
241 for (k = 0; k < q->nflds; k++)
242 { q->contents[(j+1)*q->nflds+k] =
243 q->contents[j*q->nflds+k]; /* shift up */
245 q->stepnr[j+1] = q->stepnr[j];
247 return i*q->nflds; /* new q offset */
251 typ_ck(int ft, int at, char *s)
253 if ((verbose&32) && ft != at
254 && (ft == CHAN || at == CHAN)
255 && (at != PREDEF || strcmp(s, "recv") != 0))
256 { char buf[128], tag1[64], tag2[64];
257 (void) sputtype(tag1, ft);
258 (void) sputtype(tag2, at);
259 sprintf(buf, "type-clash in %s, (%s<-> %s)", s, tag1, tag2);
260 non_fatal("%s", buf);
265 a_snd(Queue *q, Lextok *n)
267 int i = q->qlen*q->nflds; /* q offset */
268 int j = 0; /* q field# */
270 if (q->nslots > 0 && q->qlen >= q->nslots)
271 return m_loss; /* q is full */
273 if (TstOnly) return 1;
275 if (n->val) i = sa_snd(q, n); /* sorted insert */
277 q->stepnr[i/q->nflds] = depth;
279 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
280 { int New = eval(m->lft);
281 q->contents[i+j] = cast_val(q->fld_width[j], New, 0);
282 if ((verbose&16) && depth >= jumpsteps)
283 sr_talk(n, New, "Send ", "->", j, q);
284 typ_ck(q->fld_width[j], Sym_typ(m->lft), "send");
286 if ((verbose&16) && depth >= jumpsteps)
287 { for (i = j; i < q->nflds; i++)
288 sr_talk(n, 0, "Send ", "->", i, q);
290 printf("%3d: warning: missing params in send\n",
293 printf("%3d: warning: too many params in send\n",
301 a_rcv(Queue *q, Lextok *n, int full)
307 return 0; /* q is empty */
309 /* test executability */
310 for (m = n->rgt, j=0; m && j < q->nflds; m = m->rgt, j++)
311 if ((m->lft->ntyp == CONST
312 && q->contents[i*q->nflds+j] != m->lft->val)
313 || (m->lft->ntyp == EVAL
314 && q->contents[i*q->nflds+j] != eval(m->lft->lft)))
315 { if (n->val == 0 /* fifo recv */
316 || n->val == 2 /* fifo poll */
317 || ++i >= q->qlen) /* last slot */
318 return 0; /* no match */
321 if (TstOnly) return 1;
325 printf("%3d: warning: missing params in next recv\n",
328 printf("%3d: warning: too many params in next recv\n",
339 for (m = n->rgt, j = 0; m && j < q->nflds; m = m->rgt, j++)
340 { if (columns && !full) /* was columns == 1 */
342 if ((verbose&8) && !Rvous && depth >= jumpsteps)
343 { sr_talk(n, q->contents[i*q->nflds+j],
344 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", j, q);
348 if (m && m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
349 { (void) setval(m->lft, q->contents[i*q->nflds+j]);
350 typ_ck(q->fld_width[j], Sym_typ(m->lft), "recv");
352 if (n->val < 2) /* not a poll */
353 for (k = i; k < q->qlen-1; k++)
354 { q->contents[k*q->nflds+j] =
355 q->contents[(k+1)*q->nflds+j];
357 q->stepnr[k] = q->stepnr[k+1];
361 if ((!columns || full)
362 && (verbose&8) && !Rvous && depth >= jumpsteps)
363 for (i = j; i < q->nflds; i++)
365 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", i, q);
367 if (columns == 2 && full && !Rvous && depth >= jumpsteps)
370 if (full && n->val < 2)
376 s_snd(Queue *q, Lextok *n)
378 RunList *rX, *sX = X; /* rX=recvr, sX=sendr */
379 int i, j = 0; /* q field# */
381 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
382 { q->contents[j] = cast_val(q->fld_width[j], eval(m->lft), 0);
383 typ_ck(q->fld_width[j], Sym_typ(m->lft), "rv-send");
386 if (!complete_rendez())
394 q->stepnr[0] = depth;
395 if ((verbose&16) && depth >= jumpsteps)
398 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
399 sr_talk(n, eval(m->lft), "Sent ", "->", j, q);
400 for (i = j; i < q->nflds; i++)
401 sr_talk(n, 0, "Sent ", "->", i, q);
403 printf("%3d: warning: missing params in rv-send\n",
406 printf("%3d: warning: too many params in rv-send\n",
408 X = rX; /* restore receiver's context */
410 { if (!n_rem || !q_rem)
411 fatal("cannot happen, s_snd", (char *) 0);
413 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
414 { if (m->lft->ntyp != NAME
415 || strcmp(m->lft->sym->name, "_") != 0)
420 sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
423 for (i = j; i < q->nflds; i++)
424 sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
426 putarrow(depth, depth);
428 n_rem = (Lextok *) 0;
438 if (n->sym->type == CHAN)
439 strcat(Buf, n->sym->name);
440 else if (n->sym->type == NAME)
441 strcat(Buf, lookup(n->sym->name)->name);
442 else if (n->sym->type == STRUCT)
443 { Symbol *r = n->sym;
447 { strcat(Buf, "*?*");
451 printf("%s", r->name);
453 struct_name(n->lft, r, 1, lbuf);
458 { sprintf(lbuf, "[%d]", eval(n->lft->lft));
464 difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
470 strcat(Buf, (strncmp(tr, "Sen", 3))?"?":"!");
473 if (tr[0] == '[') strcat(Buf, "[");
474 sr_buf(v, q->fld_width[j] == MTYPE);
475 if (j == q->nflds - 1)
480 { cnr = X?X->pid - Have_claim:0;
482 if (tr[0] == '[') strcat(Buf, "]");
488 docolumns(Lextok *n, char *tr, int v, int j, Queue *q)
493 for (i = 0; i < nproc-nstop - Have_claim; i++)
499 { printf("%3d", q->qid);
501 for (i = 0; i < X->pid - Have_claim; i++)
506 printf("%s%c", Buf, (strncmp(tr, "Sen", 3))?'?':'!');
509 if (tr[0] == '[') printf("[");
510 sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
511 if (j == q->nflds - 1)
512 { if (tr[0] == '[') printf("]");
519 { QH *p = (QH *) emalloc(sizeof(QH));
528 for (p = qh; p; p = p->nxt)
535 sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
538 if (qishidden(eval(n->lft)))
543 difcolumns(n, tr, v, j, q);
545 docolumns(n, tr, v, j, q);
549 { if ((verbose&4) && tr[0] != '[')
550 sprintf(s, "(state -)\t[values: %d",
553 sprintf(s, "(state -)\t[%d", eval(n->lft));
554 if (strncmp(tr, "Sen", 3) == 0)
565 { char *ptr = n->fn->name;
579 sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
581 if (j == q->nflds - 1)
584 if (!(verbose&4)) printf("\n");
587 printf("\t%s queue %d (", a, eval(n->lft));
590 printf("%s)\n", Buf);
597 { int cnt = 1; Lextok *n;
600 for (n = Mtype; n && j; n = n->rgt, cnt++)
602 { if(strlen(n->lft->sym->name) >= sizeof(lbuf))
603 { non_fatal("mtype name %s too long", n->lft->sym->name);
606 sprintf(lbuf, "%s", n->lft->sym->name);
610 sprintf(lbuf, "%d", v);
615 sr_mesg(FILE *fd, int v, int j)
619 fprintf(fd, Buf, (char *) 0); /* prevent compiler warning */
626 doq(Symbol *s, int n, RunList *r)
630 if (!s->val) /* uninitialized queue */
632 for (q = qtab; q; q = q->nxt)
633 if (q->qid == s->val[n])
639 continue; /* rv q always empty */
641 if (q->qlen == 0) /* new 7/10 -- dont show if queue is empty */
645 printf("\t\tqueue %d (", q->qid);
647 printf("%s(%d):", r->n->name, r->pid - Have_claim);
648 if (s->nel > 1 || s->isarray)
649 printf("%s[%d]): ", s->name, n);
651 printf("%s): ", s->name);
652 for (k = 0; k < q->qlen; k++)
654 for (j = 0; j < q->nflds; j++)
655 { if (j > 0) printf(",");
656 sr_mesg(stdout, q->contents[k*q->nflds+j],
657 q->fld_width[j] == MTYPE);
667 nochan_manip(Lextok *p, Lextok *n, int d)
670 if (d == 0 && p->sym && p->sym->type == CHAN)
671 { setaccess(p->sym, ZS, 0, 'L');
673 if (n && n->ntyp == CONST)
674 fatal("invalid asgn to chan", (char *) 0);
676 if (n && n->sym && n->sym->type == CHAN)
677 { setaccess(n->sym, ZS, 0, 'V');
682 /* ok on the rhs of an assignment: */
683 if (!n || n->ntyp == LEN || n->ntyp == RUN
684 || n->ntyp == FULL || n->ntyp == NFULL
685 || n->ntyp == EMPTY || n->ntyp == NEMPTY
689 if (n->sym && n->sym->type == CHAN)
691 fatal("invalid use of chan name", (char *) 0);
693 setaccess(n->sym, ZS, 0, 'V');
698 e = 0; /* array index or struct element */
700 nochan_manip(p, n->lft, e);
701 nochan_manip(p, n->rgt, 1);
704 typedef struct BaseName {
707 struct BaseName *nxt;
710 static BaseName *bsn;
716 /* printf("+++++++++%s\n", s); */
717 for (b = bsn; b; b = b->nxt)
718 if (strcmp(b->str, s) == 0)
722 b = (BaseName *) emalloc(sizeof(BaseName));
723 b->str = emalloc(strlen(s)+1);
732 { BaseName *b, *prv = (BaseName *) 0;
734 for (b = bsn; b; prv = b, b = b->nxt)
735 { if (strcmp(b->str, s) == 0)
743 /* printf("---------%s\n", s); */
749 checkindex(char *s, char *t)
752 /* printf("xxx Check %s (%s)\n", s, t); */
753 for (b = bsn; b; b = b->nxt)
755 /* printf(" %s\n", b->str); */
756 if (strcmp(b->str, s) == 0)
757 { non_fatal("do not index an array with itself (%s)", t);
763 scan_tree(Lextok *t, char *mn, char *mx)
773 { strcat(mn, t->sym->name);
774 strcat(mx, t->sym->name);
775 if (t->lft) /* array index */
778 strcpy(sv, mn); /* save */
779 strcpy(mn, ""); /* clear */
781 scan_tree(t->lft, mn, mx); /* index */
783 checkindex(mn, mx); /* match against basenames */
784 strcpy(mn, sv); /* restore */
787 if (t->rgt) /* structure element */
788 { scan_tree(t->rgt, mn, mx);
790 } else if (t->ntyp == CONST)
791 { strcat(mn, "1"); /* really: t->val */
792 sprintf(tmp, "%d", t->val);
794 } else if (t->ntyp == '.')
797 scan_tree(t->lft, mn, mx);
806 no_nested_array_refs(Lextok *n) /* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */
810 /* printf("==================================ZAP\n"); */
811 bsn = (BaseName *) 0; /* start new list */
815 scan_tree(n, mn, mx);
816 /* printf("==> %s\n", mn); */
820 no_internals(Lextok *n)
829 if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
830 || (strlen(sp) == strlen("_pid") && strcmp(sp, "_pid") == 0)
831 || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
832 { fatal("invalid assignment to %s", sp);
835 no_nested_array_refs(n);