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