|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)lval.c 1.1 8/27/80";
4:
5: #include "whoami.h"
6: #include "0.h"
7: #include "tree.h"
8: #include "opcode.h"
9: #include "objfmt.h"
10: #ifdef PC
11: # include "pc.h"
12: # include "pcops.h"
13: #endif PC
14:
15: extern int flagwas;
16: /*
17: * Lvalue computes the address
18: * of a qualified name and
19: * leaves it on the stack.
20: * for pc, it can be asked for either an lvalue or an rvalue.
21: * the semantics are the same, only the code is different.
22: */
23: struct nl *
24: lvalue(r, modflag , required )
25: int *r, modflag;
26: int required;
27: {
28: register struct nl *p;
29: struct nl *firstp, *lastp;
30: register *c, *co;
31: int f, o;
32: /*
33: * Note that the local optimizations
34: * done here for offsets would more
35: * appropriately be done in put.
36: */
37: int tr[2], trp[3];
38:
39: if (r == NIL) {
40: return (NIL);
41: }
42: if (nowexp(r)) {
43: return (NIL);
44: }
45: if (r[0] != T_VAR) {
46: error("Variable required"); /* Pass mesgs down from pt of call ? */
47: return (NIL);
48: }
49: # ifdef PC
50: /*
51: * pc requires a whole different control flow
52: */
53: return pclvalue( r , modflag , required );
54: # endif PC
55: firstp = p = lookup(r[2]);
56: if (p == NIL) {
57: return (NIL);
58: }
59: c = r[3];
60: if ((modflag & NOUSE) && !lptr(c)) {
61: p->nl_flags = flagwas;
62: }
63: if (modflag & MOD) {
64: p->nl_flags |= NMOD;
65: }
66: /*
67: * Only possibilities for p->class here
68: * are the named classes, i.e. CONST, TYPE
69: * VAR, PROC, FUNC, REF, or a WITHPTR.
70: */
71: switch (p->class) {
72: case WITHPTR:
73: /*
74: * Construct the tree implied by
75: * the with statement
76: */
77: trp[0] = T_LISTPP;
78: trp[1] = tr;
79: trp[2] = r[3];
80: tr[0] = T_FIELD;
81: tr[1] = r[2];
82: c = trp;
83: # ifdef PTREE
84: /*
85: * mung r[4] to say which field this T_VAR is
86: * for VarCopy
87: */
88: r[4] = reclook( p -> type , r[2] );
89: # endif
90: /* and fall through */
91: case REF:
92: /*
93: * Obtain the indirect word
94: * of the WITHPTR or REF
95: * as the base of our lvalue
96: */
97: put(2, PTR_RV | bn << 8+INDX , p->value[0] );
98: f = 0; /* have an lv on stack */
99: o = 0;
100: break;
101: case VAR:
102: f = 1; /* no lv on stack yet */
103: o = p->value[0];
104: break;
105: default:
106: error("%s %s found where variable required", classes[p->class], p->symbol);
107: return (NIL);
108: }
109: /*
110: * Loop and handle each
111: * qualification on the name
112: */
113: if (c == NIL && (modflag&ASGN) && p->value[NL_FORV]) {
114: error("Can't modify the for variable %s in the range of the loop", p->symbol);
115: return (NIL);
116: }
117: for (; c != NIL; c = c[2]) {
118: co = c[1];
119: if (co == NIL) {
120: return (NIL);
121: }
122: lastp = p;
123: p = p->type;
124: if (p == NIL) {
125: return (NIL);
126: }
127: switch (co[0]) {
128: case T_PTR:
129: /*
130: * Pointer qualification.
131: */
132: lastp->nl_flags |= NUSED;
133: if (p->class != PTR && p->class != FILET) {
134: error("^ allowed only on files and pointers, not on %ss", nameof(p));
135: goto bad;
136: }
137: if (f) {
138: put(2, PTR_RV | bn <<8+INDX , o );
139: } else {
140: if (o) {
141: put2(O_OFF, o);
142: }
143: put(1, PTR_IND);
144: }
145: /*
146: * Pointer cannot be
147: * nil and file cannot
148: * be at end-of-file.
149: */
150: put1(p->class == FILET ? O_FNIL : O_NIL);
151: f = o = 0;
152: continue;
153: case T_ARGL:
154: if (p->class != ARRAY) {
155: if (lastp == firstp) {
156: error("%s is a %s, not a function", r[2], classes[firstp->class]);
157: } else {
158: error("Illegal function qualificiation");
159: }
160: return (NIL);
161: }
162: recovered();
163: error("Pascal uses [] for subscripting, not ()");
164: case T_ARY:
165: if (p->class != ARRAY) {
166: error("Subscripting allowed only on arrays, not on %ss", nameof(p));
167: goto bad;
168: }
169: if (f) {
170: put2(O_LV | bn<<8+INDX, o);
171: } else {
172: if (o) {
173: put2(O_OFF, o);
174: }
175: }
176: switch (arycod(p, co[1])) {
177: case 0:
178: return (NIL);
179: case -1:
180: goto bad;
181: }
182: f = o = 0;
183: continue;
184: case T_FIELD:
185: /*
186: * Field names are just
187: * an offset with some
188: * semantic checking.
189: */
190: if (p->class != RECORD) {
191: error(". allowed only on records, not on %ss", nameof(p));
192: goto bad;
193: }
194: if (co[1] == NIL) {
195: return (NIL);
196: }
197: p = reclook(p, co[1]);
198: if (p == NIL) {
199: error("%s is not a field in this record", co[1]);
200: goto bad;
201: }
202: # ifdef PTREE
203: /*
204: * mung co[3] to indicate which field
205: * this is for SelCopy
206: */
207: co[3] = p;
208: # endif
209: if (modflag & MOD) {
210: p->nl_flags |= NMOD;
211: }
212: if ((modflag & NOUSE) == 0 || lptr(c[2])) {
213: p->nl_flags |= NUSED;
214: }
215: o += p->value[0];
216: continue;
217: default:
218: panic("lval2");
219: }
220: }
221: if (f) {
222: put2(O_LV | bn<<8+INDX, o);
223: } else {
224: if (o) {
225: put2(O_OFF, o);
226: }
227: }
228: return (p->type);
229: bad:
230: cerror("Error occurred on qualification of %s", r[2]);
231: return (NIL);
232: }
233:
234: lptr(c)
235: register int *c;
236: {
237: register int *co;
238:
239: for (; c != NIL; c = c[2]) {
240: co = c[1];
241: if (co == NIL) {
242: return (NIL);
243: }
244: switch (co[0]) {
245:
246: case T_PTR:
247: return (1);
248: case T_ARGL:
249: return (0);
250: case T_ARY:
251: case T_FIELD:
252: continue;
253: default:
254: panic("lptr");
255: }
256: }
257: return (0);
258: }
259:
260: /*
261: * Arycod does the
262: * code generation
263: * for subscripting.
264: */
265: arycod(np, el)
266: struct nl *np;
267: int *el;
268: {
269: register struct nl *p, *ap;
270: int i, d, v, v1;
271: int w;
272:
273: p = np;
274: if (el == NIL) {
275: return (0);
276: }
277: d = p->value[0];
278: /*
279: * Check each subscript
280: */
281: for (i = 1; i <= d; i++) {
282: if (el == NIL) {
283: error("Too few subscripts (%d given, %d required)", i-1, d);
284: return (-1);
285: }
286: p = p->chain;
287: # ifdef PC
288: precheck( p , "_SUBSC" , "_SUBSCZ" );
289: # endif PC
290: ap = rvalue(el[1], NLNIL , RREQ );
291: if (ap == NIL) {
292: return (0);
293: }
294: # ifdef PC
295: postcheck( p );
296: # endif PC
297: if (incompat(ap, p->type, el[1])) {
298: cerror("Array index type incompatible with declared index type");
299: if (d != 1) {
300: cerror("Error occurred on index number %d", i);
301: }
302: return (-1);
303: }
304: w = aryconst(np, i);
305: # ifdef OBJ
306: if (opt('t') == 0) {
307: switch (w) {
308: case 8:
309: w = 6;
310: case 4:
311: case 2:
312: case 1:
313: put2((width(ap) != 4 ? O_INX2P2 : O_INX4P2) | (w & ~1) << 7, ( short ) p->range[0]);
314: el = el[2];
315: continue;
316: }
317: }
318: put(4, width(ap) != 4 ? O_INX2 : O_INX4,w,( short ) p->range[0],
319: ( short ) ( p->range[1] - p->range[0] ) );
320: # endif OBJ
321: # ifdef PC
322: /*
323: * subtract off the lower bound
324: */
325: if ( p -> range[ 0 ] != 0 ) {
326: putleaf( P2ICON , p -> range[0] , 0 , P2INT , 0 );
327: putop( P2MINUS , P2INT );
328: }
329: /*
330: * multiply by the width of the elements
331: */
332: if ( w != 1 ) {
333: putleaf( P2ICON , w , 0 , P2INT , 0 );
334: putop( P2MUL , P2INT );
335: }
336: /*
337: * and add it to the base address
338: */
339: putop( P2PLUS , ADDTYPE( p2type( np -> type ) , P2PTR ) );
340: # endif PC
341: el = el[2];
342: }
343: if (el != NIL) {
344: do {
345: el = el[2];
346: i++;
347: } while (el != NIL);
348: error("Too many subscripts (%d given, %d required)", i-1, d);
349: return (-1);
350: }
351: return (1);
352: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.