1 /***** spin: mesg.c *****/
2
3 /*
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
7 */
8
9 #include <stdlib.h>
10 #include <assert.h>
11 #include "spin.h"
12 #include "y.tab.h"
13
14 #ifndef MAXQ
15 #define MAXQ 2500 /* default max # queues */
16 #endif
17
18 extern RunList *X_lst;
19 extern Symbol *Fname;
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;
24
25 QH *qh_lst;
26 Queue *qtab = (Queue *) 0; /* linked list of queues */
27 Queue *ltab[MAXQ]; /* linear list of queues */
28 int nrqs = 0, firstrow = 1, has_stdin = 0;
29 char GBuf[4096];
30
31 static Lextok *n_rem = (Lextok *) 0;
32 static Queue *q_rem = (Queue *) 0;
33
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 Lextok **find_mtype_list(const char *);
39 extern char *which_mtype(const char *);
40 extern void sr_buf(int, int, const char *);
41 extern void sr_mesg(FILE *, int, int, const char *);
42 extern void putarrow(int, int);
43 static void sr_talk(Lextok *, int, char *, char *, int, Queue *);
44
45 int
cnt_mpars(Lextok * n)46 cnt_mpars(Lextok *n)
47 { Lextok *m;
48 int i=0;
49
50 for (m = n; m; m = m->rgt)
51 i += Cnt_flds(m);
52 return i;
53 }
54
55 int
qmake(Symbol * s)56 qmake(Symbol *s)
57 { Lextok *m;
58 Queue *q;
59 int i, j;
60
61 if (!s->ini)
62 return 0;
63
64 if (nrqs >= MAXQ)
65 { lineno = s->ini->ln;
66 Fname = s->ini->fn;
67 fatal("too many queues (%s)", s->name);
68 }
69 if (analyze && nrqs >= 255)
70 { fatal("too many channel types", (char *)0);
71 }
72
73 if (s->ini->ntyp != CHAN)
74 return eval(s->ini);
75
76 q = (Queue *) emalloc(sizeof(Queue));
77 q->qid = (short) ++nrqs;
78 q->nslots = s->ini->val;
79 q->nflds = cnt_mpars(s->ini->rgt);
80 q->setat = depth;
81
82 i = max(1, q->nslots); /* 0-slot qs get 1 slot minimum */
83 j = q->nflds * i;
84
85 q->contents = (int *) emalloc(j*sizeof(int));
86 q->fld_width = (int *) emalloc(q->nflds*sizeof(int));
87 q->mtp = (char **) emalloc(q->nflds*sizeof(char *));
88 q->stepnr = (int *) emalloc(i*sizeof(int));
89
90 for (m = s->ini->rgt, i = 0; m; m = m->rgt)
91 { if (m->sym && m->ntyp == STRUCT)
92 { i = Width_set(q->fld_width, i, getuname(m->sym));
93 } else
94 { if (m->sym)
95 { q->mtp[i] = m->sym->name;
96 }
97 q->fld_width[i++] = m->ntyp;
98 } }
99 q->nxt = qtab;
100 qtab = q;
101 ltab[q->qid-1] = q;
102
103 return q->qid;
104 }
105
106 int
qfull(Lextok * n)107 qfull(Lextok *n)
108 { int whichq = eval(n->lft)-1;
109
110 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
111 return (ltab[whichq]->qlen >= ltab[whichq]->nslots);
112 return 0;
113 }
114
115 int
qlen(Lextok * n)116 qlen(Lextok *n)
117 { int whichq = eval(n->lft)-1;
118
119 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
120 return ltab[whichq]->qlen;
121 return 0;
122 }
123
124 int
q_is_sync(Lextok * n)125 q_is_sync(Lextok *n)
126 { int whichq = eval(n->lft)-1;
127
128 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
129 return (ltab[whichq]->nslots == 0);
130 return 0;
131 }
132
133 int
qsend(Lextok * n)134 qsend(Lextok *n)
135 { int whichq = eval(n->lft)-1;
136
137 if (whichq == -1)
138 { printf("Error: sending to an uninitialized chan\n");
139 /* whichq = 0; */
140 return 0;
141 }
142 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
143 { ltab[whichq]->setat = depth;
144 if (ltab[whichq]->nslots > 0)
145 { return a_snd(ltab[whichq], n);;
146 } else
147 { return s_snd(ltab[whichq], n);
148 } }
149 return 0;
150 }
151
152 #ifndef PC
153 #include <termios.h>
154 static struct termios initial_settings, new_settings;
155
156 void
peek_ch_init(void)157 peek_ch_init(void)
158 {
159 tcgetattr(0,&initial_settings);
160
161 new_settings = initial_settings;
162 new_settings.c_lflag &= ~ICANON;
163 new_settings.c_lflag &= ~ECHO;
164 new_settings.c_lflag &= ~ISIG;
165 new_settings.c_cc[VMIN] = 0;
166 new_settings.c_cc[VTIME] = 0;
167 }
168
169 int
peek_ch(void)170 peek_ch(void)
171 { int n;
172
173 has_stdin = 1;
174
175 tcsetattr(0, TCSANOW, &new_settings);
176 n = getchar();
177 tcsetattr(0, TCSANOW, &initial_settings);
178
179 return n;
180 }
181 #endif
182
183 int
qrecv(Lextok * n,int full)184 qrecv(Lextok *n, int full)
185 { int whichq = eval(n->lft)-1;
186
187 if (whichq == -1)
188 { if (n->sym && !strcmp(n->sym->name, "STDIN"))
189 { Lextok *m;
190 #ifndef PC
191 static int did_once = 0;
192 if (!did_once) /* 6.2.4 */
193 { peek_ch_init();
194 did_once = 1;
195 }
196 #endif
197 if (TstOnly) return 1;
198
199 for (m = n->rgt; m; m = m->rgt)
200 if (m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
201 {
202 #ifdef PC
203 int c = getchar();
204 #else
205 int c = peek_ch(); /* 6.2.4, was getchar(); */
206 #endif
207 if (c == 27 || c == 3) /* escape or control-c */
208 { printf("quit\n");
209 exit(0);
210 } /* else: non-blocking */
211 if (c == EOF) return 0; /* no char available */
212 (void) setval(m->lft, c);
213 } else
214 { fatal("invalid use of STDIN", (char *)0);
215 }
216 return 1;
217 }
218 printf("Error: receiving from an uninitialized chan %s\n",
219 n->sym?n->sym->name:"");
220 /* whichq = 0; */
221 return 0;
222 }
223 if (whichq < MAXQ && whichq >= 0 && ltab[whichq])
224 { ltab[whichq]->setat = depth;
225 return a_rcv(ltab[whichq], n, full);
226 }
227 return 0;
228 }
229
230 static int
sa_snd(Queue * q,Lextok * n)231 sa_snd(Queue *q, Lextok *n) /* sorted asynchronous */
232 { Lextok *m;
233 int i, j, k;
234 int New, Old;
235
236 for (i = 0; i < q->qlen; i++)
237 for (j = 0, m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
238 { New = cast_val(q->fld_width[j], eval(m->lft), 0);
239 Old = q->contents[i*q->nflds+j];
240 if (New == Old)
241 continue;
242 if (New > Old)
243 break; /* inner loop */
244 goto found; /* New < Old */
245 }
246 found:
247 for (j = q->qlen-1; j >= i; j--)
248 for (k = 0; k < q->nflds; k++)
249 { q->contents[(j+1)*q->nflds+k] =
250 q->contents[j*q->nflds+k]; /* shift up */
251 if (k == 0)
252 q->stepnr[j+1] = q->stepnr[j];
253 }
254 return i*q->nflds; /* new q offset */
255 }
256
257 void
typ_ck(int ft,int at,char * s)258 typ_ck(int ft, int at, char *s)
259 {
260 if ((verbose&32) && ft != at
261 && (ft == CHAN || at == CHAN)
262 && (at != PREDEF || strcmp(s, "recv") != 0))
263 { char buf[256], tag1[64], tag2[64];
264 (void) sputtype(tag1, ft);
265 (void) sputtype(tag2, at);
266 sprintf(buf, "type-clash in %s, (%s<-> %s)", s, tag1, tag2);
267 non_fatal("%s", buf);
268 }
269 }
270
271 static void
mtype_ck(char * p,Lextok * arg)272 mtype_ck(char *p, Lextok *arg)
273 { char *t, *s = p?p:"_unnamed_";
274
275 if (!arg
276 || !arg->sym)
277 { return;
278 }
279
280 switch (arg->ntyp) {
281 case NAME:
282 if (arg->sym->mtype_name)
283 { t = arg->sym->mtype_name->name;
284 } else
285 { t = "_unnamed_";
286 }
287 break;
288 case CONST:
289 t = which_mtype(arg->sym->name);
290 break;
291 default:
292 t = "expression";
293 break;
294 }
295
296 if (strcmp(s, t) != 0)
297 { printf("spin: %s:%d, Error: '%s' is type '%s', but ",
298 arg->fn?arg->fn->name:"", arg->ln,
299 arg->sym->name, t);
300 printf("should be type '%s'\n", s);
301 non_fatal("incorrect type of '%s'", arg->sym->name);
302 }
303 }
304
305 static int
a_snd(Queue * q,Lextok * n)306 a_snd(Queue *q, Lextok *n)
307 { Lextok *m;
308 int i = q->qlen*q->nflds; /* q offset */
309 int j = 0; /* q field# */
310
311 if (q->nslots > 0 && q->qlen >= q->nslots)
312 { return m_loss; /* q is full */
313 }
314
315 if (TstOnly)
316 { return 1;
317 }
318 if (n->val) i = sa_snd(q, n); /* sorted insert */
319
320 q->stepnr[i/q->nflds] = depth;
321
322 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
323 { int New = eval(m->lft);
324 q->contents[i+j] = cast_val(q->fld_width[j], New, 0);
325
326 if (q->fld_width[i+j] == MTYPE)
327 { mtype_ck(q->mtp[i+j], m->lft); /* 6.4.8 */
328 }
329 if ((verbose&16) && depth >= jumpsteps)
330 { sr_talk(n, New, "Send ", "->", j, q); /* XXX j was i+j in 6.4.8 */
331 }
332 typ_ck(q->fld_width[i+j], Sym_typ(m->lft), "send");
333 }
334
335 if ((verbose&16) && depth >= jumpsteps)
336 { for (i = j; i < q->nflds; i++)
337 { sr_talk(n, 0, "Send ", "->", i, q);
338 }
339 if (j < q->nflds)
340 { printf("%3d: warning: missing params in send\n",
341 depth);
342 }
343 if (m)
344 { printf("%3d: warning: too many params in send\n",
345 depth);
346 } }
347 q->qlen++;
348 return 1;
349 }
350
351 static int
a_rcv(Queue * q,Lextok * n,int full)352 a_rcv(Queue *q, Lextok *n, int full)
353 { Lextok *m;
354 int i=0, oi, j, k;
355 extern int Rvous;
356
357 if (q->qlen == 0)
358 { return 0; /* q is empty */
359 }
360 try_slot:
361 /* test executability */
362 for (m = n->rgt, j=0; m && j < q->nflds; m = m->rgt, j++)
363 {
364 if (q->fld_width[i*q->nflds+j] == MTYPE)
365 { mtype_ck(q->mtp[i*q->nflds+j], m->lft); /* 6.4.8 */
366 }
367
368 if (m->lft->ntyp == CONST
369 && q->contents[i*q->nflds+j] != m->lft->val)
370 {
371 if (n->val == 0 /* fifo recv */
372 || n->val == 2 /* fifo poll */
373 || ++i >= q->qlen) /* last slot */
374 { return 0; /* no match */
375 }
376 goto try_slot; /* random recv */
377 }
378
379 if (m->lft->ntyp == EVAL)
380 { Lextok *fix = m->lft->lft;
381
382 if (fix->ntyp == ',') /* new, usertype7 */
383 { do {
384 assert(j < q->nflds);
385 if (q->contents[i*q->nflds+j] != eval(fix->lft))
386 { if (n->val == 0
387 || n->val == 2
388 || ++i >= q->qlen)
389 { return 0;
390 }
391 goto try_slot; /* random recv */
392 }
393 j++;
394 fix = fix->rgt;
395 } while (fix && fix->ntyp == ',');
396 j--;
397 } else
398 { if (q->contents[i*q->nflds+j] != eval(fix))
399 { if (n->val == 0 /* fifo recv */
400 || n->val == 2 /* fifo poll */
401 || ++i >= q->qlen) /* last slot */
402 { return 0; /* no match */
403 }
404 goto try_slot; /* random recv */
405 } } }
406 }
407
408 if (TstOnly) return 1;
409
410 if (verbose&8)
411 { if (j < q->nflds)
412 { printf("%3d: warning: missing params in next recv\n",
413 depth);
414 } else if (m)
415 { printf("%3d: warning: too many params in next recv\n",
416 depth);
417 } }
418
419 /* set the fields */
420 if (Rvous)
421 { n_rem = n;
422 q_rem = q;
423 }
424
425 oi = q->stepnr[i];
426 for (m = n->rgt, j = 0; m && j < q->nflds; m = m->rgt, j++)
427 { if (columns && !full) /* was columns == 1 */
428 continue;
429 if ((verbose&8) && !Rvous && depth >= jumpsteps)
430 { sr_talk(n, q->contents[i*q->nflds+j],
431 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", j, q);
432 }
433 if (!full)
434 continue; /* test */
435 if (m && m->lft->ntyp != CONST && m->lft->ntyp != EVAL)
436 { (void) setval(m->lft, q->contents[i*q->nflds+j]);
437 typ_ck(q->fld_width[j], Sym_typ(m->lft), "recv");
438 }
439 if (n->val < 2) /* not a poll */
440 for (k = i; k < q->qlen-1; k++)
441 { q->contents[k*q->nflds+j] =
442 q->contents[(k+1)*q->nflds+j];
443 if (j == 0)
444 q->stepnr[k] = q->stepnr[k+1];
445 }
446 }
447
448 if ((!columns || full)
449 && (verbose&8) && !Rvous && depth >= jumpsteps)
450 for (i = j; i < q->nflds; i++)
451 { sr_talk(n, 0,
452 (full && n->val < 2)?"Recv ":"[Recv] ", "<-", i, q);
453 }
454 if (columns == 2 && full && !Rvous && depth >= jumpsteps)
455 putarrow(oi, depth);
456
457 if (full && n->val < 2)
458 q->qlen--;
459 return 1;
460 }
461
462 static int
s_snd(Queue * q,Lextok * n)463 s_snd(Queue *q, Lextok *n)
464 { Lextok *m;
465 RunList *rX, *sX = X_lst; /* rX=recvr, sX=sendr */
466 int i, j = 0; /* q field# */
467
468 for (m = n->rgt; m && j < q->nflds; m = m->rgt, j++)
469 { q->contents[j] = cast_val(q->fld_width[j], eval(m->lft), 0);
470 typ_ck(q->fld_width[j], Sym_typ(m->lft), "rv-send");
471
472 if (q->fld_width[j] == MTYPE)
473 { mtype_ck(q->mtp[j], m->lft); /* 6.4.8 */
474 } }
475
476 q->qlen = 1;
477 if (!complete_rendez())
478 { q->qlen = 0;
479 return 0;
480 }
481 if (TstOnly)
482 { q->qlen = 0;
483 return 1;
484 }
485 q->stepnr[0] = depth;
486 if ((verbose&16) && depth >= jumpsteps)
487 { m = n->rgt;
488 rX = X_lst; X_lst = sX;
489
490 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
491 { sr_talk(n, eval(m->lft), "Sent ", "->", j, q);
492 }
493
494 for (i = j; i < q->nflds; i++)
495 { sr_talk(n, 0, "Sent ", "->", i, q);
496 }
497
498 if (j < q->nflds)
499 { printf("%3d: warning: missing params in rv-send\n",
500 depth);
501 } else if (m)
502 { printf("%3d: warning: too many params in rv-send\n",
503 depth);
504 }
505
506 X_lst = rX; /* restore receiver's context */
507 if (!s_trail)
508 { if (!n_rem || !q_rem)
509 fatal("cannot happen, s_snd", (char *) 0);
510 m = n_rem->rgt;
511 for (j = 0; m && j < q->nflds; m = m->rgt, j++)
512 {
513 if (q->fld_width[j] == MTYPE)
514 { mtype_ck(q->mtp[j], m->lft); /* 6.4.8 */
515 }
516
517 if (m->lft->ntyp != NAME
518 || strcmp(m->lft->sym->name, "_") != 0)
519 { i = eval(m->lft);
520 } else
521 { i = 0;
522 }
523 if (verbose&8)
524 sr_talk(n_rem,i,"Recv ","<-",j,q_rem);
525 }
526 if (verbose&8)
527 for (i = j; i < q->nflds; i++)
528 sr_talk(n_rem, 0, "Recv ", "<-", j, q_rem);
529 if (columns == 2)
530 putarrow(depth, depth);
531 }
532 n_rem = (Lextok *) 0;
533 q_rem = (Queue *) 0;
534 }
535 return 1;
536 }
537
538 static void
channm(Lextok * n)539 channm(Lextok *n)
540 { char lbuf[512];
541
542 if (n->sym->type == CHAN)
543 strcat(GBuf, n->sym->name);
544 else if (n->sym->type == NAME)
545 strcat(GBuf, lookup(n->sym->name)->name);
546 else if (n->sym->type == STRUCT)
547 { Symbol *r = n->sym;
548 if (r->context)
549 { r = findloc(r);
550 if (!r)
551 { strcat(GBuf, "*?*");
552 return;
553 } }
554 ini_struct(r);
555 printf("%s", r->name);
556 strcpy(lbuf, "");
557 struct_name(n->lft, r, 1, lbuf);
558 strcat(GBuf, lbuf);
559 } else
560 strcat(GBuf, "-");
561 if (n->lft->lft)
562 { sprintf(lbuf, "[%d]", eval(n->lft->lft));
563 strcat(GBuf, lbuf);
564 }
565 }
566
567 static void
difcolumns(Lextok * n,char * tr,int v,int j,Queue * q)568 difcolumns(Lextok *n, char *tr, int v, int j, Queue *q)
569 { extern int prno;
570
571 if (j == 0)
572 { GBuf[0] = '\0';
573 channm(n);
574 strcat(GBuf, (strncmp(tr, "Sen", 3))?"?":"!");
575 } else
576 strcat(GBuf, ",");
577 if (tr[0] == '[') strcat(GBuf, "[");
578 sr_buf(v, q->fld_width[j] == MTYPE, q->mtp[j]);
579 if (j == q->nflds - 1)
580 { int cnr;
581 if (s_trail)
582 { cnr = prno - Have_claim;
583 } else
584 { cnr = X_lst?X_lst->pid - Have_claim:0;
585 }
586 if (tr[0] == '[') strcat(GBuf, "]");
587 pstext(cnr, GBuf);
588 }
589 }
590
591 static void
docolumns(Lextok * n,char * tr,int v,int j,Queue * q)592 docolumns(Lextok *n, char *tr, int v, int j, Queue *q)
593 { int i;
594
595 if (firstrow)
596 { printf("q\\p");
597 for (i = 0; i < nproc-nstop - Have_claim; i++)
598 printf(" %3d", i);
599 printf("\n");
600 firstrow = 0;
601 }
602 if (j == 0)
603 { printf("%3d", q->qid);
604 if (X_lst)
605 for (i = 0; i < X_lst->pid - Have_claim; i++)
606 printf(" .");
607 printf(" ");
608 GBuf[0] = '\0';
609 channm(n);
610 printf("%s%c", GBuf, (strncmp(tr, "Sen", 3))?'?':'!');
611 } else
612 printf(",");
613 if (tr[0] == '[') printf("[");
614 sr_mesg(stdout, v, q->fld_width[j] == MTYPE, q->mtp[j]);
615 if (j == q->nflds - 1)
616 { if (tr[0] == '[') printf("]");
617 printf("\n");
618 }
619 }
620
621 void
qhide(int q)622 qhide(int q)
623 { QH *p = (QH *) emalloc(sizeof(QH));
624 p->n = q;
625 p->nxt = qh_lst;
626 qh_lst = p;
627 }
628
629 int
qishidden(int q)630 qishidden(int q)
631 { QH *p;
632 for (p = qh_lst; p; p = p->nxt)
633 if (p->n == q)
634 return 1;
635 return 0;
636 }
637
638 static void
sr_talk(Lextok * n,int v,char * tr,char * a,int j,Queue * q)639 sr_talk(Lextok *n, int v, char *tr, char *a, int j, Queue *q)
640 { char s[128];
641
642 if (qishidden(eval(n->lft)))
643 return;
644
645 if (columns)
646 { if (columns == 2)
647 difcolumns(n, tr, v, j, q);
648 else
649 docolumns(n, tr, v, j, q);
650 return;
651 }
652 if (xspin)
653 { if ((verbose&4) && tr[0] != '[')
654 sprintf(s, "(state -)\t[values: %d",
655 eval(n->lft));
656 else
657 sprintf(s, "(state -)\t[%d", eval(n->lft));
658 if (strncmp(tr, "Sen", 3) == 0)
659 strcat(s, "!");
660 else
661 strcat(s, "?");
662 } else
663 { strcpy(s, tr);
664 }
665
666 if (j == 0)
667 { char snm[128];
668 whoruns(1);
669 { char *ptr = n->fn->name;
670 char *qtr = snm;
671 while (*ptr != '\0')
672 { if (*ptr != '\"')
673 { *qtr++ = *ptr;
674 }
675 ptr++;
676 }
677 *qtr = '\0';
678 printf("%s:%d %s",
679 snm, n->ln, s);
680 }
681 } else
682 { printf(",");
683 }
684 sr_mesg(stdout, v, q->fld_width[j] == MTYPE, q->mtp[j]);
685
686 if (j == q->nflds - 1)
687 { if (xspin)
688 { printf("]\n");
689 if (!(verbose&4)) printf("\n");
690 return;
691 }
692 printf("\t%s queue %d (", a, eval(n->lft));
693 GBuf[0] = '\0';
694 channm(n);
695 printf("%s)\n", GBuf);
696 }
697 fflush(stdout);
698 }
699
700 void
sr_buf(int v,int j,const char * s)701 sr_buf(int v, int j, const char *s)
702 { int cnt = 1; Lextok *n;
703 char lbuf[512];
704 Lextok *Mtype = ZN;
705
706 if (j)
707 { Mtype = *find_mtype_list(s?s:"_unnamed_");
708 }
709 for (n = Mtype; n && j; n = n->rgt, cnt++)
710 { if (cnt == v)
711 { if(strlen(n->lft->sym->name) >= sizeof(lbuf))
712 { non_fatal("mtype name %s too long", n->lft->sym->name);
713 break;
714 }
715 sprintf(lbuf, "%s", n->lft->sym->name);
716 strcat(GBuf, lbuf);
717 return;
718 } }
719 sprintf(lbuf, "%d", v);
720 strcat(GBuf, lbuf);
721 }
722
723 void
sr_mesg(FILE * fd,int v,int j,const char * s)724 sr_mesg(FILE *fd, int v, int j, const char *s)
725 { GBuf[0] ='\0';
726
727 sr_buf(v, j, s);
728 fprintf(fd, GBuf, (char *) 0); /* prevent compiler warning */
729 }
730
731 void
doq(Symbol * s,int n,RunList * r)732 doq(Symbol *s, int n, RunList *r)
733 { Queue *q;
734 int j, k;
735
736 if (!s->val) /* uninitialized queue */
737 return;
738 for (q = qtab; q; q = q->nxt)
739 if (q->qid == s->val[n])
740 { if (xspin > 0
741 && (verbose&4)
742 && q->setat < depth)
743 { continue;
744 }
745 if (q->nslots == 0)
746 { continue; /* rv q always empty */
747 }
748
749 printf("\t\tqueue %d (", q->qid);
750 if (r)
751 { printf("%s(%d):", r->n->name, r->pid - Have_claim);
752 }
753
754 if (s->nel > 1 || s->isarray)
755 { printf("%s[%d]): ", s->name, n);
756 } else
757 { printf("%s): ", s->name);
758 }
759
760 for (k = 0; k < q->qlen; k++)
761 { printf("[");
762 for (j = 0; j < q->nflds; j++)
763 { if (j > 0) printf(",");
764 sr_mesg(stdout,
765 q->contents[k*q->nflds+j],
766 q->fld_width[j] == MTYPE,
767 q->mtp[j]);
768 }
769 printf("]");
770 }
771 printf("\n");
772 break;
773 }
774 }
775
776 void
nochan_manip(Lextok * p,Lextok * n,int d)777 nochan_manip(Lextok *p, Lextok *n, int d) /* p=lhs n=rhs */
778 { int e = 1;
779
780 if (!n
781 || !p
782 || !p->sym
783 || p->sym->type == STRUCT)
784 { /* if a struct, assignments to structure fields arent checked yet */
785 return;
786 }
787
788 if (d == 0 && p->sym && p->sym->type == CHAN)
789 { setaccess(p->sym, ZS, 0, 'L');
790
791 if (n && n->ntyp == CONST)
792 fatal("invalid asgn to chan", (char *) 0);
793
794 if (n && n->sym && n->sym->type == CHAN)
795 { setaccess(n->sym, ZS, 0, 'V');
796 return;
797 }
798 }
799
800 if (!d && n && n->ismtyp) /* rhs is an mtype value (a constant) */
801 { char *lhs = "_unnamed_", *rhs = "_unnamed_";
802
803 if (p->sym)
804 { lhs = p->sym->mtype_name?p->sym->mtype_name->name:"_unnamed_";
805 }
806 if (n->sym)
807 { rhs = which_mtype(n->sym->name); /* only for constants */
808 }
809
810 if (p->sym && !p->sym->mtype_name && n->sym)
811 { p->sym->mtype_name = (Symbol *) emalloc(sizeof(Symbol));
812 p->sym->mtype_name->name = rhs;
813 } else if (strcmp(lhs, rhs) != 0)
814 { fprintf(stderr, "spin: %s:%d, Error: '%s' is type '%s' but '%s' is type '%s'\n",
815 p->fn->name, p->ln,
816 p->sym?p->sym->name:"?", lhs,
817 n->sym?n->sym->name:"?", rhs);
818 non_fatal("type error", (char *) 0);
819 } }
820
821 /* ok on the rhs of an assignment: */
822 if (!n
823 || n->ntyp == LEN || n->ntyp == RUN
824 || n->ntyp == FULL || n->ntyp == NFULL
825 || n->ntyp == EMPTY || n->ntyp == NEMPTY
826 || n->ntyp == 'R')
827 return;
828
829 if (n->sym && n->sym->type == CHAN)
830 { if (d == 1)
831 fatal("invalid use of chan name", (char *) 0);
832 else
833 setaccess(n->sym, ZS, 0, 'V');
834 }
835
836 if (n->ntyp == NAME
837 || n->ntyp == '.')
838 { e = 0; /* array index or struct element */
839 }
840
841 nochan_manip(p, n->lft, e);
842 nochan_manip(p, n->rgt, 1);
843 }
844
845 typedef struct BaseName {
846 char *str;
847 int cnt;
848 struct BaseName *nxt;
849 } BaseName;
850
851 static BaseName *bsn;
852
853 void
newbasename(char * s)854 newbasename(char *s)
855 { BaseName *b;
856
857 /* printf("+++++++++%s\n", s); */
858 for (b = bsn; b; b = b->nxt)
859 if (strcmp(b->str, s) == 0)
860 { b->cnt++;
861 return;
862 }
863 b = (BaseName *) emalloc(sizeof(BaseName));
864 b->str = emalloc(strlen(s)+1);
865 b->cnt = 1;
866 strcpy(b->str, s);
867 b->nxt = bsn;
868 bsn = b;
869 }
870
871 void
delbasename(char * s)872 delbasename(char *s)
873 { BaseName *b, *prv = (BaseName *) 0;
874
875 for (b = bsn; b; prv = b, b = b->nxt)
876 { if (strcmp(b->str, s) == 0)
877 { b->cnt--;
878 if (b->cnt == 0)
879 { if (prv)
880 { prv->nxt = b->nxt;
881 } else
882 { bsn = b->nxt;
883 } }
884 /* printf("---------%s\n", s); */
885 break;
886 } }
887 }
888
889 void
checkindex(char * s,char * t)890 checkindex(char *s, char *t)
891 { BaseName *b;
892
893 /* printf("xxx Check %s (%s)\n", s, t); */
894 for (b = bsn; b; b = b->nxt)
895 {
896 /* printf(" %s\n", b->str); */
897 if (strcmp(b->str, s) == 0)
898 { non_fatal("do not index an array with itself (%s)", t);
899 break;
900 } }
901 }
902
903 void
scan_tree(Lextok * t,char * mn,char * mx)904 scan_tree(Lextok *t, char *mn, char *mx)
905 { char sv[512];
906 char tmp[32];
907 int oln = lineno;
908
909 if (!t) return;
910
911 lineno = t->ln;
912
913 if (t->ntyp == NAME)
914 { if (strlen(t->sym->name) + strlen(mn) > 256) // conservative
915 { fatal("name too long", t->sym->name);
916 }
917
918 strcat(mn, t->sym->name);
919 strcat(mx, t->sym->name);
920 if (t->lft) /* array index */
921 { strcat(mn, "[]");
922 newbasename(mn);
923 strcpy(sv, mn); /* save */
924 strcpy(mn, ""); /* clear */
925 strcat(mx, "[");
926 scan_tree(t->lft, mn, mx); /* index */
927 strcat(mx, "]");
928 checkindex(mn, mx); /* match against basenames */
929 strcpy(mn, sv); /* restore */
930 delbasename(mn);
931 }
932 if (t->rgt) /* structure element */
933 { scan_tree(t->rgt, mn, mx);
934 }
935 } else if (t->ntyp == CONST)
936 { strcat(mn, "1"); /* really: t->val */
937 sprintf(tmp, "%d", t->val);
938 strcat(mx, tmp);
939 } else if (t->ntyp == '.')
940 { strcat(mn, ".");
941 strcat(mx, ".");
942 scan_tree(t->lft, mn, mx);
943 } else
944 { strcat(mn, "??");
945 strcat(mx, "??");
946 }
947 lineno = oln;
948 }
949
950 void
no_nested_array_refs(Lextok * n)951 no_nested_array_refs(Lextok *n) /* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */
952 { char mn[512];
953 char mx[512];
954
955 /* printf("==================================ZAP\n"); */
956 bsn = (BaseName *) 0; /* start new list */
957 strcpy(mn, "");
958 strcpy(mx, "");
959
960 scan_tree(n, mn, mx);
961 /* printf("==> %s\n", mn); */
962 }
963
964 void
no_internals(Lextok * n)965 no_internals(Lextok *n)
966 { char *sp;
967
968 if (!n->sym
969 || !n->sym->name)
970 return;
971
972 sp = n->sym->name;
973
974 if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
975 || (strlen(sp) == strlen("_pid") && strcmp(sp, "_pid") == 0)
976 || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
977 { fatal("invalid assignment to %s", sp);
978 }
979
980 no_nested_array_refs(n);
981 }
982