xref: /csrg-svn/usr.bin/pascal/src/call.c (revision 1195)
1745Speter /* Copyright (c) 1979 Regents of the University of California */
2745Speter 
3*1195Speter static	char sccsid[] = "@(#)call.c 1.3 10/03/80";
4745Speter 
5745Speter #include "whoami.h"
6745Speter #include "0.h"
7745Speter #include "tree.h"
8745Speter #include "opcode.h"
9745Speter #include "objfmt.h"
10745Speter #ifdef PC
11745Speter #   include "pc.h"
12745Speter #   include "pcops.h"
13745Speter #endif PC
14745Speter 
15*1195Speter bool	slenflag = 0;
16*1195Speter bool	floatflag = 0;
17*1195Speter 
18745Speter /*
19745Speter  * Call generates code for calls to
20745Speter  * user defined procedures and functions
21745Speter  * and is called by proc and funccod.
22745Speter  * P is the result of the lookup
23745Speter  * of the procedure/function symbol,
24745Speter  * and porf is PROC or FUNC.
25745Speter  * Psbn is the block number of p.
26745Speter  */
27745Speter struct nl *
28745Speter call(p, argv, porf, psbn)
29745Speter 	struct nl *p;
30745Speter 	int *argv, porf, psbn;
31745Speter {
32745Speter 	register struct nl *p1, *q;
33745Speter 	int *r;
34745Speter 
35*1195Speter #	ifdef OBJ
36*1195Speter 	    int		cnt;
37*1195Speter #	endif OBJ
38745Speter #	ifdef PC
39745Speter 	    long	temp;
40745Speter 	    int		firsttime;
41745Speter 	    int		rettype;
42745Speter #	endif PC
43745Speter 
44745Speter #	ifdef OBJ
45*1195Speter 	    if (p->class == FFUNC || p->class == FPROC)
46*1195Speter 		put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]);
47745Speter 	    if (porf == FUNC)
48745Speter 		    /*
49745Speter 		     * Push some space
50745Speter 		     * for the function return type
51745Speter 		     */
52745Speter 		    put2(O_PUSH, even(-width(p->type)));
53745Speter #	endif OBJ
54745Speter #	ifdef PC
55745Speter 	    if ( porf == FUNC ) {
56745Speter 		switch( classify( p -> type ) ) {
57745Speter 		    case TSTR:
58745Speter 		    case TSET:
59745Speter 		    case TREC:
60745Speter 		    case TFILE:
61745Speter 		    case TARY:
62745Speter 			temp = sizes[ cbn ].om_off -= width( p -> type );
63745Speter 			putlbracket( ftnno , -sizes[cbn].om_off );
64745Speter 			if (sizes[cbn].om_off < sizes[cbn].om_max) {
65745Speter 				sizes[cbn].om_max = sizes[cbn].om_off;
66745Speter 			}
67745Speter 			putRV( 0 , cbn , temp , P2STRTY );
68745Speter 		}
69745Speter 	    }
70*1195Speter 	    switch ( p -> class ) {
71*1195Speter 		case FUNC:
72*1195Speter 		case PROC:
73*1195Speter 		    {
74*1195Speter 			char	extname[ BUFSIZ ];
75*1195Speter 			char	*starthere;
76*1195Speter 			int	funcbn;
77*1195Speter 			int	i;
78745Speter 
79*1195Speter 			starthere = &extname[0];
80*1195Speter 			funcbn = p -> nl_block & 037;
81*1195Speter 			for ( i = 1 ; i < funcbn ; i++ ) {
82*1195Speter 			    sprintf( starthere , EXTFORMAT , enclosing[ i ] );
83*1195Speter 			    starthere += strlen( enclosing[ i ] ) + 1;
84*1195Speter 			}
85*1195Speter 			sprintf( starthere , EXTFORMAT , p -> symbol );
86*1195Speter 			starthere += strlen( p -> symbol ) + 1;
87*1195Speter 			if ( starthere >= &extname[ BUFSIZ ] ) {
88*1195Speter 			    panic( "call namelength" );
89*1195Speter 			}
90*1195Speter 			putleaf( P2ICON , 0 , 0 , p2type( p ) , extname );
91*1195Speter 		    }
92*1195Speter 		    break;
93*1195Speter 		case FFUNC:
94*1195Speter 		case FPROC:
95*1195Speter 			    /*
96*1195Speter 			     *	start one of these:
97*1195Speter 			     *	FRTN( frtn , ( *FCALL( frtn ) )(...args...) )
98*1195Speter 			     */
99*1195Speter 			putleaf( P2ICON , 0 , 0 , p2type( p ) , "_FRTN" );
100*1195Speter 			putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
101*1195Speter 		    	putleaf( P2ICON , 0 , 0
102*1195Speter 			    , ADDTYPE( P2PTR , ADDTYPE( P2FTN , p2type( p ) ) )
103*1195Speter 			    , "_FCALL" );
104*1195Speter 			putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
105*1195Speter 			putop( P2CALL , p2type( p ) );
106*1195Speter 			break;
107*1195Speter 		default:
108*1195Speter 			panic("call class");
109745Speter 	    }
110745Speter 	    firsttime = TRUE;
111745Speter #	endif PC
112745Speter 	/*
113745Speter 	 * Loop and process each of
114745Speter 	 * arguments to the proc/func.
115745Speter 	 */
116*1195Speter 	if ( p -> class == FUNC || p -> class == PROC ) {
117*1195Speter 	    for (p1 = p->chain; p1 != NIL; p1 = p1->chain) {
118*1195Speter 		if (argv == NIL) {
119*1195Speter 			error("Not enough arguments to %s", p->symbol);
120*1195Speter 			return (NIL);
121*1195Speter 		}
122*1195Speter 		switch (p1->class) {
123*1195Speter 		    case REF:
124*1195Speter 			    /*
125*1195Speter 			     * Var parameter
126*1195Speter 			     */
127*1195Speter 			    r = argv[1];
128*1195Speter 			    if (r != NIL && r[0] != T_VAR) {
129*1195Speter 				    error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol);
130*1195Speter 				    break;
131*1195Speter 			    }
132*1195Speter 			    q = lvalue( (int *) argv[1], MOD , LREQ );
133*1195Speter 			    if (q == NIL)
134*1195Speter 				    break;
135*1195Speter 			    if (q != p1->type) {
136*1195Speter 				    error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol);
137*1195Speter 				    break;
138*1195Speter 			    }
139*1195Speter 			    break;
140*1195Speter 		    case VAR:
141*1195Speter 			    /*
142*1195Speter 			     * Value parameter
143*1195Speter 			     */
144745Speter #			ifdef OBJ
145*1195Speter 				q = rvalue(argv[1], p1->type , RREQ );
146745Speter #			endif OBJ
147745Speter #			ifdef PC
148*1195Speter 				    /*
149*1195Speter 				     * structure arguments require lvalues,
150*1195Speter 				     * scalars use rvalue.
151*1195Speter 				     */
152*1195Speter 				switch( classify( p1 -> type ) ) {
153*1195Speter 				    case TFILE:
154*1195Speter 				    case TARY:
155*1195Speter 				    case TREC:
156*1195Speter 				    case TSET:
157*1195Speter 				    case TSTR:
158*1195Speter 					q = rvalue( argv[1] , p1 -> type , LREQ );
159*1195Speter 					break;
160*1195Speter 				    case TINT:
161*1195Speter 				    case TSCAL:
162*1195Speter 				    case TBOOL:
163*1195Speter 				    case TCHAR:
164*1195Speter 					precheck( p1 -> type , "_RANG4" , "_RSNG4" );
165*1195Speter 					q = rvalue( argv[1] , p1 -> type , RREQ );
166*1195Speter 					postcheck( p1 -> type );
167*1195Speter 					break;
168*1195Speter 				    default:
169*1195Speter 					q = rvalue( argv[1] , p1 -> type , RREQ );
170*1195Speter 					if (  isa( p1 -> type  , "d" )
171*1195Speter 					   && isa( q , "i" ) ) {
172*1195Speter 					    putop( P2SCONV , P2DOUBLE );
173*1195Speter 					}
174*1195Speter 					break;
175*1195Speter 				}
176*1195Speter #			endif PC
177*1195Speter 			    if (q == NIL)
178745Speter 				    break;
179*1195Speter 			    if (incompat(q, p1->type, argv[1])) {
180*1195Speter 				    cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol);
181745Speter 				    break;
182745Speter 			    }
183745Speter #			ifdef OBJ
184*1195Speter 				if (isa(p1->type, "bcsi"))
185*1195Speter 					rangechk(p1->type, q);
186*1195Speter 				if (q->class != STR)
187*1195Speter 					convert(q, p1->type);
188745Speter #			endif OBJ
189745Speter #			ifdef PC
190*1195Speter 				switch( classify( p1 -> type ) ) {
191*1195Speter 				    case TFILE:
192*1195Speter 				    case TARY:
193*1195Speter 				    case TREC:
194*1195Speter 				    case TSET:
195*1195Speter 				    case TSTR:
196*1195Speter 					    putstrop( P2STARG
197*1195Speter 						, p2type( p1 -> type )
198*1195Speter 						, lwidth( p1 -> type )
199*1195Speter 						, align( p1 -> type ) );
200*1195Speter 				}
201*1195Speter #			endif PC
202*1195Speter 			    break;
203*1195Speter 		    case FFUNC:
204*1195Speter 			    /*
205*1195Speter 			     * function parameter
206*1195Speter 			     */
207*1195Speter 			    q = flvalue( (int *) argv[1] , FFUNC );
208*1195Speter 			    if (q == NIL)
209*1195Speter 				    break;
210*1195Speter 			    if (q != p1->type) {
211*1195Speter 				    error("Function type not identical to type of function parameter %s of %s", p1->symbol, p->symbol);
212*1195Speter 				    break;
213745Speter 			    }
214*1195Speter 			    break;
215*1195Speter 		    case FPROC:
216*1195Speter 			    /*
217*1195Speter 			     * procedure parameter
218*1195Speter 			     */
219*1195Speter 			    q = flvalue( (int *) argv[1] , FPROC );
220*1195Speter 			    if (q != NIL) {
221*1195Speter 				    error("Procedure parameter %s of %s cannot have a type", p1->symbol, p->symbol);
222*1195Speter 			    }
223*1195Speter 			    break;
224*1195Speter 		    default:
225*1195Speter 			    panic("call");
226*1195Speter 		}
227745Speter #	    ifdef PC
228*1195Speter 			/*
229*1195Speter 			 *	if this is the nth (>1) argument,
230*1195Speter 			 *	hang it on the left linear list of arguments
231*1195Speter 			 */
232*1195Speter 		    if ( firsttime ) {
233*1195Speter 			    firsttime = FALSE;
234*1195Speter 		    } else {
235*1195Speter 			    putop( P2LISTOP , P2INT );
236*1195Speter 		    }
237745Speter #	    endif PC
238*1195Speter 		argv = argv[2];
239*1195Speter 	    }
240*1195Speter 	    if (argv != NIL) {
241*1195Speter 		    error("Too many arguments to %s", p->symbol);
242*1195Speter 		    rvlist(argv);
243*1195Speter 		    return (NIL);
244*1195Speter 	    }
245*1195Speter 	} else if ( p -> class == FFUNC || p -> class == FPROC ) {
246*1195Speter 		/*
247*1195Speter 		 *	formal routines can only have by-value parameters.
248*1195Speter 		 *	this will lose for integer actuals passed to real
249*1195Speter 		 *	formals, and strings which people want blank padded.
250*1195Speter 		 */
251*1195Speter #	    ifdef OBJ
252*1195Speter 		cnt = 0;
253*1195Speter #	    endif OBJ
254*1195Speter 	    for ( ; argv != NIL ; argv = argv[2] ) {
255*1195Speter #		ifdef OBJ
256*1195Speter 		    q = rvalue(argv[1], NIL, RREQ );
257*1195Speter 		    cnt += even(lwidth(q));
258*1195Speter #		endif OBJ
259*1195Speter #		ifdef PC
260*1195Speter 			/*
261*1195Speter 			 * structure arguments require lvalues,
262*1195Speter 			 * scalars use rvalue.
263*1195Speter 			 */
264*1195Speter 		    codeoff();
265*1195Speter 		    p1 = rvalue( argv[1] , NIL , RREQ );
266*1195Speter 		    codeon();
267*1195Speter 		    switch( classify( p1 ) ) {
268*1195Speter 			case TSTR:
269*1195Speter 			    if ( p1 -> class == STR && slenflag == 0 ) {
270*1195Speter 				if ( opt( 's' ) ) {
271*1195Speter 				    standard();
272*1195Speter 				} else {
273*1195Speter 				    warning();
274*1195Speter 				}
275*1195Speter 				error("Implementation can't construct equal length strings");
276*1195Speter 				slenflag++;
277*1195Speter 			    }
278*1195Speter 			    /* and fall through */
279*1195Speter 			case TFILE:
280*1195Speter 			case TARY:
281*1195Speter 			case TREC:
282*1195Speter 			case TSET:
283*1195Speter 			    q = rvalue( argv[1] , p1 , LREQ );
284*1195Speter 			    break;
285*1195Speter 			case TINT:
286*1195Speter 			    if ( floatflag == 0 ) {
287*1195Speter 				if ( opt( 's' ) ) {
288*1195Speter 				    standard();
289*1195Speter 				} else {
290*1195Speter 				    warning();
291*1195Speter 				}
292*1195Speter 				error("Implementation can't coerice integer to real");
293*1195Speter 				floatflag++;
294*1195Speter 			    }
295*1195Speter 			    /* and fall through */
296*1195Speter 			case TSCAL:
297*1195Speter 			case TBOOL:
298*1195Speter 			case TCHAR:
299*1195Speter 			default:
300*1195Speter 			    q = rvalue( argv[1] , p1 , RREQ );
301*1195Speter 			    break;
302*1195Speter 		    }
303*1195Speter 		    switch( classify( p1 ) ) {
304*1195Speter 			case TFILE:
305*1195Speter 			case TARY:
306*1195Speter 			case TREC:
307*1195Speter 			case TSET:
308*1195Speter 			case TSTR:
309*1195Speter 				putstrop( P2STARG , p2type( p1 ) ,
310*1195Speter 				    lwidth( p1 ) , align( p1 ) );
311*1195Speter 		    }
312*1195Speter 			/*
313*1195Speter 			 *	if this is the nth (>1) argument,
314*1195Speter 			 *	hang it on the left linear list of arguments
315*1195Speter 			 */
316*1195Speter 		    if ( firsttime ) {
317*1195Speter 			    firsttime = FALSE;
318*1195Speter 		    } else {
319*1195Speter 			    putop( P2LISTOP , P2INT );
320*1195Speter 		    }
321*1195Speter #		endif PC
322*1195Speter 	    }
323*1195Speter 	} else {
324*1195Speter 	    panic("call class");
325745Speter 	}
326745Speter #	ifdef OBJ
327*1195Speter 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
328*1195Speter 		put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]);
329*1195Speter 		put(2, O_FCALL, cnt);
330*1195Speter 		put(2, O_FRTN, even(lwidth(p->type)));
331*1195Speter 	    } else {
332*1195Speter 		put2(O_CALL | psbn << 8+INDX, p->entloc);
333*1195Speter 	    }
334745Speter #	endif OBJ
335745Speter #	ifdef PC
336745Speter 	    if ( porf == FUNC ) {
337745Speter 		rettype = p2type( p -> type );
338745Speter 		switch ( classify( p -> type ) ) {
339745Speter 		    case TBOOL:
340745Speter 		    case TCHAR:
341745Speter 		    case TINT:
342745Speter 		    case TSCAL:
343745Speter 		    case TDOUBLE:
344745Speter 		    case TPTR:
345*1195Speter 			if ( firsttime ) {
346745Speter 				putop( P2UNARY P2CALL , rettype );
347745Speter 			} else {
348745Speter 				putop( P2CALL , rettype );
349745Speter 			}
350*1195Speter 			if (p -> class == FFUNC || p -> class == FPROC ) {
351*1195Speter 			    putop( P2LISTOP , P2INT );
352*1195Speter 			    putop( P2CALL , rettype );
353*1195Speter 			}
354745Speter 			break;
355745Speter 		    default:
356*1195Speter 			if ( firsttime ) {
357745Speter 				putstrop( P2UNARY P2STCALL
358745Speter 					, ADDTYPE( rettype , P2PTR )
359745Speter 					, lwidth( p -> type )
360745Speter 					, align( p -> type ) );
361745Speter 			} else {
362745Speter 				putstrop( P2STCALL
363745Speter 					, ADDTYPE( rettype , P2PTR )
364745Speter 					, lwidth( p -> type )
365745Speter 					, align( p -> type ) );
366745Speter 			}
367*1195Speter 			if (p -> class == FFUNC || p -> class == FPROC ) {
368*1195Speter 			    putop( P2LISTOP , P2INT );
369*1195Speter 			    putop( P2CALL , ADDTYPE( rettype , P2PTR ) );
370*1195Speter 			}
371745Speter 			putstrop( P2STASG , rettype , lwidth( p -> type )
372745Speter 				, align( p -> type ) );
373745Speter 			putLV( 0 , cbn , temp , rettype );
374745Speter 			putop( P2COMOP , P2INT );
375745Speter 			break;
376745Speter 		}
377745Speter 	    } else {
378*1195Speter 		if ( firsttime ) {
379745Speter 			putop( P2UNARY P2CALL , P2INT );
380745Speter 		} else {
381745Speter 			putop( P2CALL , P2INT );
382745Speter 		}
383*1195Speter 		if (p -> class == FFUNC || p -> class == FPROC ) {
384*1195Speter 		    putop( P2LISTOP , P2INT );
385*1195Speter 		    putop( P2CALL , P2INT );
386*1195Speter 		}
387745Speter 		putdot( filename , line );
388745Speter 	    }
389745Speter #	endif PC
390745Speter 	return (p->type);
391745Speter }
392745Speter 
393745Speter rvlist(al)
394745Speter 	register int *al;
395745Speter {
396745Speter 
397745Speter 	for (; al != NIL; al = al[2])
398745Speter 		rvalue( (int *) al[1], NLNIL , RREQ );
399745Speter }
400