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
cnt_mpars(Lextok * n)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
qmake(Symbol * s)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
qfull(Lextok * n)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
qlen(Lextok * n)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
q_is_sync(Lextok * n)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
qsend(Lextok * n)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
qrecv(Lextok * n,int full)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
sa_snd(Queue * q,Lextok * n)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
typ_ck(int ft,int at,char * s)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
a_snd(Queue * q,Lextok * n)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
a_rcv(Queue * q,Lextok * n,int full)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
s_snd(Queue * q,Lextok * n)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
channm(Lextok * n)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
difcolumns(Lextok * n,char * tr,int v,int j,Queue * q)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
docolumns(Lextok * n,char * tr,int v,int j,Queue * q)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
qhide(int q)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
qishidden(int q)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
sr_talk(Lextok * n,int v,char * tr,char * a,int j,Queue * q)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 { char snm[128];
520 whoruns(1);
521 { char *ptr = n->fn->name;
522 char *qtr = snm;
523 while (*ptr != '\0')
524 { if (*ptr != '\"')
525 { *qtr++ = *ptr;
526 }
527 ptr++;
528 }
529 *qtr = '\0';
530 printf("%s:%d %s",
531 snm, n->ln, s);
532 }
533 } else
534 printf(",");
535 sr_mesg(stdout, v, q->fld_width[j] == MTYPE);
536
537 if (j == q->nflds - 1)
538 { if (xspin)
539 { printf("]\n");
540 if (!(verbose&4)) printf("\n");
541 return;
542 }
543 printf("\t%s queue %d (", a, eval(n->lft));
544 Buf[0] = '\0';
545 channm(n);
546 printf("%s)\n", Buf);
547 }
548 fflush(stdout);
549 }
550
551 void
sr_buf(int v,int j)552 sr_buf(int v, int j)
553 { int cnt = 1; Lextok *n;
554 char lbuf[512];
555
556 for (n = Mtype; n && j; n = n->rgt, cnt++)
557 if (cnt == v)
558 { if(strlen(n->lft->sym->name) >= sizeof(lbuf))
559 { non_fatal("mtype name %s too long", n->lft->sym->name);
560 break;
561 }
562 sprintf(lbuf, "%s", n->lft->sym->name);
563 strcat(Buf, lbuf);
564 return;
565 }
566 sprintf(lbuf, "%d", v);
567 strcat(Buf, lbuf);
568 }
569
570 void
sr_mesg(FILE * fd,int v,int j)571 sr_mesg(FILE *fd, int v, int j)
572 { Buf[0] ='\0';
573 sr_buf(v, j);
574 fprintf(fd, Buf);
575 }
576
577 void
doq(Symbol * s,int n,RunList * r)578 doq(Symbol *s, int n, RunList *r)
579 { Queue *q;
580 int j, k;
581
582 if (!s->val) /* uninitialized queue */
583 return;
584 for (q = qtab; q; q = q->nxt)
585 if (q->qid == s->val[n])
586 { if (xspin > 0
587 && (verbose&4)
588 && q->setat < depth)
589 continue;
590 if (q->nslots == 0)
591 continue; /* rv q always empty */
592 #if 0
593 if (q->qlen == 0) /* new 7/10 -- dont show if queue is empty */
594 { continue;
595 }
596 #endif
597 printf("\t\tqueue %d (", q->qid);
598 if (r)
599 printf("%s(%d):", r->n->name, r->pid - Have_claim);
600 if (s->nel > 1 || s->isarray)
601 printf("%s[%d]): ", s->name, n);
602 else
603 printf("%s): ", s->name);
604 for (k = 0; k < q->qlen; k++)
605 { printf("[");
606 for (j = 0; j < q->nflds; j++)
607 { if (j > 0) printf(",");
608 sr_mesg(stdout, q->contents[k*q->nflds+j],
609 q->fld_width[j] == MTYPE);
610 }
611 printf("]");
612 }
613 printf("\n");
614 break;
615 }
616 }
617
618 void
nochan_manip(Lextok * p,Lextok * n,int d)619 nochan_manip(Lextok *p, Lextok *n, int d)
620 { int e = 1;
621
622 if (d == 0 && p->sym && p->sym->type == CHAN)
623 { setaccess(p->sym, ZS, 0, 'L');
624
625 if (n && n->ntyp == CONST)
626 fatal("invalid asgn to chan", (char *) 0);
627
628 if (n && n->sym && n->sym->type == CHAN)
629 { setaccess(n->sym, ZS, 0, 'V');
630 return;
631 }
632 }
633
634 /* ok on the rhs of an assignment: */
635 if (!n || n->ntyp == LEN || n->ntyp == RUN
636 || n->ntyp == FULL || n->ntyp == NFULL
637 || n->ntyp == EMPTY || n->ntyp == NEMPTY)
638 return;
639
640 if (n->sym && n->sym->type == CHAN)
641 { if (d == 1)
642 fatal("invalid use of chan name", (char *) 0);
643 else
644 setaccess(n->sym, ZS, 0, 'V');
645 }
646
647 if (n->ntyp == NAME
648 || n->ntyp == '.')
649 e = 0; /* array index or struct element */
650
651 nochan_manip(p, n->lft, e);
652 nochan_manip(p, n->rgt, 1);
653 }
654
655 typedef struct BaseName {
656 char *str;
657 int cnt;
658 struct BaseName *nxt;
659 } BaseName;
660 BaseName *bsn;
661
662 void
newbasename(char * s)663 newbasename(char *s)
664 { BaseName *b;
665
666 /* printf("+++++++++%s\n", s); */
667 for (b = bsn; b; b = b->nxt)
668 if (strcmp(b->str, s) == 0)
669 { b->cnt++;
670 return;
671 }
672 b = (BaseName *) emalloc(sizeof(BaseName));
673 b->str = emalloc(strlen(s)+1);
674 b->cnt = 1;
675 strcpy(b->str, s);
676 b->nxt = bsn;
677 bsn = b;
678 }
679
680 void
delbasename(char * s)681 delbasename(char *s)
682 { BaseName *b, *prv = (BaseName *) 0;
683
684 for (b = bsn; b; prv = b, b = b->nxt)
685 { if (strcmp(b->str, s) == 0)
686 { b->cnt--;
687 if (b->cnt == 0)
688 { if (prv)
689 { prv->nxt = b->nxt;
690 } else
691 { bsn = b->nxt;
692 } }
693 /* printf("---------%s\n", s); */
694 break;
695 } }
696 }
697
698 void
checkindex(char * s,char * t)699 checkindex(char *s, char *t)
700 { BaseName *b;
701
702 /* printf("xxx Check %s (%s)\n", s, t); */
703 for (b = bsn; b; b = b->nxt)
704 {
705 /* printf(" %s\n", b->str); */
706 if (strcmp(b->str, s) == 0)
707 { non_fatal("do not index an array with itself (%s)", t);
708 break;
709 } }
710 }
711
712 void
scan_tree(Lextok * t,char * mn,char * mx)713 scan_tree(Lextok *t, char *mn, char *mx)
714 { char sv[512];
715 char tmp[32];
716 int oln = lineno;
717
718 if (!t) return;
719
720 lineno = t->ln;
721
722 if (t->ntyp == NAME)
723 { strcat(mn, t->sym->name);
724 strcat(mx, t->sym->name);
725 if (t->lft) /* array index */
726 { strcat(mn, "[]");
727 newbasename(mn);
728 strcpy(sv, mn); /* save */
729 strcpy(mn, ""); /* clear */
730 strcat(mx, "[");
731 scan_tree(t->lft, mn, mx); /* index */
732 strcat(mx, "]");
733 checkindex(mn, mx); /* match against basenames */
734 strcpy(mn, sv); /* restore */
735 delbasename(mn);
736 }
737 if (t->rgt) /* structure element */
738 { scan_tree(t->rgt, mn, mx);
739 }
740 } else if (t->ntyp == CONST)
741 { strcat(mn, "1"); /* really: t->val */
742 sprintf(tmp, "%d", t->val);
743 strcat(mx, tmp);
744 } else if (t->ntyp == '.')
745 { strcat(mn, ".");
746 strcat(mx, ".");
747 scan_tree(t->lft, mn, mx);
748 } else
749 { strcat(mn, "??");
750 strcat(mx, "??");
751 }
752 lineno = oln;
753 }
754
755 void
no_nested_array_refs(Lextok * n)756 no_nested_array_refs(Lextok *n) /* a [ a[1] ] with a[1] = 1, causes trouble in pan.b */
757 { char mn[512];
758 char mx[512];
759
760 /* printf("==================================ZAP\n"); */
761 bsn = (BaseName *) 0; /* start new list */
762 strcpy(mn, "");
763 strcpy(mx, "");
764
765 scan_tree(n, mn, mx);
766 /* printf("==> %s\n", mn); */
767 }
768
769 void
no_internals(Lextok * n)770 no_internals(Lextok *n)
771 { char *sp;
772
773 if (!n->sym
774 || !n->sym->name)
775 return;
776
777 sp = n->sym->name;
778
779 if ((strlen(sp) == strlen("_nr_pr") && strcmp(sp, "_nr_pr") == 0)
780 || (strlen(sp) == strlen("_p") && strcmp(sp, "_p") == 0))
781 { fatal("attempt to assign value to system variable %s", sp);
782 }
783
784 no_nested_array_refs(n);
785 }
786