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