xref: /csrg-svn/usr.bin/pascal/src/rec.c (revision 770)
1*770Speter /* Copyright (c) 1979 Regents of the University of California */
2*770Speter 
3*770Speter static	char sccsid[] = "@(#)rec.c 1.1 08/27/80";
4*770Speter 
5*770Speter #include "whoami.h"
6*770Speter #include "0.h"
7*770Speter #include "tree.h"
8*770Speter #include "opcode.h"
9*770Speter 
10*770Speter /*
11*770Speter  * Build a record namelist entry.
12*770Speter  * Some of the processing here is somewhat involved.
13*770Speter  * The basic structure we are building is as follows.
14*770Speter  *
15*770Speter  * Each record has a main RECORD entry, with an attached
16*770Speter  * chain of fields as ->chain;  these include all the fields in all
17*770Speter  * the variants of this record.
18*770Speter  *
19*770Speter  * Attached to NL_VARNT is a chain of VARNT structures
20*770Speter  * describing each of the variants.  These are further linked
21*770Speter  * through ->chain.  Each VARNT has, in ->range[0] the value of
22*770Speter  * the associated constant, and each points at a RECORD describing
23*770Speter  * the subrecord through NL_VTOREC.  These pointers are not unique,
24*770Speter  * more than one VARNT may reference the same RECORD.
25*770Speter  *
26*770Speter  * The involved processing here is in computing the NL_OFFS entry
27*770Speter  * by maxing over the variants.  This works as follows.
28*770Speter  *
29*770Speter  * Each RECORD has two size counters.  NL_OFFS is the maximum size
30*770Speter  * so far of any variant of this record;  NL_FLDSZ gives the size
31*770Speter  * of just the FIELDs to this point as a base for further variants.
32*770Speter  *
33*770Speter  * As we process each variant record, we start its size with the
34*770Speter  * NL_FLDSZ we have so far.  After processing it, if its NL_OFFS
35*770Speter  * is the largest so far, we update the NL_OFFS of this subrecord.
36*770Speter  * This will eventually propagate back and update the NL_OFFS of the
37*770Speter  * entire record.
38*770Speter  */
39*770Speter 
40*770Speter /*
41*770Speter  * P0 points to the outermost RECORD for name searches.
42*770Speter  */
43*770Speter struct	nl *P0;
44*770Speter 
45*770Speter tyrec(r, off)
46*770Speter 	int *r, off;
47*770Speter {
48*770Speter 
49*770Speter 	    return tyrec1(r, off, 1);
50*770Speter }
51*770Speter 
52*770Speter /*
53*770Speter  * Define a record namelist entry.
54*770Speter  * R is the tree for the record to be built.
55*770Speter  * Off is the offset for the first item in this (sub)record.
56*770Speter  */
57*770Speter struct nl *
58*770Speter tyrec1(r, off, first)
59*770Speter 	register int *r;
60*770Speter 	int off;
61*770Speter 	char first;
62*770Speter {
63*770Speter 	register struct nl *p, *P0was;
64*770Speter 
65*770Speter 	p = defnl(0, RECORD, 0, 0);
66*770Speter 	P0was = P0;
67*770Speter 	if (first)
68*770Speter 		P0 = p;
69*770Speter #ifndef PI0
70*770Speter 	p->value[NL_FLDSZ] = p->value[NL_OFFS] = off;
71*770Speter #endif
72*770Speter 	if (r != NIL) {
73*770Speter 		fields(p, r[2]);
74*770Speter 		variants(p, r[3]);
75*770Speter 	}
76*770Speter 	    /*
77*770Speter 	     *	round the lengths of records up to their alignments
78*770Speter 	     */
79*770Speter 	p -> value[ NL_OFFS ] = roundup( p -> value[ NL_OFFS ] , align( p ) );
80*770Speter 	P0 = P0was;
81*770Speter 	return (p);
82*770Speter }
83*770Speter 
84*770Speter /*
85*770Speter  * Define the fixed part fields for p.
86*770Speter  */
87*770Speter struct nl *
88*770Speter fields(p, r)
89*770Speter 	struct nl *p;
90*770Speter 	int *r;
91*770Speter {
92*770Speter 	register int *fp, *tp, *ip;
93*770Speter 	struct nl *jp;
94*770Speter 
95*770Speter 	for (fp = r; fp != NIL; fp = fp[2]) {
96*770Speter 		tp = fp[1];
97*770Speter 		if (tp == NIL)
98*770Speter 			continue;
99*770Speter 		jp = gtype(tp[3]);
100*770Speter 		line = tp[1];
101*770Speter 		for (ip = tp[2]; ip != NIL; ip = ip[2])
102*770Speter 			deffld(p, ip[1], jp);
103*770Speter 	}
104*770Speter }
105*770Speter 
106*770Speter /*
107*770Speter  * Define the variants for RECORD p.
108*770Speter  */
109*770Speter struct nl *
110*770Speter variants(p, r)
111*770Speter 	struct nl *p;
112*770Speter 	register int *r;
113*770Speter {
114*770Speter 	register int *vc, *v;
115*770Speter 	int *vr;
116*770Speter 	struct nl *ct;
117*770Speter 
118*770Speter 	if (r == NIL)
119*770Speter 		return;
120*770Speter 	ct = gtype(r[3]);
121*770Speter 	if ( isnta( ct , "bcsi" ) ) {
122*770Speter 	    error("Tag fields cannot be %ss" , nameof( ct ) );
123*770Speter 	}
124*770Speter 	line = r[1];
125*770Speter 	/*
126*770Speter 	 * Want it even if r[2] is NIL so
127*770Speter 	 * we check its type in "new" and "dispose"
128*770Speter 	 * calls -- link it to NL_TAG.
129*770Speter 	 */
130*770Speter 	p->ptr[NL_TAG] = deffld(p, r[2], ct);
131*770Speter 	for (vc = r[4]; vc != NIL; vc = vc[2]) {
132*770Speter 		v = vc[1];
133*770Speter 		if (v == NIL)
134*770Speter 			continue;
135*770Speter 		vr = tyrec1(v[3], p->value[NL_FLDSZ], 0);
136*770Speter #ifndef PI0
137*770Speter 		if (vr->value[NL_OFFS] > p->value[NL_OFFS])
138*770Speter 			p->value[NL_OFFS] = vr->value[NL_OFFS];
139*770Speter #endif
140*770Speter 		line = v[1];
141*770Speter 		for (v = v[2]; v != NIL; v = v[2])
142*770Speter 			defvnt(p, v[1], vr, ct);
143*770Speter 	}
144*770Speter }
145*770Speter 
146*770Speter /*
147*770Speter  * Define a field in subrecord p of record P0
148*770Speter  * with name s and type t.
149*770Speter  */
150*770Speter struct nl *
151*770Speter deffld(p, s, t)
152*770Speter 	struct nl *p;
153*770Speter 	register char *s;
154*770Speter 	register struct nl *t;
155*770Speter {
156*770Speter 	register struct nl *fp;
157*770Speter 
158*770Speter 	if (reclook(P0, s) != NIL) {
159*770Speter #ifndef PI1
160*770Speter 		error("%s is a duplicate field name in this record", s);
161*770Speter #endif
162*770Speter 		s = NIL;
163*770Speter 	}
164*770Speter #ifndef PI0
165*770Speter 	    /*
166*770Speter 	     * it used to be easy to keep track of offsets of fields
167*770Speter 	     * and total sizes of records.
168*770Speter 	     * but now, the offset of the field is aligned
169*770Speter 	     * so only it knows it's offset, and calculating
170*770Speter 	     * the total size of the record is based on it,
171*770Speter 	     * rather than just the width of the field.
172*770Speter 	     */
173*770Speter 	fp = enter( defnl( s , FIELD , t , roundup( p -> value[ NL_OFFS ]
174*770Speter 						    , align( t ) ) ) );
175*770Speter #else
176*770Speter 	fp = enter(defnl(s, FIELD, t, 0));
177*770Speter #endif
178*770Speter 	if (s != NIL) {
179*770Speter 		fp->chain = P0->chain;
180*770Speter 		P0->chain = fp;
181*770Speter #ifndef PI0
182*770Speter 		    /*
183*770Speter 		     * and the size of the record is incremented.
184*770Speter 		     */
185*770Speter 		p -> value[ NL_OFFS ] = fp -> value[ NL_OFFS ]
186*770Speter 					    + even( width( t ) );
187*770Speter 		p -> value[ NL_FLDSZ ] = p -> value[ NL_OFFS ];
188*770Speter #endif
189*770Speter 		if (t != NIL) {
190*770Speter 			P0->nl_flags |= t->nl_flags & NFILES;
191*770Speter 			p->nl_flags |= t->nl_flags & NFILES;
192*770Speter 		}
193*770Speter #		ifdef PC
194*770Speter 		    stabfield( s , p2type( t ) , fp -> value[ NL_OFFS ]
195*770Speter 				, lwidth( t ) );
196*770Speter #		endif PC
197*770Speter 	}
198*770Speter 	return (fp);
199*770Speter }
200*770Speter 
201*770Speter /*
202*770Speter  * Define a variant from the constant tree of t
203*770Speter  * in subrecord p of record P0 where the casetype
204*770Speter  * is ct and the variant record to be associated is vr.
205*770Speter  */
206*770Speter struct nl *
207*770Speter defvnt(p, t, vr, ct)
208*770Speter 	struct nl *p, *vr;
209*770Speter 	int *t;
210*770Speter 	register struct nl *ct;
211*770Speter {
212*770Speter 	register struct nl *av;
213*770Speter 
214*770Speter 	gconst(t);
215*770Speter 	if (ct != NIL && incompat(con.ctype, ct , t )) {
216*770Speter #ifndef PI1
217*770Speter 		cerror("Variant label type incompatible with selector type");
218*770Speter #endif
219*770Speter 		ct = NIL;
220*770Speter 	}
221*770Speter 	av = defnl(0, VARNT, ct, 0);
222*770Speter #ifndef PI1
223*770Speter 	if (ct != NIL)
224*770Speter 		uniqv(p);
225*770Speter #endif
226*770Speter 	av->chain = p->ptr[NL_VARNT];
227*770Speter 	p->ptr[NL_VARNT] = av;
228*770Speter 	av->ptr[NL_VTOREC] = vr;
229*770Speter 	av->range[0] = con.crval;
230*770Speter 	return (av);
231*770Speter }
232*770Speter 
233*770Speter #ifndef PI1
234*770Speter /*
235*770Speter  * Check that the constant label value
236*770Speter  * is unique among the labels in this variant.
237*770Speter  */
238*770Speter uniqv(p)
239*770Speter 	struct nl *p;
240*770Speter {
241*770Speter 	register struct nl *vt;
242*770Speter 
243*770Speter 	for (vt = p->ptr[NL_VARNT]; vt != NIL; vt = vt->chain)
244*770Speter 		if (vt->range[0] == con.crval) {
245*770Speter 			error("Duplicate variant case label in record");
246*770Speter 			return;
247*770Speter 		}
248*770Speter }
249*770Speter #endif
250*770Speter 
251*770Speter /*
252*770Speter  * See if the field name s is defined
253*770Speter  * in the record p, returning a pointer
254*770Speter  * to it namelist entry if it is.
255*770Speter  */
256*770Speter struct nl *
257*770Speter reclook(p, s)
258*770Speter 	register struct nl *p;
259*770Speter 	char *s;
260*770Speter {
261*770Speter 
262*770Speter 	if (p == NIL || s == NIL)
263*770Speter 		return (NIL);
264*770Speter 	for (p = p->chain; p != NIL; p = p->chain)
265*770Speter 		if (p->symbol == s)
266*770Speter 			return (p);
267*770Speter 	return (NIL);
268*770Speter }
269