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