xref: /csrg-svn/usr.bin/pascal/src/call.c (revision 62203)
148116Sbostic /*-
2*62203Sbostic  * Copyright (c) 1980, 1993
3*62203Sbostic  *	The Regents of the University of California.  All rights reserved.
448116Sbostic  *
548116Sbostic  * %sccs.include.redist.c%
621953Sdist  */
7745Speter 
814727Sthien #ifndef lint
9*62203Sbostic static char sccsid[] = "@(#)call.c	8.1 (Berkeley) 06/06/93";
1048116Sbostic #endif /* not lint */
11745Speter 
12745Speter #include "whoami.h"
13745Speter #include "0.h"
14745Speter #include "tree.h"
15745Speter #include "opcode.h"
16745Speter #include "objfmt.h"
1730037Smckusick #include "align.h"
18745Speter #ifdef PC
19745Speter #   include "pc.h"
2018453Sralph #   include <pcc.h>
21745Speter #endif PC
2211331Speter #include "tmps.h"
2314727Sthien #include "tree_ty.h"
24745Speter 
25745Speter /*
26745Speter  * Call generates code for calls to
27745Speter  * user defined procedures and functions
28745Speter  * and is called by proc and funccod.
29745Speter  * P is the result of the lookup
30745Speter  * of the procedure/function symbol,
31745Speter  * and porf is PROC or FUNC.
32745Speter  * Psbn is the block number of p.
333065Smckusic  *
343065Smckusic  *	the idea here is that regular scalar functions are just called,
353065Smckusic  *	while structure functions and formal functions have their results
363065Smckusic  *	stored in a temporary after the call.
373065Smckusic  *	structure functions do this because they return pointers
383065Smckusic  *	to static results, so we copy the static
393065Smckusic  *	and return a pointer to the copy.
403065Smckusic  *	formal functions do this because we have to save the result
413065Smckusic  *	around a call to the runtime routine which restores the display,
423065Smckusic  *	so we can't just leave the result lying around in registers.
433886Speter  *	formal calls save the address of the descriptor in a local
443886Speter  *	temporary, so it can be addressed for the call which restores
453886Speter  *	the display (FRTN).
463426Speter  *	calls to formal parameters pass the formal as a hidden argument
473426Speter  *	to a special entry point for the formal call.
483426Speter  *	[this is somewhat dependent on the way arguments are addressed.]
493065Smckusic  *	so PROCs and scalar FUNCs look like
503065Smckusic  *		p(...args...)
513065Smckusic  *	structure FUNCs look like
523065Smckusic  *		(temp = p(...args...),&temp)
533065Smckusic  *	formal FPROCs look like
544014Smckusic  *		( t=p,( t -> entryaddr )(...args...,t,s),FRTN(t,s))
553065Smckusic  *	formal scalar FFUNCs look like
564014Smckusic  *		( t=p,temp=( t -> entryaddr )(...args...,t,s),FRTN(t,s),temp)
573065Smckusic  *	formal structure FFUNCs look like
584014Smckusic  *		(t=p,temp = ( t -> entryaddr )(...args...,t,s),FRTN(t,s),&temp)
59745Speter  */
60745Speter struct nl *
call(p,argv_node,porf,psbn)6114727Sthien call(p, argv_node, porf, psbn)
62745Speter 	struct nl *p;
6314727Sthien 	struct tnode	*argv_node;	/* list node */
6414727Sthien 	int porf, psbn;
65745Speter {
6615971Smckusick 	register struct nl *p1, *q, *p2;
6715971Smckusick 	register struct nl *ptype, *ctype;
6814727Sthien 	struct tnode *rnode;
6915971Smckusick 	int i, j, d;
703297Smckusic 	bool chk = TRUE;
714014Smckusic  	struct nl	*savedispnp;	/* temporary to hold saved display */
72745Speter #	ifdef PC
7314727Sthien 	    int		p_type_class = classify( p -> type );
743065Smckusic 	    long	p_type_p2type = p2type( p -> type );
753065Smckusic 	    bool	noarguments;
763065Smckusic 		/*
773065Smckusic 		 *	these get used if temporaries and structures are used
783065Smckusic 		 */
793824Speter 	    struct nl	*tempnlp;
803065Smckusic 	    long	temptype;	/* type of the temporary */
813065Smckusic 	    long	p_type_width;
823065Smckusic 	    long	p_type_align;
833362Speter 	    char	extname[ BUFSIZ ];
843886Speter 	    struct nl	*tempdescrp;
85745Speter #	endif PC
86745Speter 
874014Smckusic          if (p->class == FFUNC || p->class == FPROC) {
884014Smckusic  	    /*
894014Smckusic  	     * allocate space to save the display for formal calls
904014Smckusic  	     */
9114727Sthien 	    savedispnp = tmpalloc( (long) sizeof display , NLNIL , NOREG );
924014Smckusic  	}
93745Speter #	ifdef OBJ
943426Speter 	    if (p->class == FFUNC || p->class == FPROC) {
9514727Sthien  		(void) put(2, O_LV | cbn << 8 + INDX ,
964014Smckusic  			(int) savedispnp -> value[ NL_OFFS ] );
9714727Sthien 		(void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]);
983426Speter 	    }
993426Speter 	    if (porf == FUNC) {
100745Speter 		    /*
101745Speter 		     * Push some space
102745Speter 		     * for the function return type
103745Speter 		     */
10430037Smckusick 		    (void) put(2, O_PUSH,
10530037Smckusick 			-roundup(lwidth(p->type), (long) A_STACK));
1063426Speter 	    }
107745Speter #	endif OBJ
108745Speter #	ifdef PC
1093065Smckusic 		/*
1103886Speter 		 *	if this is a formal call,
1113886Speter 		 *	stash the address of the descriptor
1123886Speter 		 *	in a temporary so we can find it
1133886Speter 		 *	after the FCALL for the call to FRTN
1143886Speter 		 */
1153886Speter 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
11614727Sthien 		tempdescrp = tmpalloc((long) (sizeof( struct formalrtn *)),
11714727Sthien 					NLNIL, REGOK );
11814727Sthien 		putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] ,
11918453Sralph 			tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
12014727Sthien 		putRV((char *) 0 , psbn , p -> value[ NL_OFFS ] ,
12118453Sralph 			p -> extra_flags , PCCTM_PTR|PCCT_STRTY );
12218453Sralph 		putop( PCC_ASSIGN , PCCTM_PTR | PCCT_STRTY );
1233886Speter 	    }
1243886Speter 		/*
1253065Smckusic 		 *	if we have to store a temporary,
1263065Smckusic 		 *	temptype will be its type,
12718453Sralph 		 *	otherwise, it's PCCT_UNDEF.
1283065Smckusic 		 */
12918453Sralph 	    temptype = PCCT_UNDEF;
130745Speter 	    if ( porf == FUNC ) {
1313065Smckusic 		p_type_width = width( p -> type );
1323065Smckusic 		switch( p_type_class ) {
133745Speter 		    case TSTR:
134745Speter 		    case TSET:
135745Speter 		    case TREC:
136745Speter 		    case TFILE:
137745Speter 		    case TARY:
13818453Sralph 			temptype = PCCT_STRTY;
1393065Smckusic 			p_type_align = align( p -> type );
1403065Smckusic 			break;
1413065Smckusic 		    default:
1423065Smckusic 			if ( p -> class == FFUNC ) {
14314727Sthien 			    temptype = p2type( p -> type );
144745Speter 			}
1453065Smckusic 			break;
146745Speter 		}
14718453Sralph 		if ( temptype != PCCT_UNDEF ) {
1483824Speter 		    tempnlp = tmpalloc(p_type_width, p -> type, NOREG);
1493065Smckusic 			/*
1503065Smckusic 			 *	temp
1513065Smckusic 			 *	for (temp = ...
1523065Smckusic 			 */
15314727Sthien 		    putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
15414727Sthien 			    tempnlp -> extra_flags , (int) temptype );
1553065Smckusic 		}
156745Speter 	    }
1571195Speter 	    switch ( p -> class ) {
1581195Speter 		case FUNC:
1591195Speter 		case PROC:
1603065Smckusic 			/*
1613065Smckusic 			 *	... p( ...
1623065Smckusic 			 */
1633372Speter 		    sextname( extname , p -> symbol , BLOCKNO(p -> nl_block) );
16418453Sralph 		    putleaf( PCC_ICON , 0 , 0 , p2type( p ) , extname );
1651195Speter 		    break;
1661195Speter 		case FFUNC:
1671195Speter 		case FPROC:
1683886Speter 
1691195Speter 			    /*
1703886Speter 			     *	... ( t -> entryaddr )( ...
1711195Speter 			     */
17212902Speter 			    /* 	the descriptor */
17314727Sthien 			putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] ,
17418453Sralph 				tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY );
17512902Speter 			    /*	the entry address within the descriptor */
1763426Speter 			if ( FENTRYOFFSET != 0 ) {
17718453Sralph 			    putleaf( PCC_ICON , FENTRYOFFSET , 0 , PCCT_INT ,
17814727Sthien 						(char *) 0 );
17918453Sralph 			    putop( PCC_PLUS ,
18018453Sralph 				PCCM_ADDTYPE(
18118453Sralph 				    PCCM_ADDTYPE( PCCM_ADDTYPE( p2type( p ) , PCCTM_FTN ) ,
18218453Sralph 					    PCCTM_PTR ) ,
18318453Sralph 					PCCTM_PTR ) );
1843426Speter 			}
18512902Speter 			    /*
18612902Speter 			     *	indirect to fetch the formal entry address
18712902Speter 			     *	with the result type of the routine.
18812902Speter 			     */
18912902Speter 			if (p -> class == FFUNC) {
19018453Sralph 			    putop( PCCOM_UNARY PCC_MUL ,
19118453Sralph 				PCCM_ADDTYPE(PCCM_ADDTYPE(p2type(p -> type), PCCTM_FTN),
19218453Sralph 					PCCTM_PTR));
19312902Speter 			} else {
19412902Speter 				/* procedures are int returning functions */
19518453Sralph 			    putop( PCCOM_UNARY PCC_MUL ,
19618453Sralph 				PCCM_ADDTYPE(PCCM_ADDTYPE(PCCT_INT, PCCTM_FTN), PCCTM_PTR));
19712902Speter 			}
1981195Speter 			break;
1991195Speter 		default:
2001195Speter 			panic("call class");
201745Speter 	    }
2023065Smckusic 	    noarguments = TRUE;
203745Speter #	endif PC
204745Speter 	/*
205745Speter 	 * Loop and process each of
206745Speter 	 * arguments to the proc/func.
2073065Smckusic 	 *	... ( ... args ... ) ...
208745Speter 	 */
20915971Smckusick 	ptype = NIL;
21014727Sthien 	for (p1 = plist(p); p1 != NLNIL; p1 = p1->chain) {
21114727Sthien 	    if (argv_node == TR_NIL) {
2123297Smckusic 		    error("Not enough arguments to %s", p->symbol);
21314727Sthien 		    return (NLNIL);
2143297Smckusic 	    }
2153297Smckusic 	    switch (p1->class) {
2163297Smckusic 		case REF:
2173297Smckusic 			/*
2183297Smckusic 			 * Var parameter
2193297Smckusic 			 */
22014727Sthien 			rnode = argv_node->list_node.list;
22114727Sthien 			if (rnode != TR_NIL && rnode->tag != T_VAR) {
2223297Smckusic 				error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol);
2233361Speter 				chk = FALSE;
2243297Smckusic 				break;
2253297Smckusic 			}
22614727Sthien 			q = lvalue( argv_node->list_node.list,
22714727Sthien 					MOD | ASGN , LREQ );
2283297Smckusic 			if (q == NIL) {
2293297Smckusic 				chk = FALSE;
2303297Smckusic 				break;
2313297Smckusic 			}
23215971Smckusick 			p2 = p1->type;
23324050Smckusick 			if (p2 == NLNIL || p2->chain == NLNIL || p2->chain->class != CRANGE) {
23415971Smckusick 			    if (q != p2) {
2353297Smckusic 				error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol);
2363361Speter 				chk = FALSE;
23715971Smckusick 			    }
23815971Smckusick 			    break;
23915971Smckusick 			} else {
24015971Smckusick 			    /* conformant array */
24115971Smckusick 			    if (p1 == ptype) {
24215971Smckusick 				if (q != ctype) {
24315971Smckusick 				    error("Conformant array parameters in the same specification must be the same type.");
24415971Smckusick 				    goto conf_err;
24515971Smckusick 				}
24615971Smckusick 			    } else {
24715971Smckusick 				if (classify(q) != TARY && classify(q) != TSTR) {
24815971Smckusick 				    error("Array type required for var parameter %s of %s",p1->symbol,p->symbol);
24915971Smckusick 				    goto conf_err;
25015971Smckusick 				}
25115971Smckusick 				/* check base type of array */
25215971Smckusick 				if (p2->type != q->type) {
25315971Smckusick 				    error("Base type of array not identical to that of conformant array parameter %s of %s", p1->symbol, p->symbol);
25415971Smckusick 				    goto conf_err;
25515971Smckusick 				}
25615971Smckusick 				if (p2->value[0] != q->value[0]) {
25715971Smckusick 				    error("Subscript number mismatch on conformant array parameter %s of %s", p1->symbol, p->symbol);
25815971Smckusick 				    /* Don't process array bounds & width */
25915971Smckusick conf_err:			    if (p1->chain->type->class == CRANGE) {
26015971Smckusick 					d = p1->value[0];
26115971Smckusick 					for (i = 1; i <= d; i++) {
26215971Smckusick 					    /* for each subscript, pass by
26315971Smckusick 					     * bounds and width
26415971Smckusick 					     */
26515971Smckusick 					    p1 = p1->chain->chain->chain;
26615971Smckusick 					}
26715971Smckusick 				    }
26815971Smckusick 				    ptype = ctype = NLNIL;
26915971Smckusick 				    chk = FALSE;
27015971Smckusick 				    break;
27115971Smckusick 				}
27215971Smckusick 				/*
27315971Smckusick 				 * Save array type for all parameters with same
27415971Smckusick 				 * specification.
27515971Smckusick 				 */
27615971Smckusick 				ctype = q;
27715971Smckusick 				ptype = p2;
27815971Smckusick 				/*
27915971Smckusick 				 * If at end of conformant array list,
28015971Smckusick 				 * get bounds.
28115971Smckusick 				 */
28215971Smckusick 				if (p1->chain->type->class == CRANGE) {
28315971Smckusick 				    /* check each subscript, put on stack */
28415971Smckusick 				    d = ptype->value[0];
28515971Smckusick 				    q = ctype;
28615971Smckusick 				    for (i = 1; i <= d; i++) {
28715971Smckusick 					p1 = p1->chain;
28815971Smckusick 					q = q->chain;
28915971Smckusick 					if (incompat(q, p1->type, TR_NIL)){
29015971Smckusick 					    error("Subscript type not conformable with parameter %s of %s", p1->symbol, p->symbol);
29115971Smckusick 					    chk = FALSE;
29215971Smckusick 					    break;
29315971Smckusick 					}
29415971Smckusick 					/* Put lower and upper bound & width */
29515971Smckusick #					ifdef OBJ
29615971Smckusick 					if (q->type->class == CRANGE) {
29715971Smckusick 					    putcbnds(q->type);
29815971Smckusick 					} else {
29915971Smckusick 					    put(2, width(p1->type) <= 2 ? O_CON2
30015971Smckusick 						: O_CON4, q->range[0]);
30115971Smckusick 					    put(2, width(p1->type) <= 2 ? O_CON2
30215971Smckusick 						: O_CON4, q->range[1]);
30315971Smckusick 					    put(2, width(p1->type) <= 2 ? O_CON2
30415971Smckusick 						: O_CON4, aryconst(ctype,i));
30515971Smckusick 					}
30615971Smckusick #					endif OBJ
30715971Smckusick #					ifdef PC
30815971Smckusick 					if (q->type->class == CRANGE) {
30915971Smckusick 					    for (j = 1; j <= 3; j++) {
31015971Smckusick 						p2 = p->nptr[j];
31115971Smckusick 						putRV(p2->symbol, (p2->nl_block
31215971Smckusick 						    & 037), p2->value[0],
31315971Smckusick 						    p2->extra_flags,p2type(p2));
31418453Sralph 						putop(PCC_CM, PCCT_INT);
31515971Smckusick 					    }
31615971Smckusick 					} else {
31718453Sralph 					    putleaf(PCC_ICON, q->range[0], 0,PCCT_INT,0);
31818453Sralph 					    putop( PCC_CM , PCCT_INT );
31918453Sralph 					    putleaf(PCC_ICON, q->range[1], 0,PCCT_INT,0);
32018453Sralph 					    putop( PCC_CM , PCCT_INT );
32118453Sralph 					    putleaf(PCC_ICON,aryconst(ctype,i),0,PCCT_INT,0);
32218453Sralph 					    putop( PCC_CM , PCCT_INT );
32315971Smckusick 					}
32415971Smckusick #					endif PC
32515971Smckusick 					p1 = p1->chain->chain;
32615971Smckusick 				    }
32715971Smckusick 				}
32815971Smckusick 			    }
3293297Smckusic 			}
3303297Smckusic 			break;
3313297Smckusic 		case VAR:
3323297Smckusic 			/*
3333297Smckusic 			 * Value parameter
3343297Smckusic 			 */
335745Speter #			ifdef OBJ
33614727Sthien 			    q = rvalue(argv_node->list_node.list,
33714727Sthien 					p1->type , RREQ );
338745Speter #			endif OBJ
339745Speter #			ifdef PC
3403297Smckusic 				/*
3413297Smckusic 				 * structure arguments require lvalues,
3423297Smckusic 				 * scalars use rvalue.
3433297Smckusic 				 */
3443297Smckusic 			    switch( classify( p1 -> type ) ) {
3453297Smckusic 				case TFILE:
3463297Smckusic 				case TARY:
3473297Smckusic 				case TREC:
3483297Smckusic 				case TSET:
3493297Smckusic 				case TSTR:
35014727Sthien 				q = stkrval(argv_node->list_node.list,
35114727Sthien 						p1 -> type , (long) LREQ );
352745Speter 				    break;
3533297Smckusic 				case TINT:
3543297Smckusic 				case TSCAL:
3553297Smckusic 				case TBOOL:
3563297Smckusic 				case TCHAR:
3573297Smckusic 				    precheck( p1 -> type , "_RANG4" , "_RSNG4" );
35814727Sthien 				q = stkrval(argv_node->list_node.list,
35914727Sthien 						p1 -> type , (long) RREQ );
36010667Speter 				    postcheck(p1 -> type, nl+T4INT);
361745Speter 				    break;
36210365Smckusick 				case TDOUBLE:
36314727Sthien 				q = stkrval(argv_node->list_node.list,
36414727Sthien 						p1 -> type , (long) RREQ );
36518453Sralph 				    sconv(p2type(q), PCCT_DOUBLE);
36610365Smckusick 				    break;
3673297Smckusic 				default:
36814727Sthien 				    q = rvalue(argv_node->list_node.list,
36914727Sthien 						p1 -> type , RREQ );
3703297Smckusic 				    break;
371745Speter 			    }
3723297Smckusic #			endif PC
3733297Smckusic 			if (q == NIL) {
3743297Smckusic 				chk = FALSE;
3753297Smckusic 				break;
3763297Smckusic 			}
37714727Sthien 			if (incompat(q, p1->type,
37814727Sthien 				argv_node->list_node.list)) {
3793297Smckusic 				cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol);
3803361Speter 				chk = FALSE;
3813297Smckusic 				break;
3823297Smckusic 			}
383745Speter #			ifdef OBJ
3843297Smckusic 			    if (isa(p1->type, "bcsi"))
3853297Smckusic 				    rangechk(p1->type, q);
3863297Smckusic 			    if (q->class != STR)
3873297Smckusic 				    convert(q, p1->type);
388745Speter #			endif OBJ
389745Speter #			ifdef PC
3903297Smckusic 			    switch( classify( p1 -> type ) ) {
3913297Smckusic 				case TFILE:
3923297Smckusic 				case TARY:
3933297Smckusic 				case TREC:
3943297Smckusic 				case TSET:
3953297Smckusic 				case TSTR:
39618453Sralph 					putstrop( PCC_STARG
3973297Smckusic 					    , p2type( p1 -> type )
39814727Sthien 					    , (int) lwidth( p1 -> type )
3993297Smckusic 					    , align( p1 -> type ) );
4003297Smckusic 			    }
4011195Speter #			endif PC
4023297Smckusic 			break;
4033297Smckusic 		case FFUNC:
4041195Speter 			/*
4053297Smckusic 			 * function parameter
4061195Speter 			 */
40714727Sthien 			q = flvalue(argv_node->list_node.list, p1 );
40814727Sthien 			/*chk = (chk && fcompat(q, p1));*/
40914727Sthien 			if ((chk) && (fcompat(q, p1)))
41014727Sthien 			    chk = TRUE;
41114727Sthien 			else
41214727Sthien 			    chk = FALSE;
4133297Smckusic 			break;
4143297Smckusic 		case FPROC:
4151195Speter 			/*
4163297Smckusic 			 * procedure parameter
4171195Speter 			 */
41814727Sthien 			q = flvalue(argv_node->list_node.list, p1 );
41914727Sthien 			/* chk = (chk && fcompat(q, p1)); */
42014727Sthien 			if ((chk) && (fcompat(q, p1)))
42114727Sthien 			    chk = TRUE;
42214727Sthien 			else chk = FALSE;
4233297Smckusic 			break;
4243297Smckusic 		default:
4253297Smckusic 			panic("call");
4261195Speter 	    }
4273297Smckusic #	    ifdef PC
4283297Smckusic 		    /*
4293297Smckusic 		     *	if this is the nth (>1) argument,
4303297Smckusic 		     *	hang it on the left linear list of arguments
4313297Smckusic 		     */
4323297Smckusic 		if ( noarguments ) {
4333297Smckusic 			noarguments = FALSE;
4343297Smckusic 		} else {
43518453Sralph 			putop( PCC_CM , PCCT_INT );
4363297Smckusic 		}
4373297Smckusic #	    endif PC
43814727Sthien 	    argv_node = argv_node->list_node.next;
439745Speter 	}
44014727Sthien 	if (argv_node != TR_NIL) {
4413297Smckusic 		error("Too many arguments to %s", p->symbol);
44214727Sthien 		rvlist(argv_node);
44314727Sthien 		return (NLNIL);
4443297Smckusic 	}
4453297Smckusic 	if (chk == FALSE)
44614727Sthien 		return NLNIL;
447745Speter #	ifdef OBJ
4481195Speter 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
44914727Sthien 		(void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]);
45014727Sthien  		(void) put(2, O_LV | cbn << 8 + INDX ,
4514014Smckusic  			(int) savedispnp -> value[ NL_OFFS ] );
45214727Sthien 		(void) put(1, O_FCALL);
45330037Smckusick 		(void) put(2, O_FRTN, roundup(width(p->type), (long) A_STACK));
4541195Speter 	    } else {
45514727Sthien 		(void) put(2, O_CALL | psbn << 8, (long)p->value[NL_ENTLOC]);
4561195Speter 	    }
457745Speter #	endif OBJ
458745Speter #	ifdef PC
4593065Smckusic 		/*
4603426Speter 		 *	for formal calls: add the hidden argument
4613426Speter 		 *	which is the formal struct describing the
4623426Speter 		 *	environment of the routine.
4633426Speter 		 *	and the argument which is the address of the
4643426Speter 		 *	space into which to save the display.
4653426Speter 		 */
4663426Speter 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
46714727Sthien 		putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] ,
46818453Sralph 			tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY );
4693426Speter 		if ( !noarguments ) {
47018453Sralph 		    putop( PCC_CM , PCCT_INT );
4713426Speter 		}
4723426Speter 		noarguments = FALSE;
47314727Sthien  		putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] ,
47418453Sralph  			savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY );
47518453Sralph  		putop( PCC_CM , PCCT_INT );
4763426Speter 	    }
4773426Speter 		/*
4783065Smckusic 		 *	do the actual call:
4793065Smckusic 		 *	    either	... p( ... ) ...
4803886Speter 		 *	    or		... ( t -> entryaddr )( ... ) ...
4813065Smckusic 		 *	and maybe an assignment.
4823065Smckusic 		 */
483745Speter 	    if ( porf == FUNC ) {
4843065Smckusic 		switch ( p_type_class ) {
485745Speter 		    case TBOOL:
486745Speter 		    case TCHAR:
487745Speter 		    case TINT:
488745Speter 		    case TSCAL:
489745Speter 		    case TDOUBLE:
490745Speter 		    case TPTR:
49118453Sralph 			putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) ,
49214727Sthien 				(int) p_type_p2type );
4933065Smckusic 			if ( p -> class == FFUNC ) {
49418453Sralph 			    putop( PCC_ASSIGN , (int) p_type_p2type );
495745Speter 			}
496745Speter 			break;
497745Speter 		    default:
49818453Sralph 			putstrop( ( noarguments ? PCCOM_UNARY PCC_STCALL : PCC_STCALL ),
49918453Sralph 				(int) PCCM_ADDTYPE( p_type_p2type , PCCTM_PTR ) ,
50014727Sthien 				(int) p_type_width ,(int) p_type_align );
50118453Sralph 			putstrop(PCC_STASG, (int) PCCM_ADDTYPE(p_type_p2type, PCCTM_PTR),
50214727Sthien 				(int) lwidth(p -> type), align(p -> type));
503745Speter 			break;
504745Speter 		}
505745Speter 	    } else {
50618453Sralph 		putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , PCCT_INT );
5073065Smckusic 	    }
5083065Smckusic 		/*
5093886Speter 		 *	( t=p , ... , FRTN( t ) ...
5103065Smckusic 		 */
5113065Smckusic 	    if ( p -> class == FFUNC || p -> class == FPROC ) {
51218453Sralph 		putop( PCC_COMOP , PCCT_INT );
51318453Sralph 		putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) ,
5143065Smckusic 			"_FRTN" );
51514727Sthien 		putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] ,
51618453Sralph 			tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY );
51714727Sthien  		putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] ,
51818453Sralph  			savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY );
51918453Sralph  		putop( PCC_CM , PCCT_INT );
52018453Sralph 		putop( PCC_CALL , PCCT_INT );
52118453Sralph 		putop( PCC_COMOP , PCCT_INT );
5223065Smckusic 	    }
5233065Smckusic 		/*
5243065Smckusic 		 *	if required:
5253065Smckusic 		 *	either	... , temp )
5263065Smckusic 		 *	or	... , &temp )
5273065Smckusic 		 */
52818453Sralph 	    if ( porf == FUNC && temptype != PCCT_UNDEF ) {
52918453Sralph 		if ( temptype != PCCT_STRTY ) {
53014727Sthien 		    putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
53114727Sthien 			    tempnlp -> extra_flags , (int) p_type_p2type );
532745Speter 		} else {
53314727Sthien 		    putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] ,
53414727Sthien 			    tempnlp -> extra_flags , (int) p_type_p2type );
535745Speter 		}
53618453Sralph 		putop( PCC_COMOP , PCCT_INT );
5373065Smckusic 	    }
5383065Smckusic 	    if ( porf == PROC ) {
539745Speter 		putdot( filename , line );
540745Speter 	    }
541745Speter #	endif PC
542745Speter 	return (p->type);
543745Speter }
544745Speter 
rvlist(al)545745Speter rvlist(al)
54614727Sthien 	register struct tnode *al;
547745Speter {
548745Speter 
54914727Sthien 	for (; al != TR_NIL; al = al->list_node.next)
55014727Sthien 		(void) rvalue( al->list_node.list, NLNIL , RREQ );
551745Speter }
5523297Smckusic 
5533297Smckusic     /*
5543297Smckusic      *	check that two function/procedure namelist entries are compatible
5553297Smckusic      */
5563297Smckusic bool
fcompat(formal,actual)5573297Smckusic fcompat( formal , actual )
5583297Smckusic     struct nl	*formal;
5593297Smckusic     struct nl	*actual;
5603297Smckusic {
5613297Smckusic     register struct nl	*f_chain;
5623297Smckusic     register struct nl	*a_chain;
56314727Sthien     extern struct nl	*plist();
5643297Smckusic     bool compat = TRUE;
5653297Smckusic 
56614727Sthien     if ( formal == NLNIL || actual == NLNIL ) {
5673297Smckusic 	return FALSE;
5683297Smckusic     }
5693297Smckusic     for (a_chain = plist(actual), f_chain = plist(formal);
57014727Sthien          f_chain != NLNIL;
5713297Smckusic 	 f_chain = f_chain->chain, a_chain = a_chain->chain) {
5723297Smckusic 	if (a_chain == NIL) {
5733297Smckusic 	    error("%s %s declared on line %d has more arguments than",
5743297Smckusic 		parnam(formal->class), formal->symbol,
57514727Sthien 		(char *) linenum(formal));
5763297Smckusic 	    cerror("%s %s declared on line %d",
5773297Smckusic 		parnam(actual->class), actual->symbol,
57814727Sthien 		(char *) linenum(actual));
5793297Smckusic 	    return FALSE;
5803297Smckusic 	}
5813297Smckusic 	if ( a_chain -> class != f_chain -> class ) {
5823297Smckusic 	    error("%s parameter %s of %s declared on line %d is not identical",
5833297Smckusic 		parnam(f_chain->class), f_chain->symbol,
58414727Sthien 		formal->symbol, (char *) linenum(formal));
5853297Smckusic 	    cerror("with %s parameter %s of %s declared on line %d",
5863297Smckusic 		parnam(a_chain->class), a_chain->symbol,
58714727Sthien 		actual->symbol, (char *) linenum(actual));
5883297Smckusic 	    compat = FALSE;
5893297Smckusic 	} else if (a_chain->class == FFUNC || a_chain->class == FPROC) {
59014727Sthien 	    /*compat = (compat && fcompat(f_chain, a_chain));*/
59114727Sthien 	    if ((compat) && (fcompat(f_chain, a_chain)))
59214727Sthien 		compat = TRUE;
59314727Sthien 	    else compat = FALSE;
5943297Smckusic 	}
5953297Smckusic 	if ((a_chain->class != FPROC && f_chain->class != FPROC) &&
5963297Smckusic 	    (a_chain->type != f_chain->type)) {
5973297Smckusic 	    error("Type of %s parameter %s of %s declared on line %d is not identical",
5983297Smckusic 		parnam(f_chain->class), f_chain->symbol,
59914727Sthien 		formal->symbol, (char *) linenum(formal));
6003297Smckusic 	    cerror("to type of %s parameter %s of %s declared on line %d",
6013297Smckusic 		parnam(a_chain->class), a_chain->symbol,
60214727Sthien 		actual->symbol, (char *) linenum(actual));
6033297Smckusic 	    compat = FALSE;
6043297Smckusic 	}
6053297Smckusic     }
6063297Smckusic     if (a_chain != NIL) {
6073297Smckusic 	error("%s %s declared on line %d has fewer arguments than",
6083297Smckusic 	    parnam(formal->class), formal->symbol,
60914727Sthien 	    (char *) linenum(formal));
6103297Smckusic 	cerror("%s %s declared on line %d",
6113297Smckusic 	    parnam(actual->class), actual->symbol,
61214727Sthien 	    (char *) linenum(actual));
6133297Smckusic 	return FALSE;
6143297Smckusic     }
6153297Smckusic     return compat;
6163297Smckusic }
6173297Smckusic 
6183297Smckusic char *
parnam(nltype)6193297Smckusic parnam(nltype)
6203297Smckusic     int nltype;
6213297Smckusic {
6223297Smckusic     switch(nltype) {
6233297Smckusic 	case REF:
6243297Smckusic 	    return "var";
6253297Smckusic 	case VAR:
6263297Smckusic 	    return "value";
6273297Smckusic 	case FUNC:
6283297Smckusic 	case FFUNC:
6293297Smckusic 	    return "function";
6303297Smckusic 	case PROC:
6313297Smckusic 	case FPROC:
6323297Smckusic 	    return "procedure";
6333297Smckusic 	default:
6343297Smckusic 	    return "SNARK";
6353297Smckusic     }
6363297Smckusic }
6373297Smckusic 
plist(p)63814727Sthien struct nl *plist(p)
6393297Smckusic     struct nl *p;
6403297Smckusic {
6413297Smckusic     switch (p->class) {
6423297Smckusic 	case FFUNC:
6433297Smckusic 	case FPROC:
6443297Smckusic 	    return p->ptr[ NL_FCHAIN ];
6453297Smckusic 	case PROC:
6463297Smckusic 	case FUNC:
6473297Smckusic 	    return p->chain;
6483297Smckusic 	default:
64914727Sthien 	    {
65014727Sthien 		panic("plist");
65114727Sthien 		return(NLNIL); /* this is here only so lint won't complain
65214727Sthien 				  panic actually aborts */
65314727Sthien 	    }
65414727Sthien 
6553297Smckusic     }
6563297Smckusic }
6573297Smckusic 
6583297Smckusic linenum(p)
6593297Smckusic     struct nl *p;
6603297Smckusic {
6613297Smckusic     if (p->class == FUNC)
6623297Smckusic 	return p->ptr[NL_FVAR]->value[NL_LINENO];
6633297Smckusic     return p->value[NL_LINENO];
6643297Smckusic }
665