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