|
|
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.