xref: /csrg-svn/usr.bin/pascal/src/call.c (revision 745)
1*745Speter /* Copyright (c) 1979 Regents of the University of California */
2*745Speter 
3*745Speter static	char sccsid[] = "@(#)call.c 1.1 08/27/80";
4*745Speter 
5*745Speter #include "whoami.h"
6*745Speter #include "0.h"
7*745Speter #include "tree.h"
8*745Speter #include "opcode.h"
9*745Speter #include "objfmt.h"
10*745Speter #ifdef PC
11*745Speter #   include "pc.h"
12*745Speter #   include "pcops.h"
13*745Speter #endif PC
14*745Speter 
15*745Speter /*
16*745Speter  * Call generates code for calls to
17*745Speter  * user defined procedures and functions
18*745Speter  * and is called by proc and funccod.
19*745Speter  * P is the result of the lookup
20*745Speter  * of the procedure/function symbol,
21*745Speter  * and porf is PROC or FUNC.
22*745Speter  * Psbn is the block number of p.
23*745Speter  */
24*745Speter struct nl *
25*745Speter call(p, argv, porf, psbn)
26*745Speter 	struct nl *p;
27*745Speter 	int *argv, porf, psbn;
28*745Speter {
29*745Speter 	register struct nl *p1, *q;
30*745Speter 	int *r;
31*745Speter 
32*745Speter #	ifdef PC
33*745Speter 	    long	temp;
34*745Speter 	    int		firsttime;
35*745Speter 	    int		rettype;
36*745Speter #	endif PC
37*745Speter 
38*745Speter #	ifdef OBJ
39*745Speter 	    if (porf == FUNC)
40*745Speter 		    /*
41*745Speter 		     * Push some space
42*745Speter 		     * for the function return type
43*745Speter 		     */
44*745Speter 		    put2(O_PUSH, even(-width(p->type)));
45*745Speter #	endif OBJ
46*745Speter #	ifdef PC
47*745Speter 	    if ( porf == FUNC ) {
48*745Speter 		switch( classify( p -> type ) ) {
49*745Speter 		    case TSTR:
50*745Speter 		    case TSET:
51*745Speter 		    case TREC:
52*745Speter 		    case TFILE:
53*745Speter 		    case TARY:
54*745Speter 			temp = sizes[ cbn ].om_off -= width( p -> type );
55*745Speter 			putlbracket( ftnno , -sizes[cbn].om_off );
56*745Speter 			if (sizes[cbn].om_off < sizes[cbn].om_max) {
57*745Speter 				sizes[cbn].om_max = sizes[cbn].om_off;
58*745Speter 			}
59*745Speter 			putRV( 0 , cbn , temp , P2STRTY );
60*745Speter 		}
61*745Speter 	    }
62*745Speter 	    {
63*745Speter 		char	extname[ BUFSIZ ];
64*745Speter 		char	*starthere;
65*745Speter 		int	funcbn;
66*745Speter 		int	i;
67*745Speter 
68*745Speter 		starthere = &extname[0];
69*745Speter 		funcbn = p -> nl_block & 037;
70*745Speter 		for ( i = 1 ; i < funcbn ; i++ ) {
71*745Speter 		    sprintf( starthere , EXTFORMAT , enclosing[ i ] );
72*745Speter 		    starthere += strlen( enclosing[ i ] ) + 1;
73*745Speter 		}
74*745Speter 		sprintf( starthere , EXTFORMAT , p -> symbol );
75*745Speter 		starthere += strlen( p -> symbol ) + 1;
76*745Speter 		if ( starthere >= &extname[ BUFSIZ ] ) {
77*745Speter 		    panic( "call namelength" );
78*745Speter 		}
79*745Speter 		putleaf( P2ICON , 0 , 0 , p2type( p ) , extname );
80*745Speter 	    }
81*745Speter 	    firsttime = TRUE;
82*745Speter #	endif PC
83*745Speter 	/*
84*745Speter 	 * Loop and process each of
85*745Speter 	 * arguments to the proc/func.
86*745Speter 	 */
87*745Speter 	for (p1 = p->chain; p1 != NIL; p1 = p1->chain) {
88*745Speter 	    if (argv == NIL) {
89*745Speter 		    error("Not enough arguments to %s", p->symbol);
90*745Speter 		    return (NIL);
91*745Speter 	    }
92*745Speter 	    switch (p1->class) {
93*745Speter 		case REF:
94*745Speter 			/*
95*745Speter 			 * Var parameter
96*745Speter 			 */
97*745Speter 			r = argv[1];
98*745Speter 			if (r != NIL && r[0] != T_VAR) {
99*745Speter 				error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol);
100*745Speter 				break;
101*745Speter 			}
102*745Speter 			q = lvalue( (int *) argv[1], MOD , LREQ );
103*745Speter 			if (q == NIL)
104*745Speter 				break;
105*745Speter 			if (q != p1->type) {
106*745Speter 				error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol);
107*745Speter 				break;
108*745Speter 			}
109*745Speter 			break;
110*745Speter 		case VAR:
111*745Speter 			/*
112*745Speter 			 * Value parameter
113*745Speter 			 */
114*745Speter #			ifdef OBJ
115*745Speter 			    q = rvalue(argv[1], p1->type , RREQ );
116*745Speter #			endif OBJ
117*745Speter #			ifdef PC
118*745Speter 				/*
119*745Speter 				 * structure arguments require lvalues,
120*745Speter 				 * scalars use rvalue.
121*745Speter 				 */
122*745Speter 			    switch( classify( p1 -> type ) ) {
123*745Speter 				case TFILE:
124*745Speter 				case TARY:
125*745Speter 				case TREC:
126*745Speter 				case TSET:
127*745Speter 				case TSTR:
128*745Speter 				    q = rvalue( argv[1] , p1 -> type , LREQ );
129*745Speter 				    break;
130*745Speter 				case TINT:
131*745Speter 				case TSCAL:
132*745Speter 				case TBOOL:
133*745Speter 				case TCHAR:
134*745Speter 				    precheck( p1 -> type , "_RANG4" , "_RSNG4" );
135*745Speter 				    q = rvalue( argv[1] , p1 -> type , RREQ );
136*745Speter 				    postcheck( p1 -> type );
137*745Speter 				    break;
138*745Speter 					/*
139*745Speter 					 * and fall through
140*745Speter 					 */
141*745Speter 				default:
142*745Speter 				    q = rvalue( argv[1] , p1 -> type , RREQ );
143*745Speter 				    break;
144*745Speter 			    }
145*745Speter #			endif PC
146*745Speter 			if (q == NIL)
147*745Speter 				break;
148*745Speter 			if (incompat(q, p1->type, argv[1])) {
149*745Speter 				cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol);
150*745Speter 				break;
151*745Speter 			}
152*745Speter #			ifdef OBJ
153*745Speter 			    if (isa(p1->type, "bcsi"))
154*745Speter 				    rangechk(p1->type, q);
155*745Speter 			    if (q->class != STR)
156*745Speter 				    convert(q, p1->type);
157*745Speter #			endif OBJ
158*745Speter #			ifdef PC
159*745Speter 			    switch( classify( p1 -> type ) ) {
160*745Speter 				case TFILE:
161*745Speter 				case TARY:
162*745Speter 				case TREC:
163*745Speter 				case TSET:
164*745Speter 				case TSTR:
165*745Speter 					putstrop( P2STARG
166*745Speter 					    , p2type( p1 -> type )
167*745Speter 					    , lwidth( p1 -> type )
168*745Speter 					    , align( p1 -> type ) );
169*745Speter 			    }
170*745Speter #			endif PC
171*745Speter 			break;
172*745Speter 		default:
173*745Speter 			panic("call");
174*745Speter 	    }
175*745Speter #	    ifdef PC
176*745Speter 		    /*
177*745Speter 		     *	if this is the nth (>1) argument,
178*745Speter 		     *	hang it on the left linear list of arguments
179*745Speter 		     */
180*745Speter 		if ( firsttime ) {
181*745Speter 			firsttime = FALSE;
182*745Speter 		} else {
183*745Speter 			putop( P2LISTOP , P2INT );
184*745Speter 		}
185*745Speter #	    endif PC
186*745Speter 	    argv = argv[2];
187*745Speter 	}
188*745Speter 	if (argv != NIL) {
189*745Speter 		error("Too many arguments to %s", p->symbol);
190*745Speter 		rvlist(argv);
191*745Speter 		return (NIL);
192*745Speter 	}
193*745Speter #	ifdef OBJ
194*745Speter 	    put2(O_CALL | psbn << 8+INDX, p->entloc);
195*745Speter 	    put2(O_POP, p->value[NL_OFFS]-DPOFF2);
196*745Speter #	endif OBJ
197*745Speter #	ifdef PC
198*745Speter 	    if ( porf == FUNC ) {
199*745Speter 		rettype = p2type( p -> type );
200*745Speter 		switch ( classify( p -> type ) ) {
201*745Speter 		    case TBOOL:
202*745Speter 		    case TCHAR:
203*745Speter 		    case TINT:
204*745Speter 		    case TSCAL:
205*745Speter 		    case TDOUBLE:
206*745Speter 		    case TPTR:
207*745Speter 			if ( p -> chain == NIL ) {
208*745Speter 				putop( P2UNARY P2CALL , rettype );
209*745Speter 			} else {
210*745Speter 				putop( P2CALL , rettype );
211*745Speter 			}
212*745Speter 			break;
213*745Speter 		    default:
214*745Speter 			if ( p -> chain == NIL ) {
215*745Speter 				putstrop( P2UNARY P2STCALL
216*745Speter 					, ADDTYPE( rettype , P2PTR )
217*745Speter 					, lwidth( p -> type )
218*745Speter 					, align( p -> type ) );
219*745Speter 			} else {
220*745Speter 				putstrop( P2STCALL
221*745Speter 					, ADDTYPE( rettype , P2PTR )
222*745Speter 					, lwidth( p -> type )
223*745Speter 					, align( p -> type ) );
224*745Speter 			}
225*745Speter 			putstrop( P2STASG , rettype , lwidth( p -> type )
226*745Speter 				, align( p -> type ) );
227*745Speter 			putLV( 0 , cbn , temp , rettype );
228*745Speter 			putop( P2COMOP , P2INT );
229*745Speter 			break;
230*745Speter 		}
231*745Speter 	    } else {
232*745Speter 		if ( p -> chain == NIL ) {
233*745Speter 			putop( P2UNARY P2CALL , P2INT );
234*745Speter 		} else {
235*745Speter 			putop( P2CALL , P2INT );
236*745Speter 		}
237*745Speter 		putdot( filename , line );
238*745Speter 	    }
239*745Speter #	endif PC
240*745Speter 	return (p->type);
241*745Speter }
242*745Speter 
243*745Speter rvlist(al)
244*745Speter 	register int *al;
245*745Speter {
246*745Speter 
247*745Speter 	for (; al != NIL; al = al[2])
248*745Speter 		rvalue( (int *) al[1], NLNIL , RREQ );
249*745Speter }
250