121953Sdist /* 221953Sdist * Copyright (c) 1980 Regents of the University of California. 321953Sdist * All rights reserved. The Berkeley software License Agreement 421953Sdist * specifies the terms and conditions for redistribution. 521953Sdist */ 6745Speter 714727Sthien #ifndef lint 8*24050Smckusick static char sccsid[] = "@(#)call.c 5.2 (Berkeley) 07/26/85"; 921953Sdist #endif not lint 10745Speter 11745Speter #include "whoami.h" 12745Speter #include "0.h" 13745Speter #include "tree.h" 14745Speter #include "opcode.h" 15745Speter #include "objfmt.h" 16745Speter #ifdef PC 17745Speter # include "pc.h" 1818453Sralph # include <pcc.h> 19745Speter #endif PC 2011331Speter #include "tmps.h" 2114727Sthien #include "tree_ty.h" 22745Speter 23745Speter /* 24745Speter * Call generates code for calls to 25745Speter * user defined procedures and functions 26745Speter * and is called by proc and funccod. 27745Speter * P is the result of the lookup 28745Speter * of the procedure/function symbol, 29745Speter * and porf is PROC or FUNC. 30745Speter * Psbn is the block number of p. 313065Smckusic * 323065Smckusic * the idea here is that regular scalar functions are just called, 333065Smckusic * while structure functions and formal functions have their results 343065Smckusic * stored in a temporary after the call. 353065Smckusic * structure functions do this because they return pointers 363065Smckusic * to static results, so we copy the static 373065Smckusic * and return a pointer to the copy. 383065Smckusic * formal functions do this because we have to save the result 393065Smckusic * around a call to the runtime routine which restores the display, 403065Smckusic * so we can't just leave the result lying around in registers. 413886Speter * formal calls save the address of the descriptor in a local 423886Speter * temporary, so it can be addressed for the call which restores 433886Speter * the display (FRTN). 443426Speter * calls to formal parameters pass the formal as a hidden argument 453426Speter * to a special entry point for the formal call. 463426Speter * [this is somewhat dependent on the way arguments are addressed.] 473065Smckusic * so PROCs and scalar FUNCs look like 483065Smckusic * p(...args...) 493065Smckusic * structure FUNCs look like 503065Smckusic * (temp = p(...args...),&temp) 513065Smckusic * formal FPROCs look like 524014Smckusic * ( t=p,( t -> entryaddr )(...args...,t,s),FRTN(t,s)) 533065Smckusic * formal scalar FFUNCs look like 544014Smckusic * ( t=p,temp=( t -> entryaddr )(...args...,t,s),FRTN(t,s),temp) 553065Smckusic * formal structure FFUNCs look like 564014Smckusic * (t=p,temp = ( t -> entryaddr )(...args...,t,s),FRTN(t,s),&temp) 57745Speter */ 58745Speter struct nl * 5914727Sthien call(p, argv_node, porf, psbn) 60745Speter struct nl *p; 6114727Sthien struct tnode *argv_node; /* list node */ 6214727Sthien int porf, psbn; 63745Speter { 6415971Smckusick register struct nl *p1, *q, *p2; 6515971Smckusick register struct nl *ptype, *ctype; 6614727Sthien struct tnode *rnode; 6715971Smckusick int i, j, d; 683297Smckusic bool chk = TRUE; 694014Smckusic struct nl *savedispnp; /* temporary to hold saved display */ 70745Speter # ifdef PC 7114727Sthien int p_type_class = classify( p -> type ); 723065Smckusic long p_type_p2type = p2type( p -> type ); 733065Smckusic bool noarguments; 743065Smckusic /* 753065Smckusic * these get used if temporaries and structures are used 763065Smckusic */ 773824Speter struct nl *tempnlp; 783065Smckusic long temptype; /* type of the temporary */ 793065Smckusic long p_type_width; 803065Smckusic long p_type_align; 813362Speter char extname[ BUFSIZ ]; 823886Speter struct nl *tempdescrp; 83745Speter # endif PC 84745Speter 854014Smckusic if (p->class == FFUNC || p->class == FPROC) { 864014Smckusic /* 874014Smckusic * allocate space to save the display for formal calls 884014Smckusic */ 8914727Sthien savedispnp = tmpalloc( (long) sizeof display , NLNIL , NOREG ); 904014Smckusic } 91745Speter # ifdef OBJ 923426Speter if (p->class == FFUNC || p->class == FPROC) { 9314727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 944014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 9514727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 963426Speter } 973426Speter if (porf == FUNC) { 98745Speter /* 99745Speter * Push some space 100745Speter * for the function return type 101745Speter */ 10214727Sthien (void) put(2, O_PUSH, leven(-lwidth(p->type))); 1033426Speter } 104745Speter # endif OBJ 105745Speter # ifdef PC 1063065Smckusic /* 1073886Speter * if this is a formal call, 1083886Speter * stash the address of the descriptor 1093886Speter * in a temporary so we can find it 1103886Speter * after the FCALL for the call to FRTN 1113886Speter */ 1123886Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 11314727Sthien tempdescrp = tmpalloc((long) (sizeof( struct formalrtn *)), 11414727Sthien NLNIL, REGOK ); 11514727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 11618453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 11714727Sthien putRV((char *) 0 , psbn , p -> value[ NL_OFFS ] , 11818453Sralph p -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 11918453Sralph putop( PCC_ASSIGN , PCCTM_PTR | PCCT_STRTY ); 1203886Speter } 1213886Speter /* 1223065Smckusic * if we have to store a temporary, 1233065Smckusic * temptype will be its type, 12418453Sralph * otherwise, it's PCCT_UNDEF. 1253065Smckusic */ 12618453Sralph temptype = PCCT_UNDEF; 127745Speter if ( porf == FUNC ) { 1283065Smckusic p_type_width = width( p -> type ); 1293065Smckusic switch( p_type_class ) { 130745Speter case TSTR: 131745Speter case TSET: 132745Speter case TREC: 133745Speter case TFILE: 134745Speter case TARY: 13518453Sralph temptype = PCCT_STRTY; 1363065Smckusic p_type_align = align( p -> type ); 1373065Smckusic break; 1383065Smckusic default: 1393065Smckusic if ( p -> class == FFUNC ) { 14014727Sthien temptype = p2type( p -> type ); 141745Speter } 1423065Smckusic break; 143745Speter } 14418453Sralph if ( temptype != PCCT_UNDEF ) { 1453824Speter tempnlp = tmpalloc(p_type_width, p -> type, NOREG); 1463065Smckusic /* 1473065Smckusic * temp 1483065Smckusic * for (temp = ... 1493065Smckusic */ 15014727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 15114727Sthien tempnlp -> extra_flags , (int) temptype ); 1523065Smckusic } 153745Speter } 1541195Speter switch ( p -> class ) { 1551195Speter case FUNC: 1561195Speter case PROC: 1573065Smckusic /* 1583065Smckusic * ... p( ... 1593065Smckusic */ 1603372Speter sextname( extname , p -> symbol , BLOCKNO(p -> nl_block) ); 16118453Sralph putleaf( PCC_ICON , 0 , 0 , p2type( p ) , extname ); 1621195Speter break; 1631195Speter case FFUNC: 1641195Speter case FPROC: 1653886Speter 1661195Speter /* 1673886Speter * ... ( t -> entryaddr )( ... 1681195Speter */ 16912902Speter /* the descriptor */ 17014727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 17118453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 17212902Speter /* the entry address within the descriptor */ 1733426Speter if ( FENTRYOFFSET != 0 ) { 17418453Sralph putleaf( PCC_ICON , FENTRYOFFSET , 0 , PCCT_INT , 17514727Sthien (char *) 0 ); 17618453Sralph putop( PCC_PLUS , 17718453Sralph PCCM_ADDTYPE( 17818453Sralph PCCM_ADDTYPE( PCCM_ADDTYPE( p2type( p ) , PCCTM_FTN ) , 17918453Sralph PCCTM_PTR ) , 18018453Sralph PCCTM_PTR ) ); 1813426Speter } 18212902Speter /* 18312902Speter * indirect to fetch the formal entry address 18412902Speter * with the result type of the routine. 18512902Speter */ 18612902Speter if (p -> class == FFUNC) { 18718453Sralph putop( PCCOM_UNARY PCC_MUL , 18818453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(p2type(p -> type), PCCTM_FTN), 18918453Sralph PCCTM_PTR)); 19012902Speter } else { 19112902Speter /* procedures are int returning functions */ 19218453Sralph putop( PCCOM_UNARY PCC_MUL , 19318453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(PCCT_INT, PCCTM_FTN), PCCTM_PTR)); 19412902Speter } 1951195Speter break; 1961195Speter default: 1971195Speter panic("call class"); 198745Speter } 1993065Smckusic noarguments = TRUE; 200745Speter # endif PC 201745Speter /* 202745Speter * Loop and process each of 203745Speter * arguments to the proc/func. 2043065Smckusic * ... ( ... args ... ) ... 205745Speter */ 20615971Smckusick ptype = NIL; 20714727Sthien for (p1 = plist(p); p1 != NLNIL; p1 = p1->chain) { 20814727Sthien if (argv_node == TR_NIL) { 2093297Smckusic error("Not enough arguments to %s", p->symbol); 21014727Sthien return (NLNIL); 2113297Smckusic } 2123297Smckusic switch (p1->class) { 2133297Smckusic case REF: 2143297Smckusic /* 2153297Smckusic * Var parameter 2163297Smckusic */ 21714727Sthien rnode = argv_node->list_node.list; 21814727Sthien if (rnode != TR_NIL && rnode->tag != T_VAR) { 2193297Smckusic error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 2203361Speter chk = FALSE; 2213297Smckusic break; 2223297Smckusic } 22314727Sthien q = lvalue( argv_node->list_node.list, 22414727Sthien MOD | ASGN , LREQ ); 2253297Smckusic if (q == NIL) { 2263297Smckusic chk = FALSE; 2273297Smckusic break; 2283297Smckusic } 22915971Smckusick p2 = p1->type; 230*24050Smckusick if (p2 == NLNIL || p2->chain == NLNIL || p2->chain->class != CRANGE) { 23115971Smckusick if (q != p2) { 2323297Smckusic error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 2333361Speter chk = FALSE; 23415971Smckusick } 23515971Smckusick break; 23615971Smckusick } else { 23715971Smckusick /* conformant array */ 23815971Smckusick if (p1 == ptype) { 23915971Smckusick if (q != ctype) { 24015971Smckusick error("Conformant array parameters in the same specification must be the same type."); 24115971Smckusick goto conf_err; 24215971Smckusick } 24315971Smckusick } else { 24415971Smckusick if (classify(q) != TARY && classify(q) != TSTR) { 24515971Smckusick error("Array type required for var parameter %s of %s",p1->symbol,p->symbol); 24615971Smckusick goto conf_err; 24715971Smckusick } 24815971Smckusick /* check base type of array */ 24915971Smckusick if (p2->type != q->type) { 25015971Smckusick error("Base type of array not identical to that of conformant array parameter %s of %s", p1->symbol, p->symbol); 25115971Smckusick goto conf_err; 25215971Smckusick } 25315971Smckusick if (p2->value[0] != q->value[0]) { 25415971Smckusick error("Subscript number mismatch on conformant array parameter %s of %s", p1->symbol, p->symbol); 25515971Smckusick /* Don't process array bounds & width */ 25615971Smckusick conf_err: if (p1->chain->type->class == CRANGE) { 25715971Smckusick d = p1->value[0]; 25815971Smckusick for (i = 1; i <= d; i++) { 25915971Smckusick /* for each subscript, pass by 26015971Smckusick * bounds and width 26115971Smckusick */ 26215971Smckusick p1 = p1->chain->chain->chain; 26315971Smckusick } 26415971Smckusick } 26515971Smckusick ptype = ctype = NLNIL; 26615971Smckusick chk = FALSE; 26715971Smckusick break; 26815971Smckusick } 26915971Smckusick /* 27015971Smckusick * Save array type for all parameters with same 27115971Smckusick * specification. 27215971Smckusick */ 27315971Smckusick ctype = q; 27415971Smckusick ptype = p2; 27515971Smckusick /* 27615971Smckusick * If at end of conformant array list, 27715971Smckusick * get bounds. 27815971Smckusick */ 27915971Smckusick if (p1->chain->type->class == CRANGE) { 28015971Smckusick /* check each subscript, put on stack */ 28115971Smckusick d = ptype->value[0]; 28215971Smckusick q = ctype; 28315971Smckusick for (i = 1; i <= d; i++) { 28415971Smckusick p1 = p1->chain; 28515971Smckusick q = q->chain; 28615971Smckusick if (incompat(q, p1->type, TR_NIL)){ 28715971Smckusick error("Subscript type not conformable with parameter %s of %s", p1->symbol, p->symbol); 28815971Smckusick chk = FALSE; 28915971Smckusick break; 29015971Smckusick } 29115971Smckusick /* Put lower and upper bound & width */ 29215971Smckusick # ifdef OBJ 29315971Smckusick if (q->type->class == CRANGE) { 29415971Smckusick putcbnds(q->type); 29515971Smckusick } else { 29615971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29715971Smckusick : O_CON4, q->range[0]); 29815971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29915971Smckusick : O_CON4, q->range[1]); 30015971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 30115971Smckusick : O_CON4, aryconst(ctype,i)); 30215971Smckusick } 30315971Smckusick # endif OBJ 30415971Smckusick # ifdef PC 30515971Smckusick if (q->type->class == CRANGE) { 30615971Smckusick for (j = 1; j <= 3; j++) { 30715971Smckusick p2 = p->nptr[j]; 30815971Smckusick putRV(p2->symbol, (p2->nl_block 30915971Smckusick & 037), p2->value[0], 31015971Smckusick p2->extra_flags,p2type(p2)); 31118453Sralph putop(PCC_CM, PCCT_INT); 31215971Smckusick } 31315971Smckusick } else { 31418453Sralph putleaf(PCC_ICON, q->range[0], 0,PCCT_INT,0); 31518453Sralph putop( PCC_CM , PCCT_INT ); 31618453Sralph putleaf(PCC_ICON, q->range[1], 0,PCCT_INT,0); 31718453Sralph putop( PCC_CM , PCCT_INT ); 31818453Sralph putleaf(PCC_ICON,aryconst(ctype,i),0,PCCT_INT,0); 31918453Sralph putop( PCC_CM , PCCT_INT ); 32015971Smckusick } 32115971Smckusick # endif PC 32215971Smckusick p1 = p1->chain->chain; 32315971Smckusick } 32415971Smckusick } 32515971Smckusick } 3263297Smckusic } 3273297Smckusic break; 3283297Smckusic case VAR: 3293297Smckusic /* 3303297Smckusic * Value parameter 3313297Smckusic */ 332745Speter # ifdef OBJ 33314727Sthien q = rvalue(argv_node->list_node.list, 33414727Sthien p1->type , RREQ ); 335745Speter # endif OBJ 336745Speter # ifdef PC 3373297Smckusic /* 3383297Smckusic * structure arguments require lvalues, 3393297Smckusic * scalars use rvalue. 3403297Smckusic */ 3413297Smckusic switch( classify( p1 -> type ) ) { 3423297Smckusic case TFILE: 3433297Smckusic case TARY: 3443297Smckusic case TREC: 3453297Smckusic case TSET: 3463297Smckusic case TSTR: 34714727Sthien q = stkrval(argv_node->list_node.list, 34814727Sthien p1 -> type , (long) LREQ ); 349745Speter break; 3503297Smckusic case TINT: 3513297Smckusic case TSCAL: 3523297Smckusic case TBOOL: 3533297Smckusic case TCHAR: 3543297Smckusic precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 35514727Sthien q = stkrval(argv_node->list_node.list, 35614727Sthien p1 -> type , (long) RREQ ); 35710667Speter postcheck(p1 -> type, nl+T4INT); 358745Speter break; 35910365Smckusick case TDOUBLE: 36014727Sthien q = stkrval(argv_node->list_node.list, 36114727Sthien p1 -> type , (long) RREQ ); 36218453Sralph sconv(p2type(q), PCCT_DOUBLE); 36310365Smckusick break; 3643297Smckusic default: 36514727Sthien q = rvalue(argv_node->list_node.list, 36614727Sthien p1 -> type , RREQ ); 3673297Smckusic break; 368745Speter } 3693297Smckusic # endif PC 3703297Smckusic if (q == NIL) { 3713297Smckusic chk = FALSE; 3723297Smckusic break; 3733297Smckusic } 37414727Sthien if (incompat(q, p1->type, 37514727Sthien argv_node->list_node.list)) { 3763297Smckusic cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 3773361Speter chk = FALSE; 3783297Smckusic break; 3793297Smckusic } 380745Speter # ifdef OBJ 3813297Smckusic if (isa(p1->type, "bcsi")) 3823297Smckusic rangechk(p1->type, q); 3833297Smckusic if (q->class != STR) 3843297Smckusic convert(q, p1->type); 385745Speter # endif OBJ 386745Speter # ifdef PC 3873297Smckusic switch( classify( p1 -> type ) ) { 3883297Smckusic case TFILE: 3893297Smckusic case TARY: 3903297Smckusic case TREC: 3913297Smckusic case TSET: 3923297Smckusic case TSTR: 39318453Sralph putstrop( PCC_STARG 3943297Smckusic , p2type( p1 -> type ) 39514727Sthien , (int) lwidth( p1 -> type ) 3963297Smckusic , align( p1 -> type ) ); 3973297Smckusic } 3981195Speter # endif PC 3993297Smckusic break; 4003297Smckusic case FFUNC: 4011195Speter /* 4023297Smckusic * function parameter 4031195Speter */ 40414727Sthien q = flvalue(argv_node->list_node.list, p1 ); 40514727Sthien /*chk = (chk && fcompat(q, p1));*/ 40614727Sthien if ((chk) && (fcompat(q, p1))) 40714727Sthien chk = TRUE; 40814727Sthien else 40914727Sthien chk = FALSE; 4103297Smckusic break; 4113297Smckusic case FPROC: 4121195Speter /* 4133297Smckusic * procedure parameter 4141195Speter */ 41514727Sthien q = flvalue(argv_node->list_node.list, p1 ); 41614727Sthien /* chk = (chk && fcompat(q, p1)); */ 41714727Sthien if ((chk) && (fcompat(q, p1))) 41814727Sthien chk = TRUE; 41914727Sthien else chk = FALSE; 4203297Smckusic break; 4213297Smckusic default: 4223297Smckusic panic("call"); 4231195Speter } 4243297Smckusic # ifdef PC 4253297Smckusic /* 4263297Smckusic * if this is the nth (>1) argument, 4273297Smckusic * hang it on the left linear list of arguments 4283297Smckusic */ 4293297Smckusic if ( noarguments ) { 4303297Smckusic noarguments = FALSE; 4313297Smckusic } else { 43218453Sralph putop( PCC_CM , PCCT_INT ); 4333297Smckusic } 4343297Smckusic # endif PC 43514727Sthien argv_node = argv_node->list_node.next; 436745Speter } 43714727Sthien if (argv_node != TR_NIL) { 4383297Smckusic error("Too many arguments to %s", p->symbol); 43914727Sthien rvlist(argv_node); 44014727Sthien return (NLNIL); 4413297Smckusic } 4423297Smckusic if (chk == FALSE) 44314727Sthien return NLNIL; 444745Speter # ifdef OBJ 4451195Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 44614727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 44714727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 4484014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 44914727Sthien (void) put(1, O_FCALL); 45014727Sthien (void) put(2, O_FRTN, even(width(p->type))); 4511195Speter } else { 45214727Sthien (void) put(2, O_CALL | psbn << 8, (long)p->value[NL_ENTLOC]); 4531195Speter } 454745Speter # endif OBJ 455745Speter # ifdef PC 4563065Smckusic /* 4573426Speter * for formal calls: add the hidden argument 4583426Speter * which is the formal struct describing the 4593426Speter * environment of the routine. 4603426Speter * and the argument which is the address of the 4613426Speter * space into which to save the display. 4623426Speter */ 4633426Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 46414727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 46518453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 4663426Speter if ( !noarguments ) { 46718453Sralph putop( PCC_CM , PCCT_INT ); 4683426Speter } 4693426Speter noarguments = FALSE; 47014727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 47118453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 47218453Sralph putop( PCC_CM , PCCT_INT ); 4733426Speter } 4743426Speter /* 4753065Smckusic * do the actual call: 4763065Smckusic * either ... p( ... ) ... 4773886Speter * or ... ( t -> entryaddr )( ... ) ... 4783065Smckusic * and maybe an assignment. 4793065Smckusic */ 480745Speter if ( porf == FUNC ) { 4813065Smckusic switch ( p_type_class ) { 482745Speter case TBOOL: 483745Speter case TCHAR: 484745Speter case TINT: 485745Speter case TSCAL: 486745Speter case TDOUBLE: 487745Speter case TPTR: 48818453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , 48914727Sthien (int) p_type_p2type ); 4903065Smckusic if ( p -> class == FFUNC ) { 49118453Sralph putop( PCC_ASSIGN , (int) p_type_p2type ); 492745Speter } 493745Speter break; 494745Speter default: 49518453Sralph putstrop( ( noarguments ? PCCOM_UNARY PCC_STCALL : PCC_STCALL ), 49618453Sralph (int) PCCM_ADDTYPE( p_type_p2type , PCCTM_PTR ) , 49714727Sthien (int) p_type_width ,(int) p_type_align ); 49818453Sralph putstrop(PCC_STASG, (int) PCCM_ADDTYPE(p_type_p2type, PCCTM_PTR), 49914727Sthien (int) lwidth(p -> type), align(p -> type)); 500745Speter break; 501745Speter } 502745Speter } else { 50318453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , PCCT_INT ); 5043065Smckusic } 5053065Smckusic /* 5063886Speter * ( t=p , ... , FRTN( t ) ... 5073065Smckusic */ 5083065Smckusic if ( p -> class == FFUNC || p -> class == FPROC ) { 50918453Sralph putop( PCC_COMOP , PCCT_INT ); 51018453Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , 5113065Smckusic "_FRTN" ); 51214727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 51318453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 51414727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 51518453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 51618453Sralph putop( PCC_CM , PCCT_INT ); 51718453Sralph putop( PCC_CALL , PCCT_INT ); 51818453Sralph putop( PCC_COMOP , PCCT_INT ); 5193065Smckusic } 5203065Smckusic /* 5213065Smckusic * if required: 5223065Smckusic * either ... , temp ) 5233065Smckusic * or ... , &temp ) 5243065Smckusic */ 52518453Sralph if ( porf == FUNC && temptype != PCCT_UNDEF ) { 52618453Sralph if ( temptype != PCCT_STRTY ) { 52714727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 52814727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 529745Speter } else { 53014727Sthien putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 53114727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 532745Speter } 53318453Sralph putop( PCC_COMOP , PCCT_INT ); 5343065Smckusic } 5353065Smckusic if ( porf == PROC ) { 536745Speter putdot( filename , line ); 537745Speter } 538745Speter # endif PC 539745Speter return (p->type); 540745Speter } 541745Speter 542745Speter rvlist(al) 54314727Sthien register struct tnode *al; 544745Speter { 545745Speter 54614727Sthien for (; al != TR_NIL; al = al->list_node.next) 54714727Sthien (void) rvalue( al->list_node.list, NLNIL , RREQ ); 548745Speter } 5493297Smckusic 5503297Smckusic /* 5513297Smckusic * check that two function/procedure namelist entries are compatible 5523297Smckusic */ 5533297Smckusic bool 5543297Smckusic fcompat( formal , actual ) 5553297Smckusic struct nl *formal; 5563297Smckusic struct nl *actual; 5573297Smckusic { 5583297Smckusic register struct nl *f_chain; 5593297Smckusic register struct nl *a_chain; 56014727Sthien extern struct nl *plist(); 5613297Smckusic bool compat = TRUE; 5623297Smckusic 56314727Sthien if ( formal == NLNIL || actual == NLNIL ) { 5643297Smckusic return FALSE; 5653297Smckusic } 5663297Smckusic for (a_chain = plist(actual), f_chain = plist(formal); 56714727Sthien f_chain != NLNIL; 5683297Smckusic f_chain = f_chain->chain, a_chain = a_chain->chain) { 5693297Smckusic if (a_chain == NIL) { 5703297Smckusic error("%s %s declared on line %d has more arguments than", 5713297Smckusic parnam(formal->class), formal->symbol, 57214727Sthien (char *) linenum(formal)); 5733297Smckusic cerror("%s %s declared on line %d", 5743297Smckusic parnam(actual->class), actual->symbol, 57514727Sthien (char *) linenum(actual)); 5763297Smckusic return FALSE; 5773297Smckusic } 5783297Smckusic if ( a_chain -> class != f_chain -> class ) { 5793297Smckusic error("%s parameter %s of %s declared on line %d is not identical", 5803297Smckusic parnam(f_chain->class), f_chain->symbol, 58114727Sthien formal->symbol, (char *) linenum(formal)); 5823297Smckusic cerror("with %s parameter %s of %s declared on line %d", 5833297Smckusic parnam(a_chain->class), a_chain->symbol, 58414727Sthien actual->symbol, (char *) linenum(actual)); 5853297Smckusic compat = FALSE; 5863297Smckusic } else if (a_chain->class == FFUNC || a_chain->class == FPROC) { 58714727Sthien /*compat = (compat && fcompat(f_chain, a_chain));*/ 58814727Sthien if ((compat) && (fcompat(f_chain, a_chain))) 58914727Sthien compat = TRUE; 59014727Sthien else compat = FALSE; 5913297Smckusic } 5923297Smckusic if ((a_chain->class != FPROC && f_chain->class != FPROC) && 5933297Smckusic (a_chain->type != f_chain->type)) { 5943297Smckusic error("Type of %s parameter %s of %s declared on line %d is not identical", 5953297Smckusic parnam(f_chain->class), f_chain->symbol, 59614727Sthien formal->symbol, (char *) linenum(formal)); 5973297Smckusic cerror("to type of %s parameter %s of %s declared on line %d", 5983297Smckusic parnam(a_chain->class), a_chain->symbol, 59914727Sthien actual->symbol, (char *) linenum(actual)); 6003297Smckusic compat = FALSE; 6013297Smckusic } 6023297Smckusic } 6033297Smckusic if (a_chain != NIL) { 6043297Smckusic error("%s %s declared on line %d has fewer arguments than", 6053297Smckusic parnam(formal->class), formal->symbol, 60614727Sthien (char *) linenum(formal)); 6073297Smckusic cerror("%s %s declared on line %d", 6083297Smckusic parnam(actual->class), actual->symbol, 60914727Sthien (char *) linenum(actual)); 6103297Smckusic return FALSE; 6113297Smckusic } 6123297Smckusic return compat; 6133297Smckusic } 6143297Smckusic 6153297Smckusic char * 6163297Smckusic parnam(nltype) 6173297Smckusic int nltype; 6183297Smckusic { 6193297Smckusic switch(nltype) { 6203297Smckusic case REF: 6213297Smckusic return "var"; 6223297Smckusic case VAR: 6233297Smckusic return "value"; 6243297Smckusic case FUNC: 6253297Smckusic case FFUNC: 6263297Smckusic return "function"; 6273297Smckusic case PROC: 6283297Smckusic case FPROC: 6293297Smckusic return "procedure"; 6303297Smckusic default: 6313297Smckusic return "SNARK"; 6323297Smckusic } 6333297Smckusic } 6343297Smckusic 63514727Sthien struct nl *plist(p) 6363297Smckusic struct nl *p; 6373297Smckusic { 6383297Smckusic switch (p->class) { 6393297Smckusic case FFUNC: 6403297Smckusic case FPROC: 6413297Smckusic return p->ptr[ NL_FCHAIN ]; 6423297Smckusic case PROC: 6433297Smckusic case FUNC: 6443297Smckusic return p->chain; 6453297Smckusic default: 64614727Sthien { 64714727Sthien panic("plist"); 64814727Sthien return(NLNIL); /* this is here only so lint won't complain 64914727Sthien panic actually aborts */ 65014727Sthien } 65114727Sthien 6523297Smckusic } 6533297Smckusic } 6543297Smckusic 6553297Smckusic linenum(p) 6563297Smckusic struct nl *p; 6573297Smckusic { 6583297Smckusic if (p->class == FUNC) 6593297Smckusic return p->ptr[NL_FVAR]->value[NL_LINENO]; 6603297Smckusic return p->value[NL_LINENO]; 6613297Smckusic } 662