xref: /csrg-svn/usr.bin/pascal/src/rec.c (revision 3405)
1770Speter /* Copyright (c) 1979 Regents of the University of California */
2770Speter 
3*3405Speter static char sccsid[] = "@(#)rec.c 1.4 04/01/81";
4770Speter 
5770Speter #include "whoami.h"
6770Speter #include "0.h"
7770Speter #include "tree.h"
8770Speter #include "opcode.h"
9770Speter 
10770Speter /*
11770Speter  * Build a record namelist entry.
12770Speter  * Some of the processing here is somewhat involved.
13770Speter  * The basic structure we are building is as follows.
14770Speter  *
15770Speter  * Each record has a main RECORD entry, with an attached
16770Speter  * chain of fields as ->chain;  these include all the fields in all
17770Speter  * the variants of this record.
18770Speter  *
19770Speter  * Attached to NL_VARNT is a chain of VARNT structures
20770Speter  * describing each of the variants.  These are further linked
21770Speter  * through ->chain.  Each VARNT has, in ->range[0] the value of
22770Speter  * the associated constant, and each points at a RECORD describing
23770Speter  * the subrecord through NL_VTOREC.  These pointers are not unique,
24770Speter  * more than one VARNT may reference the same RECORD.
25770Speter  *
26770Speter  * The involved processing here is in computing the NL_OFFS entry
27770Speter  * by maxing over the variants.  This works as follows.
28770Speter  *
29770Speter  * Each RECORD has two size counters.  NL_OFFS is the maximum size
30770Speter  * so far of any variant of this record;  NL_FLDSZ gives the size
31770Speter  * of just the FIELDs to this point as a base for further variants.
32770Speter  *
33770Speter  * As we process each variant record, we start its size with the
34770Speter  * NL_FLDSZ we have so far.  After processing it, if its NL_OFFS
35770Speter  * is the largest so far, we update the NL_OFFS of this subrecord.
36770Speter  * This will eventually propagate back and update the NL_OFFS of the
37770Speter  * entire record.
38770Speter  */
39770Speter 
40770Speter /*
41770Speter  * P0 points to the outermost RECORD for name searches.
42770Speter  */
43770Speter struct	nl *P0;
44770Speter 
45770Speter tyrec(r, off)
46770Speter 	int *r, off;
47770Speter {
48770Speter 
49770Speter 	    return tyrec1(r, off, 1);
50770Speter }
51770Speter 
52770Speter /*
53770Speter  * Define a record namelist entry.
54770Speter  * R is the tree for the record to be built.
55770Speter  * Off is the offset for the first item in this (sub)record.
56770Speter  */
57770Speter struct nl *
58770Speter tyrec1(r, off, first)
59770Speter 	register int *r;
60770Speter 	int off;
61770Speter 	char first;
62770Speter {
63770Speter 	register struct nl *p, *P0was;
64770Speter 
65770Speter 	p = defnl(0, RECORD, 0, 0);
66770Speter 	P0was = P0;
67770Speter 	if (first)
68770Speter 		P0 = p;
69770Speter #ifndef PI0
70770Speter 	p->value[NL_FLDSZ] = p->value[NL_OFFS] = off;
71770Speter #endif
72770Speter 	if (r != NIL) {
73770Speter 		fields(p, r[2]);
74770Speter 		variants(p, r[3]);
75770Speter 	}
76770Speter 	    /*
77770Speter 	     *	round the lengths of records up to their alignments
78770Speter 	     */
793078Smckusic 	p->value[NL_OFFS] = roundup(p->value[NL_OFFS], (long)align(p));
80770Speter 	P0 = P0was;
81770Speter 	return (p);
82770Speter }
83770Speter 
84770Speter /*
85770Speter  * Define the fixed part fields for p.
86770Speter  */
87770Speter struct nl *
88770Speter fields(p, r)
89770Speter 	struct nl *p;
90770Speter 	int *r;
91770Speter {
92770Speter 	register int *fp, *tp, *ip;
93770Speter 	struct nl *jp;
94770Speter 
95770Speter 	for (fp = r; fp != NIL; fp = fp[2]) {
96770Speter 		tp = fp[1];
97770Speter 		if (tp == NIL)
98770Speter 			continue;
99770Speter 		jp = gtype(tp[3]);
100770Speter 		line = tp[1];
101770Speter 		for (ip = tp[2]; ip != NIL; ip = ip[2])
102770Speter 			deffld(p, ip[1], jp);
103770Speter 	}
104770Speter }
105770Speter 
106770Speter /*
107770Speter  * Define the variants for RECORD p.
108770Speter  */
109770Speter struct nl *
110770Speter variants(p, r)
111770Speter 	struct nl *p;
112770Speter 	register int *r;
113770Speter {
114770Speter 	register int *vc, *v;
115770Speter 	int *vr;
116770Speter 	struct nl *ct;
117770Speter 
118770Speter 	if (r == NIL)
119770Speter 		return;
120770Speter 	ct = gtype(r[3]);
121*3405Speter 	if ( ( ct != NIL ) && ( isnta( ct , "bcsi" ) ) ) {
122770Speter 	    error("Tag fields cannot be %ss" , nameof( ct ) );
123770Speter 	}
124770Speter 	line = r[1];
125770Speter 	/*
126770Speter 	 * Want it even if r[2] is NIL so
127770Speter 	 * we check its type in "new" and "dispose"
128770Speter 	 * calls -- link it to NL_TAG.
129770Speter 	 */
130770Speter 	p->ptr[NL_TAG] = deffld(p, r[2], ct);
131770Speter 	for (vc = r[4]; vc != NIL; vc = vc[2]) {
132770Speter 		v = vc[1];
133770Speter 		if (v == NIL)
134770Speter 			continue;
135770Speter 		vr = tyrec1(v[3], p->value[NL_FLDSZ], 0);
136770Speter #ifndef PI0
137770Speter 		if (vr->value[NL_OFFS] > p->value[NL_OFFS])
138770Speter 			p->value[NL_OFFS] = vr->value[NL_OFFS];
139770Speter #endif
140770Speter 		line = v[1];
141770Speter 		for (v = v[2]; v != NIL; v = v[2])
142770Speter 			defvnt(p, v[1], vr, ct);
143770Speter 	}
144770Speter }
145770Speter 
146770Speter /*
147770Speter  * Define a field in subrecord p of record P0
148770Speter  * with name s and type t.
149770Speter  */
150770Speter struct nl *
151770Speter deffld(p, s, t)
152770Speter 	struct nl *p;
153770Speter 	register char *s;
154770Speter 	register struct nl *t;
155770Speter {
156770Speter 	register struct nl *fp;
157770Speter 
158770Speter 	if (reclook(P0, s) != NIL) {
159770Speter #ifndef PI1
160770Speter 		error("%s is a duplicate field name in this record", s);
161770Speter #endif
162770Speter 		s = NIL;
163770Speter 	}
164770Speter #ifndef PI0
165770Speter 	    /*
166770Speter 	     * it used to be easy to keep track of offsets of fields
167770Speter 	     * and total sizes of records.
168770Speter 	     * but now, the offset of the field is aligned
169770Speter 	     * so only it knows it's offset, and calculating
170770Speter 	     * the total size of the record is based on it,
171770Speter 	     * rather than just the width of the field.
172770Speter 	     */
1733078Smckusic 	fp = enter(defnl(s, FIELD, t, (int)roundup(p->value[NL_OFFS],
1743078Smckusic 			(long)align(t))));
175770Speter #else
176770Speter 	fp = enter(defnl(s, FIELD, t, 0));
177770Speter #endif
178770Speter 	if (s != NIL) {
179770Speter 		fp->chain = P0->chain;
180770Speter 		P0->chain = fp;
181770Speter #ifndef PI0
182770Speter 		    /*
183770Speter 		     * and the size of the record is incremented.
184770Speter 		     */
185905Speter 		p -> value[ NL_OFFS ] = fp -> value[ NL_OFFS ] + width( t );
186770Speter 		p -> value[ NL_FLDSZ ] = p -> value[ NL_OFFS ];
187770Speter #endif
188770Speter 		if (t != NIL) {
189770Speter 			P0->nl_flags |= t->nl_flags & NFILES;
190770Speter 			p->nl_flags |= t->nl_flags & NFILES;
191770Speter 		}
192770Speter #		ifdef PC
193770Speter 		    stabfield( s , p2type( t ) , fp -> value[ NL_OFFS ]
194770Speter 				, lwidth( t ) );
195770Speter #		endif PC
196770Speter 	}
197770Speter 	return (fp);
198770Speter }
199770Speter 
200770Speter /*
201770Speter  * Define a variant from the constant tree of t
202770Speter  * in subrecord p of record P0 where the casetype
203770Speter  * is ct and the variant record to be associated is vr.
204770Speter  */
205770Speter struct nl *
206770Speter defvnt(p, t, vr, ct)
207770Speter 	struct nl *p, *vr;
208770Speter 	int *t;
209770Speter 	register struct nl *ct;
210770Speter {
211770Speter 	register struct nl *av;
212770Speter 
213770Speter 	gconst(t);
214770Speter 	if (ct != NIL && incompat(con.ctype, ct , t )) {
215770Speter #ifndef PI1
216770Speter 		cerror("Variant label type incompatible with selector type");
217770Speter #endif
218770Speter 		ct = NIL;
219770Speter 	}
220770Speter 	av = defnl(0, VARNT, ct, 0);
221770Speter #ifndef PI1
222770Speter 	if (ct != NIL)
223770Speter 		uniqv(p);
224770Speter #endif
225770Speter 	av->chain = p->ptr[NL_VARNT];
226770Speter 	p->ptr[NL_VARNT] = av;
227770Speter 	av->ptr[NL_VTOREC] = vr;
228770Speter 	av->range[0] = con.crval;
229770Speter 	return (av);
230770Speter }
231770Speter 
232770Speter #ifndef PI1
233770Speter /*
234770Speter  * Check that the constant label value
235770Speter  * is unique among the labels in this variant.
236770Speter  */
237770Speter uniqv(p)
238770Speter 	struct nl *p;
239770Speter {
240770Speter 	register struct nl *vt;
241770Speter 
242770Speter 	for (vt = p->ptr[NL_VARNT]; vt != NIL; vt = vt->chain)
243770Speter 		if (vt->range[0] == con.crval) {
244770Speter 			error("Duplicate variant case label in record");
245770Speter 			return;
246770Speter 		}
247770Speter }
248770Speter #endif
249770Speter 
250770Speter /*
251770Speter  * See if the field name s is defined
252770Speter  * in the record p, returning a pointer
253770Speter  * to it namelist entry if it is.
254770Speter  */
255770Speter struct nl *
256770Speter reclook(p, s)
257770Speter 	register struct nl *p;
258770Speter 	char *s;
259770Speter {
260770Speter 
261770Speter 	if (p == NIL || s == NIL)
262770Speter 		return (NIL);
263770Speter 	for (p = p->chain; p != NIL; p = p->chain)
264770Speter 		if (p->symbol == s)
265770Speter 			return (p);
266770Speter 	return (NIL);
267770Speter }
268