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