1745Speter /* Copyright (c) 1979 Regents of the University of California */ 2745Speter 314727Sthien #ifndef lint 4*18453Sralph static char sccsid[] = "@(#)call.c 2.2 03/20/85"; 514727Sthien #endif 6745Speter 7745Speter #include "whoami.h" 8745Speter #include "0.h" 9745Speter #include "tree.h" 10745Speter #include "opcode.h" 11745Speter #include "objfmt.h" 12745Speter #ifdef PC 13745Speter # include "pc.h" 14*18453Sralph # include <pcc.h> 15745Speter #endif PC 1611331Speter #include "tmps.h" 1714727Sthien #include "tree_ty.h" 18745Speter 19745Speter /* 20745Speter * Call generates code for calls to 21745Speter * user defined procedures and functions 22745Speter * and is called by proc and funccod. 23745Speter * P is the result of the lookup 24745Speter * of the procedure/function symbol, 25745Speter * and porf is PROC or FUNC. 26745Speter * Psbn is the block number of p. 273065Smckusic * 283065Smckusic * the idea here is that regular scalar functions are just called, 293065Smckusic * while structure functions and formal functions have their results 303065Smckusic * stored in a temporary after the call. 313065Smckusic * structure functions do this because they return pointers 323065Smckusic * to static results, so we copy the static 333065Smckusic * and return a pointer to the copy. 343065Smckusic * formal functions do this because we have to save the result 353065Smckusic * around a call to the runtime routine which restores the display, 363065Smckusic * so we can't just leave the result lying around in registers. 373886Speter * formal calls save the address of the descriptor in a local 383886Speter * temporary, so it can be addressed for the call which restores 393886Speter * the display (FRTN). 403426Speter * calls to formal parameters pass the formal as a hidden argument 413426Speter * to a special entry point for the formal call. 423426Speter * [this is somewhat dependent on the way arguments are addressed.] 433065Smckusic * so PROCs and scalar FUNCs look like 443065Smckusic * p(...args...) 453065Smckusic * structure FUNCs look like 463065Smckusic * (temp = p(...args...),&temp) 473065Smckusic * formal FPROCs look like 484014Smckusic * ( t=p,( t -> entryaddr )(...args...,t,s),FRTN(t,s)) 493065Smckusic * formal scalar FFUNCs look like 504014Smckusic * ( t=p,temp=( t -> entryaddr )(...args...,t,s),FRTN(t,s),temp) 513065Smckusic * formal structure FFUNCs look like 524014Smckusic * (t=p,temp = ( t -> entryaddr )(...args...,t,s),FRTN(t,s),&temp) 53745Speter */ 54745Speter struct nl * 5514727Sthien call(p, argv_node, porf, psbn) 56745Speter struct nl *p; 5714727Sthien struct tnode *argv_node; /* list node */ 5814727Sthien int porf, psbn; 59745Speter { 6015971Smckusick register struct nl *p1, *q, *p2; 6115971Smckusick register struct nl *ptype, *ctype; 6214727Sthien struct tnode *rnode; 6315971Smckusick int i, j, d; 643297Smckusic bool chk = TRUE; 654014Smckusic struct nl *savedispnp; /* temporary to hold saved display */ 66745Speter # ifdef PC 6714727Sthien int p_type_class = classify( p -> type ); 683065Smckusic long p_type_p2type = p2type( p -> type ); 693065Smckusic bool noarguments; 703065Smckusic /* 713065Smckusic * these get used if temporaries and structures are used 723065Smckusic */ 733824Speter struct nl *tempnlp; 743065Smckusic long temptype; /* type of the temporary */ 753065Smckusic long p_type_width; 763065Smckusic long p_type_align; 773362Speter char extname[ BUFSIZ ]; 783886Speter struct nl *tempdescrp; 79745Speter # endif PC 80745Speter 814014Smckusic if (p->class == FFUNC || p->class == FPROC) { 824014Smckusic /* 834014Smckusic * allocate space to save the display for formal calls 844014Smckusic */ 8514727Sthien savedispnp = tmpalloc( (long) sizeof display , NLNIL , NOREG ); 864014Smckusic } 87745Speter # ifdef OBJ 883426Speter if (p->class == FFUNC || p->class == FPROC) { 8914727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 904014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 9114727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 923426Speter } 933426Speter if (porf == FUNC) { 94745Speter /* 95745Speter * Push some space 96745Speter * for the function return type 97745Speter */ 9814727Sthien (void) put(2, O_PUSH, leven(-lwidth(p->type))); 993426Speter } 100745Speter # endif OBJ 101745Speter # ifdef PC 1023065Smckusic /* 1033886Speter * if this is a formal call, 1043886Speter * stash the address of the descriptor 1053886Speter * in a temporary so we can find it 1063886Speter * after the FCALL for the call to FRTN 1073886Speter */ 1083886Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 10914727Sthien tempdescrp = tmpalloc((long) (sizeof( struct formalrtn *)), 11014727Sthien NLNIL, REGOK ); 11114727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 112*18453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 11314727Sthien putRV((char *) 0 , psbn , p -> value[ NL_OFFS ] , 114*18453Sralph p -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 115*18453Sralph putop( PCC_ASSIGN , PCCTM_PTR | PCCT_STRTY ); 1163886Speter } 1173886Speter /* 1183065Smckusic * if we have to store a temporary, 1193065Smckusic * temptype will be its type, 120*18453Sralph * otherwise, it's PCCT_UNDEF. 1213065Smckusic */ 122*18453Sralph temptype = PCCT_UNDEF; 123745Speter if ( porf == FUNC ) { 1243065Smckusic p_type_width = width( p -> type ); 1253065Smckusic switch( p_type_class ) { 126745Speter case TSTR: 127745Speter case TSET: 128745Speter case TREC: 129745Speter case TFILE: 130745Speter case TARY: 131*18453Sralph temptype = PCCT_STRTY; 1323065Smckusic p_type_align = align( p -> type ); 1333065Smckusic break; 1343065Smckusic default: 1353065Smckusic if ( p -> class == FFUNC ) { 13614727Sthien temptype = p2type( p -> type ); 137745Speter } 1383065Smckusic break; 139745Speter } 140*18453Sralph if ( temptype != PCCT_UNDEF ) { 1413824Speter tempnlp = tmpalloc(p_type_width, p -> type, NOREG); 1423065Smckusic /* 1433065Smckusic * temp 1443065Smckusic * for (temp = ... 1453065Smckusic */ 14614727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 14714727Sthien tempnlp -> extra_flags , (int) temptype ); 1483065Smckusic } 149745Speter } 1501195Speter switch ( p -> class ) { 1511195Speter case FUNC: 1521195Speter case PROC: 1533065Smckusic /* 1543065Smckusic * ... p( ... 1553065Smckusic */ 1563372Speter sextname( extname , p -> symbol , BLOCKNO(p -> nl_block) ); 157*18453Sralph putleaf( PCC_ICON , 0 , 0 , p2type( p ) , extname ); 1581195Speter break; 1591195Speter case FFUNC: 1601195Speter case FPROC: 1613886Speter 1621195Speter /* 1633886Speter * ... ( t -> entryaddr )( ... 1641195Speter */ 16512902Speter /* the descriptor */ 16614727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 167*18453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 16812902Speter /* the entry address within the descriptor */ 1693426Speter if ( FENTRYOFFSET != 0 ) { 170*18453Sralph putleaf( PCC_ICON , FENTRYOFFSET , 0 , PCCT_INT , 17114727Sthien (char *) 0 ); 172*18453Sralph putop( PCC_PLUS , 173*18453Sralph PCCM_ADDTYPE( 174*18453Sralph PCCM_ADDTYPE( PCCM_ADDTYPE( p2type( p ) , PCCTM_FTN ) , 175*18453Sralph PCCTM_PTR ) , 176*18453Sralph PCCTM_PTR ) ); 1773426Speter } 17812902Speter /* 17912902Speter * indirect to fetch the formal entry address 18012902Speter * with the result type of the routine. 18112902Speter */ 18212902Speter if (p -> class == FFUNC) { 183*18453Sralph putop( PCCOM_UNARY PCC_MUL , 184*18453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(p2type(p -> type), PCCTM_FTN), 185*18453Sralph PCCTM_PTR)); 18612902Speter } else { 18712902Speter /* procedures are int returning functions */ 188*18453Sralph putop( PCCOM_UNARY PCC_MUL , 189*18453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(PCCT_INT, PCCTM_FTN), PCCTM_PTR)); 19012902Speter } 1911195Speter break; 1921195Speter default: 1931195Speter panic("call class"); 194745Speter } 1953065Smckusic noarguments = TRUE; 196745Speter # endif PC 197745Speter /* 198745Speter * Loop and process each of 199745Speter * arguments to the proc/func. 2003065Smckusic * ... ( ... args ... ) ... 201745Speter */ 20215971Smckusick ptype = NIL; 20314727Sthien for (p1 = plist(p); p1 != NLNIL; p1 = p1->chain) { 20414727Sthien if (argv_node == TR_NIL) { 2053297Smckusic error("Not enough arguments to %s", p->symbol); 20614727Sthien return (NLNIL); 2073297Smckusic } 2083297Smckusic switch (p1->class) { 2093297Smckusic case REF: 2103297Smckusic /* 2113297Smckusic * Var parameter 2123297Smckusic */ 21314727Sthien rnode = argv_node->list_node.list; 21414727Sthien if (rnode != TR_NIL && rnode->tag != T_VAR) { 2153297Smckusic error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 2163361Speter chk = FALSE; 2173297Smckusic break; 2183297Smckusic } 21914727Sthien q = lvalue( argv_node->list_node.list, 22014727Sthien MOD | ASGN , LREQ ); 2213297Smckusic if (q == NIL) { 2223297Smckusic chk = FALSE; 2233297Smckusic break; 2243297Smckusic } 22515971Smckusick p2 = p1->type; 22615971Smckusick if (p2->chain->class != CRANGE) { 22715971Smckusick if (q != p2) { 2283297Smckusic error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 2293361Speter chk = FALSE; 23015971Smckusick } 23115971Smckusick break; 23215971Smckusick } else { 23315971Smckusick /* conformant array */ 23415971Smckusick if (p1 == ptype) { 23515971Smckusick if (q != ctype) { 23615971Smckusick error("Conformant array parameters in the same specification must be the same type."); 23715971Smckusick goto conf_err; 23815971Smckusick } 23915971Smckusick } else { 24015971Smckusick if (classify(q) != TARY && classify(q) != TSTR) { 24115971Smckusick error("Array type required for var parameter %s of %s",p1->symbol,p->symbol); 24215971Smckusick goto conf_err; 24315971Smckusick } 24415971Smckusick /* check base type of array */ 24515971Smckusick if (p2->type != q->type) { 24615971Smckusick error("Base type of array not identical to that of conformant array parameter %s of %s", p1->symbol, p->symbol); 24715971Smckusick goto conf_err; 24815971Smckusick } 24915971Smckusick if (p2->value[0] != q->value[0]) { 25015971Smckusick error("Subscript number mismatch on conformant array parameter %s of %s", p1->symbol, p->symbol); 25115971Smckusick /* Don't process array bounds & width */ 25215971Smckusick conf_err: if (p1->chain->type->class == CRANGE) { 25315971Smckusick d = p1->value[0]; 25415971Smckusick for (i = 1; i <= d; i++) { 25515971Smckusick /* for each subscript, pass by 25615971Smckusick * bounds and width 25715971Smckusick */ 25815971Smckusick p1 = p1->chain->chain->chain; 25915971Smckusick } 26015971Smckusick } 26115971Smckusick ptype = ctype = NLNIL; 26215971Smckusick chk = FALSE; 26315971Smckusick break; 26415971Smckusick } 26515971Smckusick /* 26615971Smckusick * Save array type for all parameters with same 26715971Smckusick * specification. 26815971Smckusick */ 26915971Smckusick ctype = q; 27015971Smckusick ptype = p2; 27115971Smckusick /* 27215971Smckusick * If at end of conformant array list, 27315971Smckusick * get bounds. 27415971Smckusick */ 27515971Smckusick if (p1->chain->type->class == CRANGE) { 27615971Smckusick /* check each subscript, put on stack */ 27715971Smckusick d = ptype->value[0]; 27815971Smckusick q = ctype; 27915971Smckusick for (i = 1; i <= d; i++) { 28015971Smckusick p1 = p1->chain; 28115971Smckusick q = q->chain; 28215971Smckusick if (incompat(q, p1->type, TR_NIL)){ 28315971Smckusick error("Subscript type not conformable with parameter %s of %s", p1->symbol, p->symbol); 28415971Smckusick chk = FALSE; 28515971Smckusick break; 28615971Smckusick } 28715971Smckusick /* Put lower and upper bound & width */ 28815971Smckusick # ifdef OBJ 28915971Smckusick if (q->type->class == CRANGE) { 29015971Smckusick putcbnds(q->type); 29115971Smckusick } else { 29215971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29315971Smckusick : O_CON4, q->range[0]); 29415971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29515971Smckusick : O_CON4, q->range[1]); 29615971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29715971Smckusick : O_CON4, aryconst(ctype,i)); 29815971Smckusick } 29915971Smckusick # endif OBJ 30015971Smckusick # ifdef PC 30115971Smckusick if (q->type->class == CRANGE) { 30215971Smckusick for (j = 1; j <= 3; j++) { 30315971Smckusick p2 = p->nptr[j]; 30415971Smckusick putRV(p2->symbol, (p2->nl_block 30515971Smckusick & 037), p2->value[0], 30615971Smckusick p2->extra_flags,p2type(p2)); 307*18453Sralph putop(PCC_CM, PCCT_INT); 30815971Smckusick } 30915971Smckusick } else { 310*18453Sralph putleaf(PCC_ICON, q->range[0], 0,PCCT_INT,0); 311*18453Sralph putop( PCC_CM , PCCT_INT ); 312*18453Sralph putleaf(PCC_ICON, q->range[1], 0,PCCT_INT,0); 313*18453Sralph putop( PCC_CM , PCCT_INT ); 314*18453Sralph putleaf(PCC_ICON,aryconst(ctype,i),0,PCCT_INT,0); 315*18453Sralph putop( PCC_CM , PCCT_INT ); 31615971Smckusick } 31715971Smckusick # endif PC 31815971Smckusick p1 = p1->chain->chain; 31915971Smckusick } 32015971Smckusick } 32115971Smckusick } 3223297Smckusic } 3233297Smckusic break; 3243297Smckusic case VAR: 3253297Smckusic /* 3263297Smckusic * Value parameter 3273297Smckusic */ 328745Speter # ifdef OBJ 32914727Sthien q = rvalue(argv_node->list_node.list, 33014727Sthien p1->type , RREQ ); 331745Speter # endif OBJ 332745Speter # ifdef PC 3333297Smckusic /* 3343297Smckusic * structure arguments require lvalues, 3353297Smckusic * scalars use rvalue. 3363297Smckusic */ 3373297Smckusic switch( classify( p1 -> type ) ) { 3383297Smckusic case TFILE: 3393297Smckusic case TARY: 3403297Smckusic case TREC: 3413297Smckusic case TSET: 3423297Smckusic case TSTR: 34314727Sthien q = stkrval(argv_node->list_node.list, 34414727Sthien p1 -> type , (long) LREQ ); 345745Speter break; 3463297Smckusic case TINT: 3473297Smckusic case TSCAL: 3483297Smckusic case TBOOL: 3493297Smckusic case TCHAR: 3503297Smckusic precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 35114727Sthien q = stkrval(argv_node->list_node.list, 35214727Sthien p1 -> type , (long) RREQ ); 35310667Speter postcheck(p1 -> type, nl+T4INT); 354745Speter break; 35510365Smckusick case TDOUBLE: 35614727Sthien q = stkrval(argv_node->list_node.list, 35714727Sthien p1 -> type , (long) RREQ ); 358*18453Sralph sconv(p2type(q), PCCT_DOUBLE); 35910365Smckusick break; 3603297Smckusic default: 36114727Sthien q = rvalue(argv_node->list_node.list, 36214727Sthien p1 -> type , RREQ ); 3633297Smckusic break; 364745Speter } 3653297Smckusic # endif PC 3663297Smckusic if (q == NIL) { 3673297Smckusic chk = FALSE; 3683297Smckusic break; 3693297Smckusic } 37014727Sthien if (incompat(q, p1->type, 37114727Sthien argv_node->list_node.list)) { 3723297Smckusic cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 3733361Speter chk = FALSE; 3743297Smckusic break; 3753297Smckusic } 376745Speter # ifdef OBJ 3773297Smckusic if (isa(p1->type, "bcsi")) 3783297Smckusic rangechk(p1->type, q); 3793297Smckusic if (q->class != STR) 3803297Smckusic convert(q, p1->type); 381745Speter # endif OBJ 382745Speter # ifdef PC 3833297Smckusic switch( classify( p1 -> type ) ) { 3843297Smckusic case TFILE: 3853297Smckusic case TARY: 3863297Smckusic case TREC: 3873297Smckusic case TSET: 3883297Smckusic case TSTR: 389*18453Sralph putstrop( PCC_STARG 3903297Smckusic , p2type( p1 -> type ) 39114727Sthien , (int) lwidth( p1 -> type ) 3923297Smckusic , align( p1 -> type ) ); 3933297Smckusic } 3941195Speter # endif PC 3953297Smckusic break; 3963297Smckusic case FFUNC: 3971195Speter /* 3983297Smckusic * function parameter 3991195Speter */ 40014727Sthien q = flvalue(argv_node->list_node.list, p1 ); 40114727Sthien /*chk = (chk && fcompat(q, p1));*/ 40214727Sthien if ((chk) && (fcompat(q, p1))) 40314727Sthien chk = TRUE; 40414727Sthien else 40514727Sthien chk = FALSE; 4063297Smckusic break; 4073297Smckusic case FPROC: 4081195Speter /* 4093297Smckusic * procedure parameter 4101195Speter */ 41114727Sthien q = flvalue(argv_node->list_node.list, p1 ); 41214727Sthien /* chk = (chk && fcompat(q, p1)); */ 41314727Sthien if ((chk) && (fcompat(q, p1))) 41414727Sthien chk = TRUE; 41514727Sthien else chk = FALSE; 4163297Smckusic break; 4173297Smckusic default: 4183297Smckusic panic("call"); 4191195Speter } 4203297Smckusic # ifdef PC 4213297Smckusic /* 4223297Smckusic * if this is the nth (>1) argument, 4233297Smckusic * hang it on the left linear list of arguments 4243297Smckusic */ 4253297Smckusic if ( noarguments ) { 4263297Smckusic noarguments = FALSE; 4273297Smckusic } else { 428*18453Sralph putop( PCC_CM , PCCT_INT ); 4293297Smckusic } 4303297Smckusic # endif PC 43114727Sthien argv_node = argv_node->list_node.next; 432745Speter } 43314727Sthien if (argv_node != TR_NIL) { 4343297Smckusic error("Too many arguments to %s", p->symbol); 43514727Sthien rvlist(argv_node); 43614727Sthien return (NLNIL); 4373297Smckusic } 4383297Smckusic if (chk == FALSE) 43914727Sthien return NLNIL; 440745Speter # ifdef OBJ 4411195Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 44214727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 44314727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 4444014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 44514727Sthien (void) put(1, O_FCALL); 44614727Sthien (void) put(2, O_FRTN, even(width(p->type))); 4471195Speter } else { 44814727Sthien (void) put(2, O_CALL | psbn << 8, (long)p->value[NL_ENTLOC]); 4491195Speter } 450745Speter # endif OBJ 451745Speter # ifdef PC 4523065Smckusic /* 4533426Speter * for formal calls: add the hidden argument 4543426Speter * which is the formal struct describing the 4553426Speter * environment of the routine. 4563426Speter * and the argument which is the address of the 4573426Speter * space into which to save the display. 4583426Speter */ 4593426Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 46014727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 461*18453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 4623426Speter if ( !noarguments ) { 463*18453Sralph putop( PCC_CM , PCCT_INT ); 4643426Speter } 4653426Speter noarguments = FALSE; 46614727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 467*18453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 468*18453Sralph putop( PCC_CM , PCCT_INT ); 4693426Speter } 4703426Speter /* 4713065Smckusic * do the actual call: 4723065Smckusic * either ... p( ... ) ... 4733886Speter * or ... ( t -> entryaddr )( ... ) ... 4743065Smckusic * and maybe an assignment. 4753065Smckusic */ 476745Speter if ( porf == FUNC ) { 4773065Smckusic switch ( p_type_class ) { 478745Speter case TBOOL: 479745Speter case TCHAR: 480745Speter case TINT: 481745Speter case TSCAL: 482745Speter case TDOUBLE: 483745Speter case TPTR: 484*18453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , 48514727Sthien (int) p_type_p2type ); 4863065Smckusic if ( p -> class == FFUNC ) { 487*18453Sralph putop( PCC_ASSIGN , (int) p_type_p2type ); 488745Speter } 489745Speter break; 490745Speter default: 491*18453Sralph putstrop( ( noarguments ? PCCOM_UNARY PCC_STCALL : PCC_STCALL ), 492*18453Sralph (int) PCCM_ADDTYPE( p_type_p2type , PCCTM_PTR ) , 49314727Sthien (int) p_type_width ,(int) p_type_align ); 494*18453Sralph putstrop(PCC_STASG, (int) PCCM_ADDTYPE(p_type_p2type, PCCTM_PTR), 49514727Sthien (int) lwidth(p -> type), align(p -> type)); 496745Speter break; 497745Speter } 498745Speter } else { 499*18453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , PCCT_INT ); 5003065Smckusic } 5013065Smckusic /* 5023886Speter * ( t=p , ... , FRTN( t ) ... 5033065Smckusic */ 5043065Smckusic if ( p -> class == FFUNC || p -> class == FPROC ) { 505*18453Sralph putop( PCC_COMOP , PCCT_INT ); 506*18453Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , 5073065Smckusic "_FRTN" ); 50814727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 509*18453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 51014727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 511*18453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 512*18453Sralph putop( PCC_CM , PCCT_INT ); 513*18453Sralph putop( PCC_CALL , PCCT_INT ); 514*18453Sralph putop( PCC_COMOP , PCCT_INT ); 5153065Smckusic } 5163065Smckusic /* 5173065Smckusic * if required: 5183065Smckusic * either ... , temp ) 5193065Smckusic * or ... , &temp ) 5203065Smckusic */ 521*18453Sralph if ( porf == FUNC && temptype != PCCT_UNDEF ) { 522*18453Sralph if ( temptype != PCCT_STRTY ) { 52314727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 52414727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 525745Speter } else { 52614727Sthien putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 52714727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 528745Speter } 529*18453Sralph putop( PCC_COMOP , PCCT_INT ); 5303065Smckusic } 5313065Smckusic if ( porf == PROC ) { 532745Speter putdot( filename , line ); 533745Speter } 534745Speter # endif PC 535745Speter return (p->type); 536745Speter } 537745Speter 538745Speter rvlist(al) 53914727Sthien register struct tnode *al; 540745Speter { 541745Speter 54214727Sthien for (; al != TR_NIL; al = al->list_node.next) 54314727Sthien (void) rvalue( al->list_node.list, NLNIL , RREQ ); 544745Speter } 5453297Smckusic 5463297Smckusic /* 5473297Smckusic * check that two function/procedure namelist entries are compatible 5483297Smckusic */ 5493297Smckusic bool 5503297Smckusic fcompat( formal , actual ) 5513297Smckusic struct nl *formal; 5523297Smckusic struct nl *actual; 5533297Smckusic { 5543297Smckusic register struct nl *f_chain; 5553297Smckusic register struct nl *a_chain; 55614727Sthien extern struct nl *plist(); 5573297Smckusic bool compat = TRUE; 5583297Smckusic 55914727Sthien if ( formal == NLNIL || actual == NLNIL ) { 5603297Smckusic return FALSE; 5613297Smckusic } 5623297Smckusic for (a_chain = plist(actual), f_chain = plist(formal); 56314727Sthien f_chain != NLNIL; 5643297Smckusic f_chain = f_chain->chain, a_chain = a_chain->chain) { 5653297Smckusic if (a_chain == NIL) { 5663297Smckusic error("%s %s declared on line %d has more arguments than", 5673297Smckusic parnam(formal->class), formal->symbol, 56814727Sthien (char *) linenum(formal)); 5693297Smckusic cerror("%s %s declared on line %d", 5703297Smckusic parnam(actual->class), actual->symbol, 57114727Sthien (char *) linenum(actual)); 5723297Smckusic return FALSE; 5733297Smckusic } 5743297Smckusic if ( a_chain -> class != f_chain -> class ) { 5753297Smckusic error("%s parameter %s of %s declared on line %d is not identical", 5763297Smckusic parnam(f_chain->class), f_chain->symbol, 57714727Sthien formal->symbol, (char *) linenum(formal)); 5783297Smckusic cerror("with %s parameter %s of %s declared on line %d", 5793297Smckusic parnam(a_chain->class), a_chain->symbol, 58014727Sthien actual->symbol, (char *) linenum(actual)); 5813297Smckusic compat = FALSE; 5823297Smckusic } else if (a_chain->class == FFUNC || a_chain->class == FPROC) { 58314727Sthien /*compat = (compat && fcompat(f_chain, a_chain));*/ 58414727Sthien if ((compat) && (fcompat(f_chain, a_chain))) 58514727Sthien compat = TRUE; 58614727Sthien else compat = FALSE; 5873297Smckusic } 5883297Smckusic if ((a_chain->class != FPROC && f_chain->class != FPROC) && 5893297Smckusic (a_chain->type != f_chain->type)) { 5903297Smckusic error("Type of %s parameter %s of %s declared on line %d is not identical", 5913297Smckusic parnam(f_chain->class), f_chain->symbol, 59214727Sthien formal->symbol, (char *) linenum(formal)); 5933297Smckusic cerror("to type of %s parameter %s of %s declared on line %d", 5943297Smckusic parnam(a_chain->class), a_chain->symbol, 59514727Sthien actual->symbol, (char *) linenum(actual)); 5963297Smckusic compat = FALSE; 5973297Smckusic } 5983297Smckusic } 5993297Smckusic if (a_chain != NIL) { 6003297Smckusic error("%s %s declared on line %d has fewer arguments than", 6013297Smckusic parnam(formal->class), formal->symbol, 60214727Sthien (char *) linenum(formal)); 6033297Smckusic cerror("%s %s declared on line %d", 6043297Smckusic parnam(actual->class), actual->symbol, 60514727Sthien (char *) linenum(actual)); 6063297Smckusic return FALSE; 6073297Smckusic } 6083297Smckusic return compat; 6093297Smckusic } 6103297Smckusic 6113297Smckusic char * 6123297Smckusic parnam(nltype) 6133297Smckusic int nltype; 6143297Smckusic { 6153297Smckusic switch(nltype) { 6163297Smckusic case REF: 6173297Smckusic return "var"; 6183297Smckusic case VAR: 6193297Smckusic return "value"; 6203297Smckusic case FUNC: 6213297Smckusic case FFUNC: 6223297Smckusic return "function"; 6233297Smckusic case PROC: 6243297Smckusic case FPROC: 6253297Smckusic return "procedure"; 6263297Smckusic default: 6273297Smckusic return "SNARK"; 6283297Smckusic } 6293297Smckusic } 6303297Smckusic 63114727Sthien struct nl *plist(p) 6323297Smckusic struct nl *p; 6333297Smckusic { 6343297Smckusic switch (p->class) { 6353297Smckusic case FFUNC: 6363297Smckusic case FPROC: 6373297Smckusic return p->ptr[ NL_FCHAIN ]; 6383297Smckusic case PROC: 6393297Smckusic case FUNC: 6403297Smckusic return p->chain; 6413297Smckusic default: 64214727Sthien { 64314727Sthien panic("plist"); 64414727Sthien return(NLNIL); /* this is here only so lint won't complain 64514727Sthien panic actually aborts */ 64614727Sthien } 64714727Sthien 6483297Smckusic } 6493297Smckusic } 6503297Smckusic 6513297Smckusic linenum(p) 6523297Smckusic struct nl *p; 6533297Smckusic { 6543297Smckusic if (p->class == FUNC) 6553297Smckusic return p->ptr[NL_FVAR]->value[NL_LINENO]; 6563297Smckusic return p->value[NL_LINENO]; 6573297Smckusic } 658