1 /***** spin: structs.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 "spin.h"
10 #include "y.tab.h"
11
12 typedef struct UType {
13 Symbol *nm; /* name of the type */
14 Lextok *cn; /* contents */
15 struct UType *nxt; /* linked list */
16 } UType;
17
18 extern Symbol *Fname;
19 extern int lineno, depth, Expand_Ok, has_hidden, in_for;
20
21 Symbol *owner;
22
23 static UType *Unames = 0;
24 static UType *Pnames = 0;
25
26 static Lextok *cpnn(Lextok *, int, int, int);
27 extern void sr_mesg(FILE *, int, int, const char *);
28 extern void Done_case(char *, Symbol *);
29
30 void
setuname(Lextok * n)31 setuname(Lextok *n)
32 { UType *tmp;
33
34 if (!owner)
35 fatal("illegal reference inside typedef", (char *) 0);
36
37 for (tmp = Unames; tmp; tmp = tmp->nxt)
38 if (!strcmp(owner->name, tmp->nm->name))
39 { non_fatal("typename %s was defined before",
40 tmp->nm->name);
41 return;
42 }
43
44 tmp = (UType *) emalloc(sizeof(UType));
45 tmp->nm = owner;
46 tmp->cn = n;
47 tmp->nxt = Unames;
48 Unames = tmp;
49 }
50
51 static void
putUname(FILE * fd,UType * tmp)52 putUname(FILE *fd, UType *tmp)
53 { Lextok *fp, *tl;
54
55 if (!tmp) return;
56 putUname(fd, tmp->nxt); /* postorder */
57 fprintf(fd, "struct %s { /* user defined type */\n",
58 tmp->nm->name);
59 for (fp = tmp->cn; fp; fp = fp->rgt)
60 for (tl = fp->lft; tl; tl = tl->rgt)
61 typ2c(tl->sym);
62 fprintf(fd, "};\n");
63 }
64
65 void
putunames(FILE * fd)66 putunames(FILE *fd)
67 {
68 putUname(fd, Unames);
69 }
70
71 int
isutype(char * t)72 isutype(char *t)
73 { UType *tmp;
74
75 for (tmp = Unames; tmp; tmp = tmp->nxt)
76 { if (!strcmp(t, tmp->nm->name))
77 return 1;
78 }
79 return 0;
80 }
81
82 Lextok *
getuname(Symbol * t)83 getuname(Symbol *t)
84 { UType *tmp;
85
86 for (tmp = Unames; tmp; tmp = tmp->nxt)
87 { if (!strcmp(t->name, tmp->nm->name))
88 return tmp->cn;
89 }
90 fatal("%s is not a typename", t->name);
91 return (Lextok *)0;
92 }
93
94 void
setutype(Lextok * p,Symbol * t,Lextok * vis)95 setutype(Lextok *p, Symbol *t, Lextok *vis) /* user-defined types */
96 { int oln = lineno;
97 Symbol *ofn = Fname;
98 Lextok *m, *n;
99
100 m = getuname(t);
101 for (n = p; n; n = n->rgt)
102 { lineno = n->ln;
103 Fname = n->fn;
104 if (n->sym->type)
105 { fatal("redeclaration of '%s'", n->sym->name);
106 }
107
108 if (n->sym->nbits > 0)
109 non_fatal("(%s) only an unsigned can have width-field",
110 n->sym->name);
111
112 if (Expand_Ok)
113 n->sym->hidden |= (4|8|16); /* formal par */
114
115 if (vis)
116 { if (strncmp(vis->sym->name, ":hide:", (size_t) 6) == 0)
117 { n->sym->hidden |= 1;
118 has_hidden++;
119 } else if (strncmp(vis->sym->name, ":show:", (size_t) 6) == 0)
120 n->sym->hidden |= 2;
121 else if (strncmp(vis->sym->name, ":local:", (size_t) 7) == 0)
122 n->sym->hidden |= 64;
123 }
124 n->sym->type = STRUCT; /* classification */
125 n->sym->Slst = m; /* structure itself */
126 n->sym->Snm = t; /* name of typedef */
127 n->sym->Nid = 0; /* this is no chan */
128 n->sym->hidden |= 4;
129 if (n->sym->nel <= 0)
130 non_fatal("bad array size for '%s'", n->sym->name);
131 }
132 lineno = oln;
133 Fname = ofn;
134 }
135
136 static Symbol *
do_same(Lextok * n,Symbol * v,int xinit)137 do_same(Lextok *n, Symbol *v, int xinit)
138 { Lextok *tmp, *fp, *tl;
139 int ix = eval(n->lft);
140 int oln = lineno;
141 Symbol *ofn = Fname;
142
143 lineno = n->ln;
144 Fname = n->fn;
145
146 /* n->sym->type == STRUCT
147 * index: n->lft
148 * subfields: n->rgt
149 * structure template: n->sym->Slst
150 * runtime values: n->sym->Sval
151 */
152 if (xinit) ini_struct(v); /* once, at top level */
153
154 if (ix >= v->nel || ix < 0)
155 { printf("spin: indexing %s[%d] - size is %d\n",
156 v->name, ix, v->nel);
157 fatal("indexing error \'%s\'", v->name);
158 }
159 if (!n->rgt || !n->rgt->lft)
160 { non_fatal("no subfields %s", v->name); /* i.e., wants all */
161 lineno = oln; Fname = ofn;
162 return ZS;
163 }
164
165 if (n->rgt->ntyp != '.')
166 { printf("bad subfield type %d\n", n->rgt->ntyp);
167 alldone(1);
168 }
169
170 tmp = n->rgt->lft;
171 if (tmp->ntyp != NAME && tmp->ntyp != TYPE)
172 { printf("bad subfield entry %d\n", tmp->ntyp);
173 alldone(1);
174 }
175 for (fp = v->Sval[ix]; fp; fp = fp->rgt)
176 for (tl = fp->lft; tl; tl = tl->rgt)
177 if (!strcmp(tl->sym->name, tmp->sym->name))
178 { lineno = oln; Fname = ofn;
179 return tl->sym;
180 }
181 fatal("cannot locate subfield %s", tmp->sym->name);
182 return ZS;
183 }
184
185 int
Rval_struct(Lextok * n,Symbol * v,int xinit)186 Rval_struct(Lextok *n, Symbol *v, int xinit) /* n varref, v valref */
187 { Symbol *tl;
188 Lextok *tmp;
189 int ix;
190
191 if (!n || !(tl = do_same(n, v, xinit)))
192 return 0;
193
194 tmp = n->rgt->lft;
195 if (tmp->sym->type == STRUCT)
196 { return Rval_struct(tmp, tl, 0);
197 } else if (tmp->rgt)
198 fatal("non-zero 'rgt' on non-structure", 0);
199
200 ix = eval(tmp->lft);
201 /* printf("%d: ix: %d (%d) %d\n", depth, ix, tl->nel, tl->val[ix]); */
202 if (ix >= tl->nel || ix < 0)
203 fatal("indexing error \'%s\'", tl->name);
204
205 return cast_val(tl->type, tl->val[ix], tl->nbits);
206 }
207
208 int
Lval_struct(Lextok * n,Symbol * v,int xinit,int a)209 Lval_struct(Lextok *n, Symbol *v, int xinit, int a) /* a = assigned value */
210 { Symbol *tl;
211 Lextok *tmp;
212 int ix;
213
214 if (!(tl = do_same(n, v, xinit)))
215 return 1;
216
217 tmp = n->rgt->lft;
218 if (tmp->sym->type == STRUCT)
219 return Lval_struct(tmp, tl, 0, a);
220 else if (tmp->rgt)
221 fatal("non-zero 'rgt' on non-structure", 0);
222
223 ix = eval(tmp->lft);
224 if (ix >= tl->nel || ix < 0)
225 fatal("indexing error \'%s\'", tl->name);
226
227 if (tl->nbits > 0)
228 a = (a & ((1<<tl->nbits)-1));
229
230 if (a != tl->val[ix])
231 { tl->val[ix] = a;
232 tl->setat = depth;
233 }
234 return 1;
235 }
236
237 int
Cnt_flds(Lextok * m)238 Cnt_flds(Lextok *m)
239 { Lextok *fp, *tl, *n;
240 int cnt = 0;
241
242 if (!m)
243 { return 0;
244 }
245
246 if (m->ntyp == ',')
247 { n = m;
248 goto is_lst;
249 }
250 if (!m->sym
251 || m->ntyp != STRUCT)
252 { return 1;
253 }
254
255 n = getuname(m->sym);
256 is_lst:
257 for (fp = n; fp; fp = fp->rgt)
258 for (tl = fp->lft; tl; tl = tl->rgt)
259 { if (tl->sym->type == STRUCT)
260 { if (tl->sym->nel > 1 || tl->sym->isarray)
261 fatal("array of structures in param list, %s",
262 tl->sym->name);
263 cnt += Cnt_flds(tl->sym->Slst);
264 } else
265 cnt += tl->sym->nel;
266 }
267 return cnt;
268 }
269
270 int
Sym_typ(Lextok * t)271 Sym_typ(Lextok *t)
272 { Symbol *s = t->sym;
273
274 if (!s) return 0;
275
276 if (s->type != STRUCT)
277 return s->type;
278
279 if (!t->rgt
280 || t->rgt->ntyp != '.' /* gh: had ! in wrong place */
281 || !t->rgt->lft)
282 return STRUCT; /* not a field reference */
283
284 return Sym_typ(t->rgt->lft);
285 }
286
287 int
Width_set(int * wdth,int i,Lextok * n)288 Width_set(int *wdth, int i, Lextok *n)
289 { Lextok *fp, *tl;
290 int j = i, k;
291
292 for (fp = n; fp; fp = fp->rgt)
293 for (tl = fp->lft; tl; tl = tl->rgt)
294 { if (tl->sym->type == STRUCT)
295 j = Width_set(wdth, j, tl->sym->Slst);
296 else
297 { for (k = 0; k < tl->sym->nel; k++, j++)
298 wdth[j] = tl->sym->type;
299 } }
300 return j;
301 }
302
303 void
ini_struct(Symbol * s)304 ini_struct(Symbol *s)
305 { int i; Lextok *fp, *tl;
306
307 if (s->type != STRUCT) /* last step */
308 { (void) checkvar(s, 0);
309 return;
310 }
311 if (s->Sval == (Lextok **) 0)
312 { s->Sval = (Lextok **) emalloc(s->nel * sizeof(Lextok *));
313 for (i = 0; i < s->nel; i++)
314 { s->Sval[i] = cpnn(s->Slst, 1, 1, 1);
315
316 for (fp = s->Sval[i]; fp; fp = fp->rgt)
317 for (tl = fp->lft; tl; tl = tl->rgt)
318 ini_struct(tl->sym);
319 } }
320 }
321
322 static Lextok *
cpnn(Lextok * s,int L,int R,int S)323 cpnn(Lextok *s, int L, int R, int S)
324 { Lextok *d; extern int Nid_nr;
325
326 if (!s) return ZN;
327
328 d = (Lextok *) emalloc(sizeof(Lextok));
329 d->uiid = s->uiid;
330 d->ntyp = s->ntyp;
331 d->val = s->val;
332 d->ln = s->ln;
333 d->fn = s->fn;
334 d->sym = s->sym;
335 if (L) d->lft = cpnn(s->lft, 1, 1, S);
336 if (R) d->rgt = cpnn(s->rgt, 1, 1, S);
337
338 if (S && s->sym)
339 { d->sym = (Symbol *) emalloc(sizeof(Symbol));
340 memcpy(d->sym, s->sym, sizeof(Symbol));
341 if (d->sym->type == CHAN)
342 d->sym->Nid = ++Nid_nr;
343 }
344 if (s->sq || s->sl)
345 fatal("cannot happen cpnn", (char *) 0);
346
347 return d;
348 }
349
350 int
full_name(FILE * fd,Lextok * n,Symbol * v,int xinit)351 full_name(FILE *fd, Lextok *n, Symbol *v, int xinit)
352 { Symbol *tl;
353 Lextok *tmp;
354 int hiddenarrays = 0;
355
356 fprintf(fd, "%s", v->name);
357
358 if (!n || !(tl = do_same(n, v, xinit)))
359 return 0;
360 tmp = n->rgt->lft;
361
362 if (tmp->sym->type == STRUCT)
363 { fprintf(fd, ".");
364 hiddenarrays = full_name(fd, tmp, tl, 0);
365 goto out;
366 }
367 fprintf(fd, ".%s", tl->name);
368 out: if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
369 { fprintf(fd, "[%d]", eval(tmp->lft));
370 hiddenarrays = 1;
371 }
372 return hiddenarrays;
373 }
374
375 void
validref(Lextok * p,Lextok * c)376 validref(Lextok *p, Lextok *c)
377 { Lextok *fp, *tl;
378 char lbuf[512];
379
380 for (fp = p->sym->Slst; fp; fp = fp->rgt)
381 for (tl = fp->lft; tl; tl = tl->rgt)
382 if (strcmp(tl->sym->name, c->sym->name) == 0)
383 return;
384
385 sprintf(lbuf, "no field '%s' defined in structure '%s'\n",
386 c->sym->name, p->sym->name);
387 non_fatal(lbuf, (char *) 0);
388 }
389
390 void
struct_name(Lextok * n,Symbol * v,int xinit,char * buf)391 struct_name(Lextok *n, Symbol *v, int xinit, char *buf)
392 { Symbol *tl;
393 Lextok *tmp;
394 char lbuf[512];
395
396 if (!n || !(tl = do_same(n, v, xinit)))
397 return;
398 tmp = n->rgt->lft;
399 if (tmp->sym->type == STRUCT)
400 { strcat(buf, ".");
401 struct_name(tmp, tl, 0, buf);
402 return;
403 }
404 sprintf(lbuf, ".%s", tl->name);
405 strcat(buf, lbuf);
406 if (tmp->sym->nel > 1 || tmp->sym->isarray == 1)
407 { sprintf(lbuf, "[%d]", eval(tmp->lft));
408 strcat(buf, lbuf);
409 }
410 }
411
412 void
walk2_struct(char * s,Symbol * z)413 walk2_struct(char *s, Symbol *z)
414 { Lextok *fp, *tl;
415 char eprefix[128];
416 int ix;
417
418 memset(eprefix, 0, sizeof(eprefix));
419 ini_struct(z);
420 if (z->nel == 1 && z->isarray == 0)
421 snprintf(eprefix, sizeof(eprefix)-1, "%s%s.", s, z->name);
422 for (ix = 0; ix < z->nel; ix++)
423 { if (z->nel > 1 || z->isarray == 1)
424 snprintf(eprefix, sizeof(eprefix)-1, "%s%s[%d].", s, z->name, ix);
425 for (fp = z->Sval[ix]; fp; fp = fp->rgt)
426 for (tl = fp->lft; tl; tl = tl->rgt)
427 { if (tl->sym->type == STRUCT)
428 walk2_struct(eprefix, tl->sym);
429 else if (tl->sym->type == CHAN)
430 Done_case(eprefix, tl->sym);
431 } }
432 }
433
434 void
walk_struct(FILE * ofd,int dowhat,char * s,Symbol * z,char * a,char * b,char * c)435 walk_struct(FILE *ofd, int dowhat, char *s, Symbol *z, char *a, char *b, char *c)
436 { Lextok *fp, *tl;
437 char eprefix[128];
438 int ix;
439
440 memset(eprefix, 0, sizeof(eprefix));
441 ini_struct(z);
442 if (z->nel == 1 && z->isarray == 0)
443 snprintf(eprefix, sizeof(eprefix)-1, "%s%s.", s, z->name);
444 for (ix = 0; ix < z->nel; ix++)
445 { if (z->nel > 1 || z->isarray == 1)
446 snprintf(eprefix, sizeof(eprefix)-1, "%s%s[%d].", s, z->name, ix);
447 for (fp = z->Sval[ix]; fp; fp = fp->rgt)
448 for (tl = fp->lft; tl; tl = tl->rgt)
449 { if (tl->sym->type == STRUCT)
450 walk_struct(ofd, dowhat, eprefix, tl->sym, a,b,c);
451 else
452 do_var(ofd, dowhat, eprefix, tl->sym, a,b,c);
453 } }
454 }
455
456 void
c_struct(FILE * fd,char * ipref,Symbol * z)457 c_struct(FILE *fd, char *ipref, Symbol *z)
458 { Lextok *fp, *tl;
459 char pref[256], eprefix[300];
460 int ix;
461
462 ini_struct(z);
463
464 for (ix = 0; ix < z->nel; ix++)
465 for (fp = z->Sval[ix]; fp; fp = fp->rgt)
466 for (tl = fp->lft; tl; tl = tl->rgt)
467 { strcpy(eprefix, ipref);
468 if (z->nel > 1 || z->isarray == 1)
469 { /* insert index before last '.' */
470 eprefix[strlen(eprefix)-1] = '\0';
471 sprintf(pref, "[ %d ].", ix);
472 strcat(eprefix, pref);
473 }
474 if (tl->sym->type == STRUCT)
475 { strcat(eprefix, tl->sym->name);
476 strcat(eprefix, ".");
477 c_struct(fd, eprefix, tl->sym);
478 } else
479 c_var(fd, eprefix, tl->sym);
480 }
481 }
482
483 void
dump_struct(Symbol * z,char * prefix,RunList * r)484 dump_struct(Symbol *z, char *prefix, RunList *r)
485 { Lextok *fp, *tl;
486 char eprefix[256];
487 int ix, jx;
488
489 ini_struct(z);
490
491 for (ix = 0; ix < z->nel; ix++)
492 { if (z->nel > 1 || z->isarray == 1)
493 sprintf(eprefix, "%s[%d]", prefix, ix);
494 else
495 strcpy(eprefix, prefix);
496
497 for (fp = z->Sval[ix]; fp; fp = fp->rgt)
498 for (tl = fp->lft; tl; tl = tl->rgt)
499 { if (tl->sym->type == STRUCT)
500 { char pref[300];
501 strcpy(pref, eprefix);
502 strcat(pref, ".");
503 strcat(pref, tl->sym->name);
504 dump_struct(tl->sym, pref, r);
505 } else
506 for (jx = 0; jx < tl->sym->nel; jx++)
507 { if (tl->sym->type == CHAN)
508 doq(tl->sym, jx, r);
509 else
510 { char *s = 0;
511 printf("\t\t");
512 if (r)
513 printf("%s(%d):", r->n->name, r->pid);
514 printf("%s.%s", eprefix, tl->sym->name);
515 if (tl->sym->nel > 1 || tl->sym->isarray == 1)
516 printf("[%d]", jx);
517 printf(" = ");
518
519 if (tl->sym->type == MTYPE
520 && tl->sym->mtype_name)
521 { s = tl->sym->mtype_name->name;
522 }
523
524 sr_mesg(stdout, tl->sym->val[jx],
525 tl->sym->type == MTYPE, s);
526 printf("\n");
527 } } }
528 }
529 }
530
531 static int
retrieve(Lextok ** targ,int i,int want,Lextok * n,int Ntyp)532 retrieve(Lextok **targ, int i, int want, Lextok *n, int Ntyp)
533 { Lextok *fp, *tl;
534 int j = i, k;
535
536 for (fp = n; fp; fp = fp->rgt)
537 for (tl = fp->lft; tl; tl = tl->rgt)
538 { if (tl->sym->type == STRUCT)
539 { j = retrieve(targ, j, want, tl->sym->Slst, Ntyp);
540 if (j < 0)
541 { Lextok *x = cpnn(tl, 1, 0, 0);
542 x->rgt = nn(ZN, '.', (*targ), ZN);
543 (*targ) = x;
544 return -1;
545 }
546 } else
547 { for (k = 0; k < tl->sym->nel; k++, j++)
548 { if (j == want)
549 { *targ = cpnn(tl, 1, 0, 0);
550 (*targ)->lft = nn(ZN, CONST, ZN, ZN);
551 (*targ)->lft->val = k;
552 if (Ntyp)
553 (*targ)->ntyp = (short) Ntyp;
554 return -1;
555 }
556 } } }
557 return j;
558 }
559
560 static int
is_explicit(Lextok * n)561 is_explicit(Lextok *n)
562 {
563 if (!n) return 0;
564 if (!n->sym) fatal("unexpected - no symbol", 0);
565 if (n->sym->type != STRUCT) return 1;
566 if (!n->rgt) return 0;
567 if (n->rgt->ntyp != '.')
568 { lineno = n->ln;
569 Fname = n->fn;
570 printf("ntyp %d\n", n->rgt->ntyp);
571 fatal("unexpected %s, no '.'", n->sym->name);
572 }
573 return is_explicit(n->rgt->lft);
574 }
575
576 Lextok *
expand(Lextok * n,int Ok)577 expand(Lextok *n, int Ok)
578 /* turn rgt-lnked list of struct nms, into ',' list of flds */
579 { Lextok *x = ZN, *y;
580
581 if (!Ok) return n;
582
583 while (n)
584 { y = mk_explicit(n, 1, 0);
585 if (x)
586 (void) tail_add(x, y);
587 else
588 x = y;
589
590 n = n->rgt;
591 }
592 return x;
593 }
594
595 Lextok *
mk_explicit(Lextok * n,int Ok,int Ntyp)596 mk_explicit(Lextok *n, int Ok, int Ntyp)
597 /* produce a single ',' list of fields */
598 { Lextok *bld = ZN, *x;
599 int i, cnt; extern int IArgs;
600
601 if (n->sym->type != STRUCT
602 || in_for
603 || is_explicit(n))
604 return n;
605
606
607 if (n->rgt
608 && n->rgt->ntyp == '.'
609 && n->rgt->lft
610 && n->rgt->lft->sym
611 && n->rgt->lft->sym->type == STRUCT)
612 { Lextok *y;
613 bld = mk_explicit(n->rgt->lft, Ok, Ntyp);
614 for (x = bld; x; x = x->rgt)
615 { y = cpnn(n, 1, 0, 0);
616 y->rgt = nn(ZN, '.', x->lft, ZN);
617 x->lft = y;
618 }
619
620 return bld;
621 }
622
623 if (!Ok || !n->sym->Slst)
624 { if (IArgs) return n;
625 printf("spin: saw '");
626 comment(stdout, n, 0);
627 printf("'\n");
628 fatal("incomplete structure ref '%s'", n->sym->name);
629 }
630
631 cnt = Cnt_flds(n->sym->Slst);
632 for (i = cnt-1; i >= 0; i--)
633 { bld = nn(ZN, ',', ZN, bld);
634 if (retrieve(&(bld->lft), 0, i, n->sym->Slst, Ntyp) >= 0)
635 { printf("cannot retrieve field %d\n", i);
636 fatal("bad structure %s", n->sym->name);
637 }
638 x = cpnn(n, 1, 0, 0);
639 x->rgt = nn(ZN, '.', bld->lft, ZN);
640 bld->lft = x;
641 }
642 return bld;
643 }
644
645 Lextok *
tail_add(Lextok * a,Lextok * b)646 tail_add(Lextok *a, Lextok *b)
647 { Lextok *t;
648
649 for (t = a; t->rgt; t = t->rgt)
650 if (t->ntyp != ',')
651 fatal("unexpected type - tail_add", 0);
652 t->rgt = b;
653 return a;
654 }
655
656 void
setpname(Lextok * n)657 setpname(Lextok *n)
658 { UType *tmp;
659
660 for (tmp = Pnames; tmp; tmp = tmp->nxt)
661 if (!strcmp(n->sym->name, tmp->nm->name))
662 { non_fatal("proctype %s redefined",
663 n->sym->name);
664 return;
665 }
666 tmp = (UType *) emalloc(sizeof(UType));
667 tmp->nm = n->sym;
668 tmp->nxt = Pnames;
669 Pnames = tmp;
670 }
671
672 int
isproctype(char * t)673 isproctype(char *t)
674 { UType *tmp;
675
676 for (tmp = Pnames; tmp; tmp = tmp->nxt)
677 { if (!strcmp(t, tmp->nm->name))
678 return 1;
679 }
680 return 0;
681 }
682