mesg.c 16 KB

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