xref: /plan9-contrib/sys/src/cmd/spin/mesg.c (revision de2caf28f9ba1a56e70be94a699435d36eb50311)
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