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