structs.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. /***** spin: structs.c *****/
  2. /* Copyright (c) 1991-2000 by Lucent Technologies - Bell Laboratories */
  3. /* All Rights Reserved. This software is for educational purposes only. */
  4. /* Permission is given to distribute this code provided that this intro- */
  5. /* ductory message is not removed and no monies are exchanged. */
  6. /* No guarantee is expressed or implied by the distribution of this code. */
  7. /* Software written by Gerard J. Holzmann as part of the book: */
  8. /* `Design and Validation of Computer Protocols,' ISBN 0-13-539925-4, */
  9. /* Prentice Hall, Englewood Cliffs, NJ, 07632. */
  10. /* Send bug-reports and/or questions to: gerard@research.bell-labs.com */
  11. #include "spin.h"
  12. #ifdef PC
  13. #include "y_tab.h"
  14. #else
  15. #include "y.tab.h"
  16. #endif
  17. typedef struct UType {
  18. Symbol *nm; /* name of the type */
  19. Lextok *cn; /* contents */
  20. struct UType *nxt; /* linked list */
  21. } UType;
  22. extern Symbol *context;
  23. extern RunList *X;
  24. extern Symbol *Fname;
  25. extern int lineno, depth, Expand_Ok;
  26. Symbol *owner;
  27. static UType *Unames = 0;
  28. static UType *Pnames = 0;
  29. static Lextok *cpnn(Lextok *, int, int, int);
  30. extern void sr_mesg(FILE *, int, int);
  31. void
  32. setuname(Lextok *n)
  33. { UType *tmp;
  34. for (tmp = Unames; tmp; tmp = tmp->nxt)
  35. if (!strcmp(owner->name, tmp->nm->name))
  36. { non_fatal("typename %s was defined before",
  37. tmp->nm->name);
  38. return;
  39. }
  40. if (!owner) fatal("illegal reference inside typedef",
  41. (char *) 0);
  42. tmp = (UType *) emalloc(sizeof(UType));
  43. tmp->nm = owner;
  44. tmp->cn = n;
  45. tmp->nxt = Unames;
  46. Unames = tmp;
  47. }
  48. static void
  49. putUname(FILE *fd, UType *tmp)
  50. { Lextok *fp, *tl;
  51. if (!tmp) return;
  52. putUname(fd, tmp->nxt); /* postorder */
  53. fprintf(fd, "struct %s { /* user defined type */\n",
  54. tmp->nm->name);
  55. for (fp = tmp->cn; fp; fp = fp->rgt)
  56. for (tl = fp->lft; tl; tl = tl->rgt)
  57. typ2c(tl->sym);
  58. fprintf(fd, "};\n");
  59. }
  60. void
  61. putunames(FILE *fd)
  62. {
  63. putUname(fd, Unames);
  64. }
  65. int
  66. isutype(char *t)
  67. { UType *tmp;
  68. for (tmp = Unames; tmp; tmp = tmp->nxt)
  69. { if (!strcmp(t, tmp->nm->name))
  70. return 1;
  71. }
  72. return 0;
  73. }
  74. Lextok *
  75. getuname(Symbol *t)
  76. { UType *tmp;
  77. for (tmp = Unames; tmp; tmp = tmp->nxt)
  78. { if (!strcmp(t->name, tmp->nm->name))
  79. return tmp->cn;
  80. }
  81. fatal("%s is not a typename", t->name);
  82. return (Lextok *)0;
  83. }
  84. void
  85. setutype(Lextok *p, Symbol *t, Lextok *vis) /* user-defined types */
  86. { int oln = lineno;
  87. Symbol *ofn = Fname;
  88. Lextok *m, *n;
  89. m = getuname(t);
  90. for (n = p; n; n = n->rgt)
  91. { lineno = n->ln;
  92. Fname = n->fn;
  93. if (n->sym->type)
  94. non_fatal("redeclaration of '%s'", n->sym->name);
  95. if (n->sym->nbits > 0)
  96. non_fatal("(%s) only an unsigned can have width-field",
  97. n->sym->name);
  98. if (Expand_Ok)
  99. n->sym->hidden |= (4|8|16); /* formal par */
  100. if (vis)
  101. { if (strncmp(vis->sym->name, ":hide:", 6) == 0)
  102. n->sym->hidden |= 1;
  103. else if (strncmp(vis->sym->name, ":show:", 6) == 0)
  104. n->sym->hidden |= 2;
  105. else if (strncmp(vis->sym->name, ":local:", 7) == 0)
  106. n->sym->hidden |= 64;
  107. }
  108. n->sym->type = STRUCT; /* classification */
  109. n->sym->Slst = m; /* structure itself */
  110. n->sym->Snm = t; /* name of typedef */
  111. n->sym->Nid = 0; /* this is no chan */
  112. n->sym->hidden |= 4;
  113. if (n->sym->nel <= 0)
  114. non_fatal("bad array size for '%s'", n->sym->name);
  115. }
  116. lineno = oln;
  117. Fname = ofn;
  118. }
  119. static Symbol *
  120. do_same(Lextok *n, Symbol *v, int xinit)
  121. { Lextok *tmp, *fp, *tl;
  122. int ix = eval(n->lft);
  123. int oln = lineno;
  124. Symbol *ofn = Fname;
  125. lineno = n->ln;
  126. Fname = n->fn;
  127. /* n->sym->type == STRUCT
  128. * index: n->lft
  129. * subfields: n->rgt
  130. * structure template: n->sym->Slst
  131. * runtime values: n->sym->Sval
  132. */
  133. if (xinit) ini_struct(v); /* once, at top level */
  134. if (ix >= v->nel || ix < 0)
  135. { printf("spin: indexing %s[%d] - size is %d\n",
  136. v->name, ix, v->nel);
  137. fatal("indexing error \'%s\'", v->name);
  138. }
  139. if (!n->rgt || !n->rgt->lft)
  140. { non_fatal("no subfields %s", v->name); /* i.e., wants all */
  141. lineno = oln; Fname = ofn;
  142. return ZS;
  143. }
  144. if (n->rgt->ntyp != '.')
  145. { printf("bad subfield type %d\n", n->rgt->ntyp);
  146. alldone(1);
  147. }
  148. tmp = n->rgt->lft;
  149. if (tmp->ntyp != NAME && tmp->ntyp != TYPE)
  150. { printf("bad subfield entry %d\n", tmp->ntyp);
  151. alldone(1);
  152. }
  153. for (fp = v->Sval[ix]; fp; fp = fp->rgt)
  154. for (tl = fp->lft; tl; tl = tl->rgt)
  155. if (!strcmp(tl->sym->name, tmp->sym->name))
  156. { lineno = oln; Fname = ofn;
  157. return tl->sym;
  158. }
  159. fatal("cannot locate subfield %s", tmp->sym->name);
  160. return ZS;
  161. }
  162. int
  163. Rval_struct(Lextok *n, Symbol *v, int xinit) /* n varref, v valref */
  164. { Symbol *tl;
  165. Lextok *tmp;
  166. int ix;
  167. if (!n || !(tl = do_same(n, v, xinit)))
  168. return 0;
  169. tmp = n->rgt->lft;
  170. if (tmp->sym->type == STRUCT)
  171. { return Rval_struct(tmp, tl, 0);
  172. } else if (tmp->rgt)
  173. fatal("non-zero 'rgt' on non-structure", 0);
  174. ix = eval(tmp->lft);
  175. if (ix >= tl->nel || ix < 0)
  176. fatal("indexing error \'%s\'", tl->name);
  177. return cast_val(tl->type, tl->val[ix], tl->nbits);
  178. }
  179. int
  180. Lval_struct(Lextok *n, Symbol *v, int xinit, int a) /* a = assigned value */
  181. { Symbol *tl;
  182. Lextok *tmp;
  183. int ix;
  184. if (!(tl = do_same(n, v, xinit)))
  185. return 1;
  186. tmp = n->rgt->lft;
  187. if (tmp->sym->type == STRUCT)
  188. return Lval_struct(tmp, tl, 0, a);
  189. else if (tmp->rgt)
  190. fatal("non-zero 'rgt' on non-structure", 0);
  191. ix = eval(tmp->lft);
  192. if (ix >= tl->nel || ix < 0)
  193. fatal("indexing error \'%s\'", tl->name);
  194. if (tl->nbits > 0)
  195. a = (a & ((1<<tl->nbits)-1));
  196. tl->val[ix] = a;
  197. tl->setat = depth;
  198. return 1;
  199. }
  200. int
  201. Cnt_flds(Lextok *m)
  202. { Lextok *fp, *tl, *n;
  203. int cnt = 0;
  204. if (m->ntyp == ',')
  205. { n = m;
  206. goto is_lst;
  207. }
  208. if (!m->sym || m->ntyp != STRUCT)
  209. return 1;
  210. n = getuname(m->sym);
  211. is_lst:
  212. for (fp = n; fp; fp = fp->rgt)
  213. for (tl = fp->lft; tl; tl = tl->rgt)
  214. { if (tl->sym->type == STRUCT)
  215. { if (tl->sym->nel != 1)
  216. fatal("hidden array in parameter, %s",
  217. tl->sym->name);
  218. cnt += Cnt_flds(tl->sym->Slst);
  219. } else
  220. cnt += tl->sym->nel;
  221. }
  222. return cnt;
  223. }
  224. int
  225. Sym_typ(Lextok *t)
  226. { Symbol *s = t->sym;
  227. if (!s) return 0;
  228. if (s->type != STRUCT)
  229. return s->type;
  230. if (!t->rgt
  231. || !t->rgt->ntyp == '.'
  232. || !t->rgt->lft)
  233. fatal("unexpected struct layout %s", s->name);
  234. return Sym_typ(t->rgt->lft);
  235. }
  236. int
  237. Width_set(int *wdth, int i, Lextok *n)
  238. { Lextok *fp, *tl;
  239. int j = i, k;
  240. for (fp = n; fp; fp = fp->rgt)
  241. for (tl = fp->lft; tl; tl = tl->rgt)
  242. { if (tl->sym->type == STRUCT)
  243. j = Width_set(wdth, j, tl->sym->Slst);
  244. else
  245. { for (k = 0; k < tl->sym->nel; k++, j++)
  246. wdth[j] = tl->sym->type;
  247. } }
  248. return j;
  249. }
  250. void
  251. ini_struct(Symbol *s)
  252. { int i; Lextok *fp, *tl;
  253. if (s->type != STRUCT) /* last step */
  254. { (void) checkvar(s, 0);
  255. return;
  256. }
  257. if (s->Sval == (Lextok **) 0)
  258. { s->Sval = (Lextok **) emalloc(s->nel * sizeof(Lextok *));
  259. for (i = 0; i < s->nel; i++)
  260. { s->Sval[i] = cpnn(s->Slst, 1, 1, 1);
  261. for (fp = s->Sval[i]; fp; fp = fp->rgt)
  262. for (tl = fp->lft; tl; tl = tl->rgt)
  263. ini_struct(tl->sym);
  264. } }
  265. }
  266. static Lextok *
  267. cpnn(Lextok *s, int L, int R, int S)
  268. { Lextok *d; extern int Nid;
  269. if (!s) return ZN;
  270. d = (Lextok *) emalloc(sizeof(Lextok));
  271. d->ntyp = s->ntyp;
  272. d->val = s->val;
  273. d->ln = s->ln;
  274. d->fn = s->fn;
  275. d->sym = s->sym;
  276. if (L) d->lft = cpnn(s->lft, 1, 1, S);
  277. if (R) d->rgt = cpnn(s->rgt, 1, 1, S);
  278. if (S && s->sym)
  279. { d->sym = (Symbol *) emalloc(sizeof(Symbol));
  280. memcpy(d->sym, s->sym, sizeof(Symbol));
  281. if (d->sym->type == CHAN)
  282. d->sym->Nid = ++Nid;
  283. }
  284. if (s->sq || s->sl)
  285. fatal("cannot happen cpnn", (char *) 0);
  286. return d;
  287. }
  288. int
  289. full_name(FILE *fd, Lextok *n, Symbol *v, int xinit)
  290. { Symbol *tl;
  291. Lextok *tmp;
  292. int hiddenarrays = 0;
  293. fprintf(fd, "%s", v->name);
  294. if (!n || !(tl = do_same(n, v, xinit)))
  295. return 0;
  296. tmp = n->rgt->lft;
  297. if (tmp->sym->type == STRUCT)
  298. { fprintf(fd, ".");
  299. hiddenarrays = full_name(fd, tmp, tl, 0);
  300. goto out;
  301. }
  302. fprintf(fd, ".%s", tl->name);
  303. out: if (tmp->sym->nel > 1)
  304. { fprintf(fd, "[%d]", eval(tmp->lft));
  305. hiddenarrays = 1;
  306. }
  307. return hiddenarrays;
  308. }
  309. void
  310. validref(Lextok *p, Lextok *c)
  311. { Lextok *fp, *tl;
  312. char lbuf[512];
  313. for (fp = p->sym->Slst; fp; fp = fp->rgt)
  314. for (tl = fp->lft; tl; tl = tl->rgt)
  315. if (strcmp(tl->sym->name, c->sym->name) == 0)
  316. return;
  317. sprintf(lbuf, "no field '%s' defined in structure '%s'\n",
  318. c->sym->name, p->sym->name);
  319. non_fatal(lbuf, (char *) 0);
  320. }
  321. void
  322. struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
  323. { Symbol *tl;
  324. Lextok *tmp;
  325. char lbuf[128];
  326. if (!n || !(tl = do_same(n, v, xinit)))
  327. return;
  328. tmp = n->rgt->lft;
  329. if (tmp->sym->type == STRUCT)
  330. { strcat(buf, ".");
  331. struct_name(tmp, tl, 0, buf);
  332. return;
  333. }
  334. sprintf(lbuf, ".%s", tl->name);
  335. strcat(buf, lbuf);
  336. if (tmp->sym->nel > 1)
  337. { sprintf(lbuf, "[%d]", eval(tmp->lft));
  338. strcat(buf, lbuf);
  339. }
  340. }
  341. void
  342. walk2_struct(char *s, Symbol *z)
  343. { Lextok *fp, *tl;
  344. char eprefix[128];
  345. int ix;
  346. extern void Done_case(char *, Symbol *);
  347. ini_struct(z);
  348. if (z->nel == 1)
  349. sprintf(eprefix, "%s%s.", s, z->name);
  350. for (ix = 0; ix < z->nel; ix++)
  351. { if (z->nel > 1)
  352. sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
  353. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  354. for (tl = fp->lft; tl; tl = tl->rgt)
  355. { if (tl->sym->type == STRUCT)
  356. walk2_struct(eprefix, tl->sym);
  357. else if (tl->sym->type == CHAN)
  358. Done_case(eprefix, tl->sym);
  359. } }
  360. }
  361. void
  362. walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a, char *b, char *c)
  363. { Lextok *fp, *tl;
  364. char eprefix[128];
  365. int ix;
  366. ini_struct(z);
  367. if (z->nel == 1)
  368. sprintf(eprefix, "%s%s.", s, z->name);
  369. for (ix = 0; ix < z->nel; ix++)
  370. { if (z->nel > 1)
  371. sprintf(eprefix, "%s%s[%d].", s, z->name, ix);
  372. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  373. for (tl = fp->lft; tl; tl = tl->rgt)
  374. { if (tl->sym->type == STRUCT)
  375. walk_struct(ofd, dowhat, eprefix, tl->sym, a,b,c);
  376. else
  377. do_var(ofd, dowhat, eprefix, tl->sym, a,b,c);
  378. } }
  379. }
  380. void
  381. dump_struct(Symbol *z, char *prefix, RunList *r)
  382. { Lextok *fp, *tl;
  383. char eprefix[128];
  384. int ix, jx;
  385. ini_struct(z);
  386. for (ix = 0; ix < z->nel; ix++)
  387. { if (z->nel > 1)
  388. sprintf(eprefix, "%s[%d]", prefix, ix);
  389. else
  390. strcpy(eprefix, prefix);
  391. for (fp = z->Sval[ix]; fp; fp = fp->rgt)
  392. for (tl = fp->lft; tl; tl = tl->rgt)
  393. { if (tl->sym->type == STRUCT)
  394. { char pref[128];
  395. strcpy(pref, eprefix);
  396. strcat(pref, ".");
  397. strcat(pref, tl->sym->name);
  398. dump_struct(tl->sym, pref, r);
  399. } else
  400. for (jx = 0; jx < tl->sym->nel; jx++)
  401. { if (tl->sym->type == CHAN)
  402. doq(tl->sym, jx, r);
  403. else
  404. { printf("\t\t");
  405. if (r)
  406. printf("%s(%d):", r->n->name, r->pid);
  407. printf("%s.%s", eprefix, tl->sym->name);
  408. if (tl->sym->nel > 1)
  409. printf("[%d]", jx);
  410. printf(" = ");
  411. sr_mesg(stdout, tl->sym->val[jx],
  412. tl->sym->type == MTYPE);
  413. printf("\n");
  414. } } }
  415. }
  416. }
  417. static int
  418. retrieve(Lextok **targ, int i, int want, Lextok *n, int Ntyp)
  419. { Lextok *fp, *tl;
  420. int j = i, k;
  421. for (fp = n; fp; fp = fp->rgt)
  422. for (tl = fp->lft; tl; tl = tl->rgt)
  423. { if (tl->sym->type == STRUCT)
  424. { j = retrieve(targ, j, want, tl->sym->Slst, Ntyp);
  425. if (j < 0)
  426. { Lextok *x = cpnn(tl, 1, 0, 0);
  427. x->rgt = nn(ZN, '.', (*targ), ZN);
  428. (*targ) = x;
  429. return -1;
  430. }
  431. } else
  432. { for (k = 0; k < tl->sym->nel; k++, j++)
  433. { if (j == want)
  434. { *targ = cpnn(tl, 1, 0, 0);
  435. (*targ)->lft = nn(ZN, CONST, ZN, ZN);
  436. (*targ)->lft->val = k;
  437. if (Ntyp)
  438. (*targ)->ntyp = (short) Ntyp;
  439. return -1;
  440. }
  441. } } }
  442. return j;
  443. }
  444. static int
  445. is_explicit(Lextok *n)
  446. {
  447. if (!n) return 0;
  448. if (!n->sym) fatal("unexpected - no symbol", 0);
  449. if (n->sym->type != STRUCT) return 1;
  450. if (!n->rgt) return 0;
  451. if (n->rgt->ntyp != '.')
  452. { lineno = n->ln;
  453. Fname = n->fn;
  454. printf("ntyp %d\n", n->rgt->ntyp);
  455. fatal("unexpected %s, no '.'", n->sym->name);
  456. }
  457. return is_explicit(n->rgt->lft);
  458. }
  459. Lextok *
  460. expand(Lextok *n, int Ok)
  461. /* turn rgt-lnked list of struct nms, into ',' list of flds */
  462. { Lextok *x = ZN, *y;
  463. if (!Ok) return n;
  464. while (n)
  465. { y = mk_explicit(n, 1, 0);
  466. if (x)
  467. (void) tail_add(x, y);
  468. else
  469. x = y;
  470. n = n->rgt;
  471. }
  472. return x;
  473. }
  474. Lextok *
  475. mk_explicit(Lextok *n, int Ok, int Ntyp)
  476. /* produce a single ',' list of fields */
  477. { Lextok *bld = ZN, *x;
  478. int i, cnt; extern int IArgs;
  479. if (n->sym->type != STRUCT
  480. || is_explicit(n))
  481. return n;
  482. if (!Ok || !n->sym->Slst)
  483. { if (IArgs) return n;
  484. printf("spin: saw '");
  485. comment(stdout, n, 0);
  486. printf("'\n");
  487. fatal("incomplete structure ref '%s'", n->sym->name);
  488. }
  489. cnt = Cnt_flds(n->sym->Slst);
  490. for (i = cnt-1; i >= 0; i--)
  491. { bld = nn(ZN, ',', ZN, bld);
  492. if (retrieve(&(bld->lft), 0, i, n->sym->Slst, Ntyp) >= 0)
  493. { printf("cannot retrieve field %d\n", i);
  494. fatal("bad structure %s", n->sym->name);
  495. }
  496. x = cpnn(n, 1, 0, 0);
  497. x->rgt = nn(ZN, '.', bld->lft, ZN);
  498. bld->lft = x;
  499. }
  500. return bld;
  501. }
  502. Lextok *
  503. tail_add(Lextok *a, Lextok *b)
  504. { Lextok *t;
  505. for (t = a; t->rgt; t = t->rgt)
  506. if (t->ntyp != ',')
  507. fatal("unexpected type - tail_add", 0);
  508. t->rgt = b;
  509. return a;
  510. }
  511. void
  512. setpname(Lextok *n)
  513. { UType *tmp;
  514. for (tmp = Pnames; tmp; tmp = tmp->nxt)
  515. if (!strcmp(n->sym->name, tmp->nm->name))
  516. { non_fatal("proctype %s redefined",
  517. n->sym->name);
  518. return;
  519. }
  520. tmp = (UType *) emalloc(sizeof(UType));
  521. tmp->nm = n->sym;
  522. tmp->nxt = Pnames;
  523. Pnames = tmp;
  524. }
  525. int
  526. isproctype(char *t)
  527. { UType *tmp;
  528. for (tmp = Pnames; tmp; tmp = tmp->nxt)
  529. { if (!strcmp(t, tmp->nm->name))
  530. return 1;
  531. }
  532. return 0;
  533. }