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