xref: /csrg-svn/usr.bin/pascal/src/call.c (revision 3063)
1745Speter /* Copyright (c) 1979 Regents of the University of California */
2745Speter 
3*3063Smckusic static	char sccsid[] = "@(#)call.c 1.4.1.1 03/08/81";
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*3063Smckusic bool	slenflag = 0;
16*3063Smckusic bool	floatflag = 0;
171195Speter 
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 
351195Speter #	ifdef OBJ
361195Speter 	    int		cnt;
371195Speter #	endif OBJ
38745Speter #	ifdef PC
39*3063Smckusic 	    long	temp;
40*3063Smckusic 	    int		firsttime;
41*3063Smckusic 	    int		rettype;
42745Speter #	endif PC
43745Speter 
44745Speter #	ifdef OBJ
451195Speter 	    if (p->class == FFUNC || p->class == FPROC)
46*3063Smckusic 		put(2, PTR_RV | cbn << 8+INDX, (int)p->value[NL_OFFS]);
47745Speter 	    if (porf == FUNC)
48745Speter 		    /*
49745Speter 		     * Push some space
50745Speter 		     * for the function return type
51745Speter 		     */
52*3063Smckusic 		    put(2, O_PUSH, leven(-lwidth(p->type)));
53745Speter #	endif OBJ
54745Speter #	ifdef PC
55745Speter 	    if ( porf == FUNC ) {
56*3063Smckusic 		switch( classify( p -> type ) ) {
57745Speter 		    case TSTR:
58745Speter 		    case TSET:
59745Speter 		    case TREC:
60745Speter 		    case TFILE:
61745Speter 		    case TARY:
62*3063Smckusic 			temp = sizes[ cbn ].om_off -= width( p -> type );
63*3063Smckusic 			putlbracket( ftnno , -sizes[cbn].om_off );
64*3063Smckusic 			if (sizes[cbn].om_off < sizes[cbn].om_max) {
65*3063Smckusic 				sizes[cbn].om_max = sizes[cbn].om_off;
66745Speter 			}
67*3063Smckusic 			putRV( 0 , cbn , temp , P2STRTY );
68745Speter 		}
69745Speter 	    }
701195Speter 	    switch ( p -> class ) {
711195Speter 		case FUNC:
721195Speter 		case PROC:
731195Speter 		    {
741195Speter 			char	extname[ BUFSIZ ];
751195Speter 			char	*starthere;
761195Speter 			int	funcbn;
771195Speter 			int	i;
78745Speter 
791195Speter 			starthere = &extname[0];
801195Speter 			funcbn = p -> nl_block & 037;
811195Speter 			for ( i = 1 ; i < funcbn ; i++ ) {
821195Speter 			    sprintf( starthere , EXTFORMAT , enclosing[ i ] );
831195Speter 			    starthere += strlen( enclosing[ i ] ) + 1;
841195Speter 			}
851195Speter 			sprintf( starthere , EXTFORMAT , p -> symbol );
861195Speter 			starthere += strlen( p -> symbol ) + 1;
871195Speter 			if ( starthere >= &extname[ BUFSIZ ] ) {
881195Speter 			    panic( "call namelength" );
891195Speter 			}
901195Speter 			putleaf( P2ICON , 0 , 0 , p2type( p ) , extname );
911195Speter 		    }
921195Speter 		    break;
931195Speter 		case FFUNC:
941195Speter 		case FPROC:
951195Speter 			    /*
96*3063Smckusic 			     *	start one of these:
97*3063Smckusic 			     *	FRTN( frtn , ( *FCALL( frtn ) )(...args...) )
981195Speter 			     */
99*3063Smckusic 			putleaf( P2ICON , 0 , 0 , p2type( p ) , "_FRTN" );
100*3063Smckusic 			putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
1011195Speter 		    	putleaf( P2ICON , 0 , 0
102*3063Smckusic 			    , ADDTYPE( P2PTR , ADDTYPE( P2FTN , p2type( p ) ) )
1031195Speter 			    , "_FCALL" );
1041195Speter 			putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY );
105*3063Smckusic 			putop( P2CALL , p2type( p ) );
1061195Speter 			break;
1071195Speter 		default:
1081195Speter 			panic("call class");
109745Speter 	    }
110*3063Smckusic 	    firsttime = TRUE;
111745Speter #	endif PC
112745Speter 	/*
113745Speter 	 * Loop and process each of
114745Speter 	 * arguments to the proc/func.
115745Speter 	 */
1161195Speter 	if ( p -> class == FUNC || p -> class == PROC ) {
1171195Speter 	    for (p1 = p->chain; p1 != NIL; p1 = p1->chain) {
1181195Speter 		if (argv == NIL) {
1191195Speter 			error("Not enough arguments to %s", p->symbol);
1201195Speter 			return (NIL);
1211195Speter 		}
1221195Speter 		switch (p1->class) {
1231195Speter 		    case REF:
1241195Speter 			    /*
1251195Speter 			     * Var parameter
1261195Speter 			     */
1271195Speter 			    r = argv[1];
1281195Speter 			    if (r != NIL && r[0] != T_VAR) {
1291195Speter 				    error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol);
1301195Speter 				    break;
1311195Speter 			    }
1321195Speter 			    q = lvalue( (int *) argv[1], MOD , LREQ );
1331195Speter 			    if (q == NIL)
1341195Speter 				    break;
1351195Speter 			    if (q != p1->type) {
1361195Speter 				    error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol);
1371195Speter 				    break;
1381195Speter 			    }
1391195Speter 			    break;
1401195Speter 		    case VAR:
1411195Speter 			    /*
1421195Speter 			     * Value parameter
1431195Speter 			     */
144745Speter #			ifdef OBJ
1451195Speter 				q = rvalue(argv[1], p1->type , RREQ );
146745Speter #			endif OBJ
147745Speter #			ifdef PC
1481195Speter 				    /*
1491195Speter 				     * structure arguments require lvalues,
1501195Speter 				     * scalars use rvalue.
1511195Speter 				     */
1521195Speter 				switch( classify( p1 -> type ) ) {
1531195Speter 				    case TFILE:
1541195Speter 				    case TARY:
1551195Speter 				    case TREC:
1561195Speter 				    case TSET:
1571195Speter 				    case TSTR:
1581195Speter 					q = rvalue( argv[1] , p1 -> type , LREQ );
1591195Speter 					break;
1601195Speter 				    case TINT:
1611195Speter 				    case TSCAL:
1621195Speter 				    case TBOOL:
1631195Speter 				    case TCHAR:
1641195Speter 					precheck( p1 -> type , "_RANG4" , "_RSNG4" );
1651195Speter 					q = rvalue( argv[1] , p1 -> type , RREQ );
1661195Speter 					postcheck( p1 -> type );
1671195Speter 					break;
1681195Speter 				    default:
1691195Speter 					q = rvalue( argv[1] , p1 -> type , RREQ );
1701195Speter 					if (  isa( p1 -> type  , "d" )
1711195Speter 					   && isa( q , "i" ) ) {
1721195Speter 					    putop( P2SCONV , P2DOUBLE );
1731195Speter 					}
1741195Speter 					break;
1751195Speter 				}
1761195Speter #			endif PC
1771195Speter 			    if (q == NIL)
178745Speter 				    break;
1791195Speter 			    if (incompat(q, p1->type, argv[1])) {
1801195Speter 				    cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol);
181745Speter 				    break;
182745Speter 			    }
183745Speter #			ifdef OBJ
1841195Speter 				if (isa(p1->type, "bcsi"))
1851195Speter 					rangechk(p1->type, q);
1861195Speter 				if (q->class != STR)
1871195Speter 					convert(q, p1->type);
188745Speter #			endif OBJ
189745Speter #			ifdef PC
1901195Speter 				switch( classify( p1 -> type ) ) {
1911195Speter 				    case TFILE:
1921195Speter 				    case TARY:
1931195Speter 				    case TREC:
1941195Speter 				    case TSET:
1951195Speter 				    case TSTR:
1961195Speter 					    putstrop( P2STARG
1971195Speter 						, p2type( p1 -> type )
1981195Speter 						, lwidth( p1 -> type )
1991195Speter 						, align( p1 -> type ) );
2001195Speter 				}
2011195Speter #			endif PC
2021195Speter 			    break;
2031195Speter 		    case FFUNC:
2041195Speter 			    /*
2051195Speter 			     * function parameter
2061195Speter 			     */
2071195Speter 			    q = flvalue( (int *) argv[1] , FFUNC );
2081195Speter 			    if (q == NIL)
2091195Speter 				    break;
2101195Speter 			    if (q != p1->type) {
2111195Speter 				    error("Function type not identical to type of function parameter %s of %s", p1->symbol, p->symbol);
2121195Speter 				    break;
213745Speter 			    }
2141195Speter 			    break;
2151195Speter 		    case FPROC:
2161195Speter 			    /*
2171195Speter 			     * procedure parameter
2181195Speter 			     */
2191195Speter 			    q = flvalue( (int *) argv[1] , FPROC );
2201195Speter 			    if (q != NIL) {
2211195Speter 				    error("Procedure parameter %s of %s cannot have a type", p1->symbol, p->symbol);
2221195Speter 			    }
2231195Speter 			    break;
2241195Speter 		    default:
2251195Speter 			    panic("call");
2261195Speter 		}
227745Speter #	    ifdef PC
2281195Speter 			/*
2291195Speter 			 *	if this is the nth (>1) argument,
2301195Speter 			 *	hang it on the left linear list of arguments
2311195Speter 			 */
232*3063Smckusic 		    if ( firsttime ) {
233*3063Smckusic 			    firsttime = FALSE;
2341195Speter 		    } else {
2351195Speter 			    putop( P2LISTOP , P2INT );
2361195Speter 		    }
237745Speter #	    endif PC
2381195Speter 		argv = argv[2];
2391195Speter 	    }
2401195Speter 	    if (argv != NIL) {
2411195Speter 		    error("Too many arguments to %s", p->symbol);
2421195Speter 		    rvlist(argv);
2431195Speter 		    return (NIL);
2441195Speter 	    }
2451195Speter 	} else if ( p -> class == FFUNC || p -> class == FPROC ) {
2461195Speter 		/*
2471195Speter 		 *	formal routines can only have by-value parameters.
2481195Speter 		 *	this will lose for integer actuals passed to real
2491195Speter 		 *	formals, and strings which people want blank padded.
2501195Speter 		 */
2511195Speter #	    ifdef OBJ
2521195Speter 		cnt = 0;
2531195Speter #	    endif OBJ
2541195Speter 	    for ( ; argv != NIL ; argv = argv[2] ) {
2551195Speter #		ifdef OBJ
2561195Speter 		    q = rvalue(argv[1], NIL, RREQ );
257*3063Smckusic 		    cnt += leven(lwidth(q));
2581195Speter #		endif OBJ
2591195Speter #		ifdef PC
2601195Speter 			/*
2611195Speter 			 * structure arguments require lvalues,
2621195Speter 			 * scalars use rvalue.
2631195Speter 			 */
2641195Speter 		    codeoff();
2651195Speter 		    p1 = rvalue( argv[1] , NIL , RREQ );
2661195Speter 		    codeon();
2671195Speter 		    switch( classify( p1 ) ) {
2681195Speter 			case TSTR:
269*3063Smckusic 			    if ( p1 -> class == STR && slenflag == 0 ) {
270*3063Smckusic 				if ( opt( 's' ) ) {
271*3063Smckusic 				    standard();
272*3063Smckusic 				} else {
273*3063Smckusic 				    warning();
274*3063Smckusic 				}
2751195Speter 				error("Implementation can't construct equal length strings");
276*3063Smckusic 				slenflag++;
2771195Speter 			    }
2781195Speter 			    /* and fall through */
2791195Speter 			case TFILE:
2801195Speter 			case TARY:
2811195Speter 			case TREC:
2821195Speter 			case TSET:
2831195Speter 			    q = rvalue( argv[1] , p1 , LREQ );
2841195Speter 			    break;
2851195Speter 			case TINT:
286*3063Smckusic 			    if ( floatflag == 0 ) {
287*3063Smckusic 				if ( opt( 's' ) ) {
288*3063Smckusic 				    standard();
289*3063Smckusic 				} else {
290*3063Smckusic 				    warning();
291*3063Smckusic 				}
2921195Speter 				error("Implementation can't coerice integer to real");
293*3063Smckusic 				floatflag++;
2941195Speter 			    }
2951195Speter 			    /* and fall through */
2961195Speter 			case TSCAL:
2971195Speter 			case TBOOL:
2981195Speter 			case TCHAR:
2991195Speter 			default:
3001195Speter 			    q = rvalue( argv[1] , p1 , RREQ );
3011195Speter 			    break;
3021195Speter 		    }
3031195Speter 		    switch( classify( p1 ) ) {
3041195Speter 			case TFILE:
3051195Speter 			case TARY:
3061195Speter 			case TREC:
3071195Speter 			case TSET:
3081195Speter 			case TSTR:
3091195Speter 				putstrop( P2STARG , p2type( p1 ) ,
3101195Speter 				    lwidth( p1 ) , align( p1 ) );
3111195Speter 		    }
3121195Speter 			/*
3131195Speter 			 *	if this is the nth (>1) argument,
3141195Speter 			 *	hang it on the left linear list of arguments
3151195Speter 			 */
316*3063Smckusic 		    if ( firsttime ) {
317*3063Smckusic 			    firsttime = FALSE;
3181195Speter 		    } else {
3191195Speter 			    putop( P2LISTOP , P2INT );
3201195Speter 		    }
3211195Speter #		endif PC
3221195Speter 	    }
3231195Speter 	} else {
3241195Speter 	    panic("call class");
325745Speter 	}
326745Speter #	ifdef OBJ
3271195Speter 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
328*3063Smckusic 		put(2, PTR_RV | cbn << 8+INDX, (int)p->value[NL_OFFS]);
329*3063Smckusic 		put(2, O_FCALL, (long)cnt);
330*3063Smckusic 		put(2, O_FRTN, even(width(p->type)));
3311195Speter 	    } else {
332*3063Smckusic 		/* put(2, O_CALL | psbn << 8+INDX, (long)p->entloc); */
333*3063Smckusic 		put(2, O_CALL | psbn << 8, (long)p->entloc);
3341195Speter 	    }
335745Speter #	endif OBJ
336745Speter #	ifdef PC
337745Speter 	    if ( porf == FUNC ) {
338*3063Smckusic 		rettype = p2type( p -> type );
339*3063Smckusic 		switch ( classify( p -> type ) ) {
340745Speter 		    case TBOOL:
341745Speter 		    case TCHAR:
342745Speter 		    case TINT:
343745Speter 		    case TSCAL:
344745Speter 		    case TDOUBLE:
345745Speter 		    case TPTR:
346*3063Smckusic 			if ( firsttime ) {
347*3063Smckusic 				putop( P2UNARY P2CALL , rettype );
348*3063Smckusic 			} else {
349*3063Smckusic 				putop( P2CALL , rettype );
350745Speter 			}
351*3063Smckusic 			if (p -> class == FFUNC || p -> class == FPROC ) {
352*3063Smckusic 			    putop( P2LISTOP , P2INT );
353*3063Smckusic 			    putop( P2CALL , rettype );
354*3063Smckusic 			}
355745Speter 			break;
356745Speter 		    default:
357*3063Smckusic 			if ( firsttime ) {
358*3063Smckusic 				putstrop( P2UNARY P2STCALL
359*3063Smckusic 					, ADDTYPE( rettype , P2PTR )
360*3063Smckusic 					, lwidth( p -> type )
361*3063Smckusic 					, align( p -> type ) );
362*3063Smckusic 			} else {
363*3063Smckusic 				putstrop( P2STCALL
364*3063Smckusic 					, ADDTYPE( rettype , P2PTR )
365*3063Smckusic 					, lwidth( p -> type )
366*3063Smckusic 					, align( p -> type ) );
367*3063Smckusic 			}
368*3063Smckusic 			if (p -> class == FFUNC || p -> class == FPROC ) {
369*3063Smckusic 			    putop( P2LISTOP , P2INT );
370*3063Smckusic 			    putop( P2CALL , ADDTYPE( rettype , P2PTR ) );
371*3063Smckusic 			}
372*3063Smckusic 			putstrop( P2STASG , rettype , lwidth( p -> type )
373745Speter 				, align( p -> type ) );
374*3063Smckusic 			putLV( 0 , cbn , temp , rettype );
375*3063Smckusic 			putop( P2COMOP , P2INT );
376745Speter 			break;
377745Speter 		}
378745Speter 	    } else {
379*3063Smckusic 		if ( firsttime ) {
380*3063Smckusic 			putop( P2UNARY P2CALL , P2INT );
381745Speter 		} else {
382*3063Smckusic 			putop( P2CALL , P2INT );
383745Speter 		}
384*3063Smckusic 		if (p -> class == FFUNC || p -> class == FPROC ) {
385*3063Smckusic 		    putop( P2LISTOP , P2INT );
386*3063Smckusic 		    putop( P2CALL , P2INT );
387*3063Smckusic 		}
388745Speter 		putdot( filename , line );
389745Speter 	    }
390745Speter #	endif PC
391745Speter 	return (p->type);
392745Speter }
393745Speter 
394745Speter rvlist(al)
395745Speter 	register int *al;
396745Speter {
397745Speter 
398745Speter 	for (; al != NIL; al = al[2])
399745Speter 		rvalue( (int *) al[1], NLNIL , RREQ );
400745Speter }
401