|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2:
3: static char sccsid[] = "@(#)pclval.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: /*
12: * and the rest of the file
13: */
14: # include "pc.h"
15: # include "pcops.h"
16:
17: extern int flagwas;
18: /*
19: * pclvalue computes the address
20: * of a qualified name and
21: * leaves it on the stack.
22: * for pc, it can be asked for either an lvalue or an rvalue.
23: * the semantics are the same, only the code is different.
24: * for putting out calls to check for nil and fnil,
25: * we have to traverse the list of qualifications twice:
26: * once to put out the calls and once to put out the address to be checked.
27: */
28: struct nl *
29: pclvalue( r , modflag , required )
30: int *r;
31: int modflag;
32: int required;
33: {
34: register struct nl *p;
35: register *c, *co;
36: int f, o;
37: int tr[2], trp[3];
38: struct nl *firstp;
39: struct nl *lastp;
40: char *firstsymbol;
41: int firstbn;
42:
43: if ( r == NIL ) {
44: return NIL;
45: }
46: if ( nowexp( r ) ) {
47: return NIL;
48: }
49: if ( r[0] != T_VAR ) {
50: error("Variable required"); /* Pass mesgs down from pt of call ? */
51: return NIL;
52: }
53: firstp = p = lookup( r[2] );
54: if ( p == NIL ) {
55: return NIL;
56: }
57: firstsymbol = p -> symbol;
58: firstbn = bn;
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: if ( p -> class == WITHPTR ) {
72: /*
73: * Construct the tree implied by
74: * the with statement
75: */
76: trp[0] = T_LISTPP;
77: trp[1] = tr;
78: trp[2] = r[3];
79: tr[0] = T_FIELD;
80: tr[1] = r[2];
81: c = trp;
82: }
83: /*
84: * this not only puts out the names of functions to call
85: * but also does all the semantic checking of the qualifications.
86: */
87: if ( ! nilfnil( p , c , modflag , firstp , r[2] ) ) {
88: return NIL;
89: }
90: switch (p -> class) {
91: case WITHPTR:
92: case REF:
93: /*
94: * Obtain the indirect word
95: * of the WITHPTR or REF
96: * as the base of our lvalue
97: */
98: putRV( firstsymbol , firstbn , p -> value[ 0 ]
99: , p2type( p ) );
100: firstsymbol = 0;
101: f = 0; /* have an lv on stack */
102: o = 0;
103: break;
104: case VAR:
105: f = 1; /* no lv on stack yet */
106: o = p -> value[0];
107: break;
108: default:
109: error("%s %s found where variable required", classes[p -> class], p -> symbol);
110: return (NIL);
111: }
112: /*
113: * Loop and handle each
114: * qualification on the name
115: */
116: if ( c == NIL && ( modflag & ASGN ) && p -> value[ NL_FORV ] ) {
117: error("Can't modify the for variable %s in the range of the loop", p -> symbol);
118: return (NIL);
119: }
120: for ( ; c != NIL ; c = c[2] ) {
121: co = c[1];
122: if ( co == NIL ) {
123: return NIL;
124: }
125: lastp = p;
126: p = p -> type;
127: if ( p == NIL ) {
128: return NIL;
129: }
130: switch ( co[0] ) {
131: case T_PTR:
132: /*
133: * Pointer qualification.
134: */
135: if ( f ) {
136: putLV( firstsymbol , firstbn , o
137: , p2type( p ) );
138: firstsymbol = 0;
139: } else {
140: if (o) {
141: putleaf( P2ICON , o , 0 , P2INT
142: , 0 );
143: putop( P2PLUS , P2PTR | P2CHAR );
144: }
145: }
146: /*
147: * Pointer cannot be
148: * nil and file cannot
149: * be at end-of-file.
150: * the appropriate function name is
151: * already out there from nilfnil.
152: */
153: if ( p -> class == PTR ) {
154: /*
155: * this is the indirection from
156: * the address of the pointer
157: * to the pointer itself.
158: * kirk sez:
159: * fnil doesn't want this.
160: * and does it itself for files
161: * since only it knows where the
162: * actual window is.
163: * but i have to do this for
164: * regular pointers.
165: */
166: putop( P2UNARY P2MUL , p2type( p ) );
167: if ( opt( 't' ) ) {
168: putop( P2CALL , P2INT );
169: }
170: } else {
171: putop( P2CALL , P2INT );
172: }
173: f = o = 0;
174: continue;
175: case T_ARGL:
176: case T_ARY:
177: if ( f ) {
178: putLV( firstsymbol , firstbn , o
179: , p2type( p ) );
180: firstsymbol = 0;
181: } else {
182: if (o) {
183: putleaf( P2ICON , o , 0 , P2INT
184: , 0 );
185: putop( P2PLUS , P2INT );
186: }
187: }
188: arycod( p , co[1] );
189: f = o = 0;
190: continue;
191: case T_FIELD:
192: /*
193: * Field names are just
194: * an offset with some
195: * semantic checking.
196: */
197: p = reclook(p, co[1]);
198: o += p -> value[0];
199: continue;
200: default:
201: panic("lval2");
202: }
203: }
204: if (f) {
205: putLV( firstsymbol , firstbn , o , p2type( p -> type ) );
206: } else {
207: if (o) {
208: putleaf( P2ICON , o , 0 , P2INT , 0 );
209: putop( P2PLUS , P2INT );
210: }
211: }
212: if ( required == RREQ ) {
213: putop( P2UNARY P2MUL , p2type( p -> type ) );
214: }
215: return ( p -> type );
216: }
217:
218: /*
219: * this recursively follows done a list of qualifications
220: * and puts out the beginnings of calls to fnil for files
221: * or nil for pointers (if checking is on) on the way back.
222: * this returns true or false.
223: */
224: nilfnil( p , c , modflag , firstp , r2 )
225: struct nl *p;
226: int *c;
227: int modflag;
228: struct nl *firstp;
229: char *r2; /* no, not r2-d2 */
230: {
231: int *co;
232: struct nl *lastp;
233: int t;
234:
235: if ( c == NIL ) {
236: return TRUE;
237: }
238: co = (int *) ( c[1] );
239: if ( co == NIL ) {
240: return FALSE;
241: }
242: lastp = p;
243: p = p -> type;
244: if ( p == NIL ) {
245: return FALSE;
246: }
247: switch ( co[0] ) {
248: case T_PTR:
249: /*
250: * Pointer qualification.
251: */
252: lastp -> nl_flags |= NUSED;
253: if ( p -> class != PTR && p -> class != FILET) {
254: error("^ allowed only on files and pointers, not on %ss", nameof(p));
255: goto bad;
256: }
257: break;
258: case T_ARGL:
259: if ( p -> class != ARRAY ) {
260: if ( lastp == firstp ) {
261: error("%s is a %s, not a function", r2, classes[firstp -> class]);
262: } else {
263: error("Illegal function qualificiation");
264: }
265: return FALSE;
266: }
267: recovered();
268: error("Pascal uses [] for subscripting, not ()");
269: /* and fall through */
270: case T_ARY:
271: if ( p -> class != ARRAY ) {
272: error("Subscripting allowed only on arrays, not on %ss", nameof(p));
273: goto bad;
274: }
275: codeoff();
276: t = arycod( p , co[1] );
277: codeon();
278: switch ( t ) {
279: case 0:
280: return FALSE;
281: case -1:
282: goto bad;
283: }
284: break;
285: case T_FIELD:
286: /*
287: * Field names are just
288: * an offset with some
289: * semantic checking.
290: */
291: if ( p -> class != RECORD ) {
292: error(". allowed only on records, not on %ss", nameof(p));
293: goto bad;
294: }
295: if ( co[1] == NIL ) {
296: return FALSE;
297: }
298: p = reclook( p , co[1] );
299: if ( p == NIL ) {
300: error("%s is not a field in this record", co[1]);
301: goto bad;
302: }
303: if ( modflag & MOD ) {
304: p -> nl_flags |= NMOD;
305: }
306: if ( ( modflag & NOUSE ) == 0 || lptr( c[2] ) ) {
307: p -> nl_flags |= NUSED;
308: }
309: break;
310: default:
311: panic("nilfnil");
312: }
313: /*
314: * recursive call, check the rest of the qualifications.
315: */
316: if ( ! nilfnil( p , c[2] , modflag , firstp , r2 ) ) {
317: return FALSE;
318: }
319: /*
320: * the point of all this.
321: */
322: if ( co[0] == T_PTR ) {
323: if ( p -> class == PTR ) {
324: if ( opt( 't' ) ) {
325: putleaf( P2ICON , 0 , 0
326: , ADDTYPE( P2FTN | P2INT , P2PTR )
327: , "_NIL" );
328: }
329: } else {
330: putleaf( P2ICON , 0 , 0
331: , ADDTYPE( P2FTN | P2INT , P2PTR )
332: , "_FNIL" );
333: }
334: }
335: return TRUE;
336: bad:
337: cerror("Error occurred on qualification of %s", r2);
338: return FALSE;
339: }
340: #endif PC
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.