mesg.c 17 KB

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