1*48116Sbostic /*- 2*48116Sbostic * Copyright (c) 1980 The Regents of the University of California. 3*48116Sbostic * All rights reserved. 4*48116Sbostic * 5*48116Sbostic * %sccs.include.redist.c% 621953Sdist */ 7745Speter 814727Sthien #ifndef lint 9*48116Sbostic static char sccsid[] = "@(#)call.c 5.4 (Berkeley) 04/16/91"; 10*48116Sbostic #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 * 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 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 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 * 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 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