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*30037Smckusick static char sccsid[] = "@(#)call.c 5.3 (Berkeley) 11/12/86"; 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" 16*30037Smckusick #include "align.h" 17745Speter #ifdef PC 18745Speter # include "pc.h" 1918453Sralph # include <pcc.h> 20745Speter #endif PC 2111331Speter #include "tmps.h" 2214727Sthien #include "tree_ty.h" 23745Speter 24745Speter /* 25745Speter * Call generates code for calls to 26745Speter * user defined procedures and functions 27745Speter * and is called by proc and funccod. 28745Speter * P is the result of the lookup 29745Speter * of the procedure/function symbol, 30745Speter * and porf is PROC or FUNC. 31745Speter * Psbn is the block number of p. 323065Smckusic * 333065Smckusic * the idea here is that regular scalar functions are just called, 343065Smckusic * while structure functions and formal functions have their results 353065Smckusic * stored in a temporary after the call. 363065Smckusic * structure functions do this because they return pointers 373065Smckusic * to static results, so we copy the static 383065Smckusic * and return a pointer to the copy. 393065Smckusic * formal functions do this because we have to save the result 403065Smckusic * around a call to the runtime routine which restores the display, 413065Smckusic * so we can't just leave the result lying around in registers. 423886Speter * formal calls save the address of the descriptor in a local 433886Speter * temporary, so it can be addressed for the call which restores 443886Speter * the display (FRTN). 453426Speter * calls to formal parameters pass the formal as a hidden argument 463426Speter * to a special entry point for the formal call. 473426Speter * [this is somewhat dependent on the way arguments are addressed.] 483065Smckusic * so PROCs and scalar FUNCs look like 493065Smckusic * p(...args...) 503065Smckusic * structure FUNCs look like 513065Smckusic * (temp = p(...args...),&temp) 523065Smckusic * formal FPROCs look like 534014Smckusic * ( t=p,( t -> entryaddr )(...args...,t,s),FRTN(t,s)) 543065Smckusic * formal scalar FFUNCs look like 554014Smckusic * ( t=p,temp=( t -> entryaddr )(...args...,t,s),FRTN(t,s),temp) 563065Smckusic * formal structure FFUNCs look like 574014Smckusic * (t=p,temp = ( t -> entryaddr )(...args...,t,s),FRTN(t,s),&temp) 58745Speter */ 59745Speter struct nl * 6014727Sthien call(p, argv_node, porf, psbn) 61745Speter struct nl *p; 6214727Sthien struct tnode *argv_node; /* list node */ 6314727Sthien int porf, psbn; 64745Speter { 6515971Smckusick register struct nl *p1, *q, *p2; 6615971Smckusick register struct nl *ptype, *ctype; 6714727Sthien struct tnode *rnode; 6815971Smckusick int i, j, d; 693297Smckusic bool chk = TRUE; 704014Smckusic struct nl *savedispnp; /* temporary to hold saved display */ 71745Speter # ifdef PC 7214727Sthien int p_type_class = classify( p -> type ); 733065Smckusic long p_type_p2type = p2type( p -> type ); 743065Smckusic bool noarguments; 753065Smckusic /* 763065Smckusic * these get used if temporaries and structures are used 773065Smckusic */ 783824Speter struct nl *tempnlp; 793065Smckusic long temptype; /* type of the temporary */ 803065Smckusic long p_type_width; 813065Smckusic long p_type_align; 823362Speter char extname[ BUFSIZ ]; 833886Speter struct nl *tempdescrp; 84745Speter # endif PC 85745Speter 864014Smckusic if (p->class == FFUNC || p->class == FPROC) { 874014Smckusic /* 884014Smckusic * allocate space to save the display for formal calls 894014Smckusic */ 9014727Sthien savedispnp = tmpalloc( (long) sizeof display , NLNIL , NOREG ); 914014Smckusic } 92745Speter # ifdef OBJ 933426Speter if (p->class == FFUNC || p->class == FPROC) { 9414727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 954014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 9614727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 973426Speter } 983426Speter if (porf == FUNC) { 99745Speter /* 100745Speter * Push some space 101745Speter * for the function return type 102745Speter */ 103*30037Smckusick (void) put(2, O_PUSH, 104*30037Smckusick -roundup(lwidth(p->type), (long) A_STACK)); 1053426Speter } 106745Speter # endif OBJ 107745Speter # ifdef PC 1083065Smckusic /* 1093886Speter * if this is a formal call, 1103886Speter * stash the address of the descriptor 1113886Speter * in a temporary so we can find it 1123886Speter * after the FCALL for the call to FRTN 1133886Speter */ 1143886Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 11514727Sthien tempdescrp = tmpalloc((long) (sizeof( struct formalrtn *)), 11614727Sthien NLNIL, REGOK ); 11714727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 11818453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 11914727Sthien putRV((char *) 0 , psbn , p -> value[ NL_OFFS ] , 12018453Sralph p -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 12118453Sralph putop( PCC_ASSIGN , PCCTM_PTR | PCCT_STRTY ); 1223886Speter } 1233886Speter /* 1243065Smckusic * if we have to store a temporary, 1253065Smckusic * temptype will be its type, 12618453Sralph * otherwise, it's PCCT_UNDEF. 1273065Smckusic */ 12818453Sralph temptype = PCCT_UNDEF; 129745Speter if ( porf == FUNC ) { 1303065Smckusic p_type_width = width( p -> type ); 1313065Smckusic switch( p_type_class ) { 132745Speter case TSTR: 133745Speter case TSET: 134745Speter case TREC: 135745Speter case TFILE: 136745Speter case TARY: 13718453Sralph temptype = PCCT_STRTY; 1383065Smckusic p_type_align = align( p -> type ); 1393065Smckusic break; 1403065Smckusic default: 1413065Smckusic if ( p -> class == FFUNC ) { 14214727Sthien temptype = p2type( p -> type ); 143745Speter } 1443065Smckusic break; 145745Speter } 14618453Sralph if ( temptype != PCCT_UNDEF ) { 1473824Speter tempnlp = tmpalloc(p_type_width, p -> type, NOREG); 1483065Smckusic /* 1493065Smckusic * temp 1503065Smckusic * for (temp = ... 1513065Smckusic */ 15214727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 15314727Sthien tempnlp -> extra_flags , (int) temptype ); 1543065Smckusic } 155745Speter } 1561195Speter switch ( p -> class ) { 1571195Speter case FUNC: 1581195Speter case PROC: 1593065Smckusic /* 1603065Smckusic * ... p( ... 1613065Smckusic */ 1623372Speter sextname( extname , p -> symbol , BLOCKNO(p -> nl_block) ); 16318453Sralph putleaf( PCC_ICON , 0 , 0 , p2type( p ) , extname ); 1641195Speter break; 1651195Speter case FFUNC: 1661195Speter case FPROC: 1673886Speter 1681195Speter /* 1693886Speter * ... ( t -> entryaddr )( ... 1701195Speter */ 17112902Speter /* the descriptor */ 17214727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 17318453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 17412902Speter /* the entry address within the descriptor */ 1753426Speter if ( FENTRYOFFSET != 0 ) { 17618453Sralph putleaf( PCC_ICON , FENTRYOFFSET , 0 , PCCT_INT , 17714727Sthien (char *) 0 ); 17818453Sralph putop( PCC_PLUS , 17918453Sralph PCCM_ADDTYPE( 18018453Sralph PCCM_ADDTYPE( PCCM_ADDTYPE( p2type( p ) , PCCTM_FTN ) , 18118453Sralph PCCTM_PTR ) , 18218453Sralph PCCTM_PTR ) ); 1833426Speter } 18412902Speter /* 18512902Speter * indirect to fetch the formal entry address 18612902Speter * with the result type of the routine. 18712902Speter */ 18812902Speter if (p -> class == FFUNC) { 18918453Sralph putop( PCCOM_UNARY PCC_MUL , 19018453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(p2type(p -> type), PCCTM_FTN), 19118453Sralph PCCTM_PTR)); 19212902Speter } else { 19312902Speter /* procedures are int returning functions */ 19418453Sralph putop( PCCOM_UNARY PCC_MUL , 19518453Sralph PCCM_ADDTYPE(PCCM_ADDTYPE(PCCT_INT, PCCTM_FTN), PCCTM_PTR)); 19612902Speter } 1971195Speter break; 1981195Speter default: 1991195Speter panic("call class"); 200745Speter } 2013065Smckusic noarguments = TRUE; 202745Speter # endif PC 203745Speter /* 204745Speter * Loop and process each of 205745Speter * arguments to the proc/func. 2063065Smckusic * ... ( ... args ... ) ... 207745Speter */ 20815971Smckusick ptype = NIL; 20914727Sthien for (p1 = plist(p); p1 != NLNIL; p1 = p1->chain) { 21014727Sthien if (argv_node == TR_NIL) { 2113297Smckusic error("Not enough arguments to %s", p->symbol); 21214727Sthien return (NLNIL); 2133297Smckusic } 2143297Smckusic switch (p1->class) { 2153297Smckusic case REF: 2163297Smckusic /* 2173297Smckusic * Var parameter 2183297Smckusic */ 21914727Sthien rnode = argv_node->list_node.list; 22014727Sthien if (rnode != TR_NIL && rnode->tag != T_VAR) { 2213297Smckusic error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 2223361Speter chk = FALSE; 2233297Smckusic break; 2243297Smckusic } 22514727Sthien q = lvalue( argv_node->list_node.list, 22614727Sthien MOD | ASGN , LREQ ); 2273297Smckusic if (q == NIL) { 2283297Smckusic chk = FALSE; 2293297Smckusic break; 2303297Smckusic } 23115971Smckusick p2 = p1->type; 23224050Smckusick if (p2 == NLNIL || p2->chain == NLNIL || p2->chain->class != CRANGE) { 23315971Smckusick if (q != p2) { 2343297Smckusic error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 2353361Speter chk = FALSE; 23615971Smckusick } 23715971Smckusick break; 23815971Smckusick } else { 23915971Smckusick /* conformant array */ 24015971Smckusick if (p1 == ptype) { 24115971Smckusick if (q != ctype) { 24215971Smckusick error("Conformant array parameters in the same specification must be the same type."); 24315971Smckusick goto conf_err; 24415971Smckusick } 24515971Smckusick } else { 24615971Smckusick if (classify(q) != TARY && classify(q) != TSTR) { 24715971Smckusick error("Array type required for var parameter %s of %s",p1->symbol,p->symbol); 24815971Smckusick goto conf_err; 24915971Smckusick } 25015971Smckusick /* check base type of array */ 25115971Smckusick if (p2->type != q->type) { 25215971Smckusick error("Base type of array not identical to that of conformant array parameter %s of %s", p1->symbol, p->symbol); 25315971Smckusick goto conf_err; 25415971Smckusick } 25515971Smckusick if (p2->value[0] != q->value[0]) { 25615971Smckusick error("Subscript number mismatch on conformant array parameter %s of %s", p1->symbol, p->symbol); 25715971Smckusick /* Don't process array bounds & width */ 25815971Smckusick conf_err: if (p1->chain->type->class == CRANGE) { 25915971Smckusick d = p1->value[0]; 26015971Smckusick for (i = 1; i <= d; i++) { 26115971Smckusick /* for each subscript, pass by 26215971Smckusick * bounds and width 26315971Smckusick */ 26415971Smckusick p1 = p1->chain->chain->chain; 26515971Smckusick } 26615971Smckusick } 26715971Smckusick ptype = ctype = NLNIL; 26815971Smckusick chk = FALSE; 26915971Smckusick break; 27015971Smckusick } 27115971Smckusick /* 27215971Smckusick * Save array type for all parameters with same 27315971Smckusick * specification. 27415971Smckusick */ 27515971Smckusick ctype = q; 27615971Smckusick ptype = p2; 27715971Smckusick /* 27815971Smckusick * If at end of conformant array list, 27915971Smckusick * get bounds. 28015971Smckusick */ 28115971Smckusick if (p1->chain->type->class == CRANGE) { 28215971Smckusick /* check each subscript, put on stack */ 28315971Smckusick d = ptype->value[0]; 28415971Smckusick q = ctype; 28515971Smckusick for (i = 1; i <= d; i++) { 28615971Smckusick p1 = p1->chain; 28715971Smckusick q = q->chain; 28815971Smckusick if (incompat(q, p1->type, TR_NIL)){ 28915971Smckusick error("Subscript type not conformable with parameter %s of %s", p1->symbol, p->symbol); 29015971Smckusick chk = FALSE; 29115971Smckusick break; 29215971Smckusick } 29315971Smckusick /* Put lower and upper bound & width */ 29415971Smckusick # ifdef OBJ 29515971Smckusick if (q->type->class == CRANGE) { 29615971Smckusick putcbnds(q->type); 29715971Smckusick } else { 29815971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 29915971Smckusick : O_CON4, q->range[0]); 30015971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 30115971Smckusick : O_CON4, q->range[1]); 30215971Smckusick put(2, width(p1->type) <= 2 ? O_CON2 30315971Smckusick : O_CON4, aryconst(ctype,i)); 30415971Smckusick } 30515971Smckusick # endif OBJ 30615971Smckusick # ifdef PC 30715971Smckusick if (q->type->class == CRANGE) { 30815971Smckusick for (j = 1; j <= 3; j++) { 30915971Smckusick p2 = p->nptr[j]; 31015971Smckusick putRV(p2->symbol, (p2->nl_block 31115971Smckusick & 037), p2->value[0], 31215971Smckusick p2->extra_flags,p2type(p2)); 31318453Sralph putop(PCC_CM, PCCT_INT); 31415971Smckusick } 31515971Smckusick } else { 31618453Sralph putleaf(PCC_ICON, q->range[0], 0,PCCT_INT,0); 31718453Sralph putop( PCC_CM , PCCT_INT ); 31818453Sralph putleaf(PCC_ICON, q->range[1], 0,PCCT_INT,0); 31918453Sralph putop( PCC_CM , PCCT_INT ); 32018453Sralph putleaf(PCC_ICON,aryconst(ctype,i),0,PCCT_INT,0); 32118453Sralph putop( PCC_CM , PCCT_INT ); 32215971Smckusick } 32315971Smckusick # endif PC 32415971Smckusick p1 = p1->chain->chain; 32515971Smckusick } 32615971Smckusick } 32715971Smckusick } 3283297Smckusic } 3293297Smckusic break; 3303297Smckusic case VAR: 3313297Smckusic /* 3323297Smckusic * Value parameter 3333297Smckusic */ 334745Speter # ifdef OBJ 33514727Sthien q = rvalue(argv_node->list_node.list, 33614727Sthien p1->type , RREQ ); 337745Speter # endif OBJ 338745Speter # ifdef PC 3393297Smckusic /* 3403297Smckusic * structure arguments require lvalues, 3413297Smckusic * scalars use rvalue. 3423297Smckusic */ 3433297Smckusic switch( classify( p1 -> type ) ) { 3443297Smckusic case TFILE: 3453297Smckusic case TARY: 3463297Smckusic case TREC: 3473297Smckusic case TSET: 3483297Smckusic case TSTR: 34914727Sthien q = stkrval(argv_node->list_node.list, 35014727Sthien p1 -> type , (long) LREQ ); 351745Speter break; 3523297Smckusic case TINT: 3533297Smckusic case TSCAL: 3543297Smckusic case TBOOL: 3553297Smckusic case TCHAR: 3563297Smckusic precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 35714727Sthien q = stkrval(argv_node->list_node.list, 35814727Sthien p1 -> type , (long) RREQ ); 35910667Speter postcheck(p1 -> type, nl+T4INT); 360745Speter break; 36110365Smckusick case TDOUBLE: 36214727Sthien q = stkrval(argv_node->list_node.list, 36314727Sthien p1 -> type , (long) RREQ ); 36418453Sralph sconv(p2type(q), PCCT_DOUBLE); 36510365Smckusick break; 3663297Smckusic default: 36714727Sthien q = rvalue(argv_node->list_node.list, 36814727Sthien p1 -> type , RREQ ); 3693297Smckusic break; 370745Speter } 3713297Smckusic # endif PC 3723297Smckusic if (q == NIL) { 3733297Smckusic chk = FALSE; 3743297Smckusic break; 3753297Smckusic } 37614727Sthien if (incompat(q, p1->type, 37714727Sthien argv_node->list_node.list)) { 3783297Smckusic cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 3793361Speter chk = FALSE; 3803297Smckusic break; 3813297Smckusic } 382745Speter # ifdef OBJ 3833297Smckusic if (isa(p1->type, "bcsi")) 3843297Smckusic rangechk(p1->type, q); 3853297Smckusic if (q->class != STR) 3863297Smckusic convert(q, p1->type); 387745Speter # endif OBJ 388745Speter # ifdef PC 3893297Smckusic switch( classify( p1 -> type ) ) { 3903297Smckusic case TFILE: 3913297Smckusic case TARY: 3923297Smckusic case TREC: 3933297Smckusic case TSET: 3943297Smckusic case TSTR: 39518453Sralph putstrop( PCC_STARG 3963297Smckusic , p2type( p1 -> type ) 39714727Sthien , (int) lwidth( p1 -> type ) 3983297Smckusic , align( p1 -> type ) ); 3993297Smckusic } 4001195Speter # endif PC 4013297Smckusic break; 4023297Smckusic case FFUNC: 4031195Speter /* 4043297Smckusic * function parameter 4051195Speter */ 40614727Sthien q = flvalue(argv_node->list_node.list, p1 ); 40714727Sthien /*chk = (chk && fcompat(q, p1));*/ 40814727Sthien if ((chk) && (fcompat(q, p1))) 40914727Sthien chk = TRUE; 41014727Sthien else 41114727Sthien chk = FALSE; 4123297Smckusic break; 4133297Smckusic case FPROC: 4141195Speter /* 4153297Smckusic * procedure parameter 4161195Speter */ 41714727Sthien q = flvalue(argv_node->list_node.list, p1 ); 41814727Sthien /* chk = (chk && fcompat(q, p1)); */ 41914727Sthien if ((chk) && (fcompat(q, p1))) 42014727Sthien chk = TRUE; 42114727Sthien else chk = FALSE; 4223297Smckusic break; 4233297Smckusic default: 4243297Smckusic panic("call"); 4251195Speter } 4263297Smckusic # ifdef PC 4273297Smckusic /* 4283297Smckusic * if this is the nth (>1) argument, 4293297Smckusic * hang it on the left linear list of arguments 4303297Smckusic */ 4313297Smckusic if ( noarguments ) { 4323297Smckusic noarguments = FALSE; 4333297Smckusic } else { 43418453Sralph putop( PCC_CM , PCCT_INT ); 4353297Smckusic } 4363297Smckusic # endif PC 43714727Sthien argv_node = argv_node->list_node.next; 438745Speter } 43914727Sthien if (argv_node != TR_NIL) { 4403297Smckusic error("Too many arguments to %s", p->symbol); 44114727Sthien rvlist(argv_node); 44214727Sthien return (NLNIL); 4433297Smckusic } 4443297Smckusic if (chk == FALSE) 44514727Sthien return NLNIL; 446745Speter # ifdef OBJ 4471195Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 44814727Sthien (void) put(2, PTR_RV | psbn << 8+INDX, (int)p->value[NL_OFFS]); 44914727Sthien (void) put(2, O_LV | cbn << 8 + INDX , 4504014Smckusic (int) savedispnp -> value[ NL_OFFS ] ); 45114727Sthien (void) put(1, O_FCALL); 452*30037Smckusick (void) put(2, O_FRTN, roundup(width(p->type), (long) A_STACK)); 4531195Speter } else { 45414727Sthien (void) put(2, O_CALL | psbn << 8, (long)p->value[NL_ENTLOC]); 4551195Speter } 456745Speter # endif OBJ 457745Speter # ifdef PC 4583065Smckusic /* 4593426Speter * for formal calls: add the hidden argument 4603426Speter * which is the formal struct describing the 4613426Speter * environment of the routine. 4623426Speter * and the argument which is the address of the 4633426Speter * space into which to save the display. 4643426Speter */ 4653426Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 46614727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 46718453Sralph tempdescrp -> extra_flags , PCCTM_PTR|PCCT_STRTY ); 4683426Speter if ( !noarguments ) { 46918453Sralph putop( PCC_CM , PCCT_INT ); 4703426Speter } 4713426Speter noarguments = FALSE; 47214727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 47318453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 47418453Sralph putop( PCC_CM , PCCT_INT ); 4753426Speter } 4763426Speter /* 4773065Smckusic * do the actual call: 4783065Smckusic * either ... p( ... ) ... 4793886Speter * or ... ( t -> entryaddr )( ... ) ... 4803065Smckusic * and maybe an assignment. 4813065Smckusic */ 482745Speter if ( porf == FUNC ) { 4833065Smckusic switch ( p_type_class ) { 484745Speter case TBOOL: 485745Speter case TCHAR: 486745Speter case TINT: 487745Speter case TSCAL: 488745Speter case TDOUBLE: 489745Speter case TPTR: 49018453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , 49114727Sthien (int) p_type_p2type ); 4923065Smckusic if ( p -> class == FFUNC ) { 49318453Sralph putop( PCC_ASSIGN , (int) p_type_p2type ); 494745Speter } 495745Speter break; 496745Speter default: 49718453Sralph putstrop( ( noarguments ? PCCOM_UNARY PCC_STCALL : PCC_STCALL ), 49818453Sralph (int) PCCM_ADDTYPE( p_type_p2type , PCCTM_PTR ) , 49914727Sthien (int) p_type_width ,(int) p_type_align ); 50018453Sralph putstrop(PCC_STASG, (int) PCCM_ADDTYPE(p_type_p2type, PCCTM_PTR), 50114727Sthien (int) lwidth(p -> type), align(p -> type)); 502745Speter break; 503745Speter } 504745Speter } else { 50518453Sralph putop( ( noarguments ? PCCOM_UNARY PCC_CALL : PCC_CALL ) , PCCT_INT ); 5063065Smckusic } 5073065Smckusic /* 5083886Speter * ( t=p , ... , FRTN( t ) ... 5093065Smckusic */ 5103065Smckusic if ( p -> class == FFUNC || p -> class == FPROC ) { 51118453Sralph putop( PCC_COMOP , PCCT_INT ); 51218453Sralph putleaf( PCC_ICON , 0 , 0 , PCCM_ADDTYPE( PCCTM_FTN | PCCT_INT , PCCTM_PTR ) , 5133065Smckusic "_FRTN" ); 51414727Sthien putRV((char *) 0 , cbn , tempdescrp -> value[ NL_OFFS ] , 51518453Sralph tempdescrp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 51614727Sthien putLV((char *) 0 , cbn , savedispnp -> value[ NL_OFFS ] , 51718453Sralph savedispnp -> extra_flags , PCCTM_PTR | PCCT_STRTY ); 51818453Sralph putop( PCC_CM , PCCT_INT ); 51918453Sralph putop( PCC_CALL , PCCT_INT ); 52018453Sralph putop( PCC_COMOP , PCCT_INT ); 5213065Smckusic } 5223065Smckusic /* 5233065Smckusic * if required: 5243065Smckusic * either ... , temp ) 5253065Smckusic * or ... , &temp ) 5263065Smckusic */ 52718453Sralph if ( porf == FUNC && temptype != PCCT_UNDEF ) { 52818453Sralph if ( temptype != PCCT_STRTY ) { 52914727Sthien putRV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 53014727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 531745Speter } else { 53214727Sthien putLV((char *) 0 , cbn , tempnlp -> value[ NL_OFFS ] , 53314727Sthien tempnlp -> extra_flags , (int) p_type_p2type ); 534745Speter } 53518453Sralph putop( PCC_COMOP , PCCT_INT ); 5363065Smckusic } 5373065Smckusic if ( porf == PROC ) { 538745Speter putdot( filename , line ); 539745Speter } 540745Speter # endif PC 541745Speter return (p->type); 542745Speter } 543745Speter 544745Speter rvlist(al) 54514727Sthien register struct tnode *al; 546745Speter { 547745Speter 54814727Sthien for (; al != TR_NIL; al = al->list_node.next) 54914727Sthien (void) rvalue( al->list_node.list, NLNIL , RREQ ); 550745Speter } 5513297Smckusic 5523297Smckusic /* 5533297Smckusic * check that two function/procedure namelist entries are compatible 5543297Smckusic */ 5553297Smckusic bool 5563297Smckusic fcompat( formal , actual ) 5573297Smckusic struct nl *formal; 5583297Smckusic struct nl *actual; 5593297Smckusic { 5603297Smckusic register struct nl *f_chain; 5613297Smckusic register struct nl *a_chain; 56214727Sthien extern struct nl *plist(); 5633297Smckusic bool compat = TRUE; 5643297Smckusic 56514727Sthien if ( formal == NLNIL || actual == NLNIL ) { 5663297Smckusic return FALSE; 5673297Smckusic } 5683297Smckusic for (a_chain = plist(actual), f_chain = plist(formal); 56914727Sthien f_chain != NLNIL; 5703297Smckusic f_chain = f_chain->chain, a_chain = a_chain->chain) { 5713297Smckusic if (a_chain == NIL) { 5723297Smckusic error("%s %s declared on line %d has more arguments than", 5733297Smckusic parnam(formal->class), formal->symbol, 57414727Sthien (char *) linenum(formal)); 5753297Smckusic cerror("%s %s declared on line %d", 5763297Smckusic parnam(actual->class), actual->symbol, 57714727Sthien (char *) linenum(actual)); 5783297Smckusic return FALSE; 5793297Smckusic } 5803297Smckusic if ( a_chain -> class != f_chain -> class ) { 5813297Smckusic error("%s parameter %s of %s declared on line %d is not identical", 5823297Smckusic parnam(f_chain->class), f_chain->symbol, 58314727Sthien formal->symbol, (char *) linenum(formal)); 5843297Smckusic cerror("with %s parameter %s of %s declared on line %d", 5853297Smckusic parnam(a_chain->class), a_chain->symbol, 58614727Sthien actual->symbol, (char *) linenum(actual)); 5873297Smckusic compat = FALSE; 5883297Smckusic } else if (a_chain->class == FFUNC || a_chain->class == FPROC) { 58914727Sthien /*compat = (compat && fcompat(f_chain, a_chain));*/ 59014727Sthien if ((compat) && (fcompat(f_chain, a_chain))) 59114727Sthien compat = TRUE; 59214727Sthien else compat = FALSE; 5933297Smckusic } 5943297Smckusic if ((a_chain->class != FPROC && f_chain->class != FPROC) && 5953297Smckusic (a_chain->type != f_chain->type)) { 5963297Smckusic error("Type of %s parameter %s of %s declared on line %d is not identical", 5973297Smckusic parnam(f_chain->class), f_chain->symbol, 59814727Sthien formal->symbol, (char *) linenum(formal)); 5993297Smckusic cerror("to type of %s parameter %s of %s declared on line %d", 6003297Smckusic parnam(a_chain->class), a_chain->symbol, 60114727Sthien actual->symbol, (char *) linenum(actual)); 6023297Smckusic compat = FALSE; 6033297Smckusic } 6043297Smckusic } 6053297Smckusic if (a_chain != NIL) { 6063297Smckusic error("%s %s declared on line %d has fewer arguments than", 6073297Smckusic parnam(formal->class), formal->symbol, 60814727Sthien (char *) linenum(formal)); 6093297Smckusic cerror("%s %s declared on line %d", 6103297Smckusic parnam(actual->class), actual->symbol, 61114727Sthien (char *) linenum(actual)); 6123297Smckusic return FALSE; 6133297Smckusic } 6143297Smckusic return compat; 6153297Smckusic } 6163297Smckusic 6173297Smckusic char * 6183297Smckusic parnam(nltype) 6193297Smckusic int nltype; 6203297Smckusic { 6213297Smckusic switch(nltype) { 6223297Smckusic case REF: 6233297Smckusic return "var"; 6243297Smckusic case VAR: 6253297Smckusic return "value"; 6263297Smckusic case FUNC: 6273297Smckusic case FFUNC: 6283297Smckusic return "function"; 6293297Smckusic case PROC: 6303297Smckusic case FPROC: 6313297Smckusic return "procedure"; 6323297Smckusic default: 6333297Smckusic return "SNARK"; 6343297Smckusic } 6353297Smckusic } 6363297Smckusic 63714727Sthien struct nl *plist(p) 6383297Smckusic struct nl *p; 6393297Smckusic { 6403297Smckusic switch (p->class) { 6413297Smckusic case FFUNC: 6423297Smckusic case FPROC: 6433297Smckusic return p->ptr[ NL_FCHAIN ]; 6443297Smckusic case PROC: 6453297Smckusic case FUNC: 6463297Smckusic return p->chain; 6473297Smckusic default: 64814727Sthien { 64914727Sthien panic("plist"); 65014727Sthien return(NLNIL); /* this is here only so lint won't complain 65114727Sthien panic actually aborts */ 65214727Sthien } 65314727Sthien 6543297Smckusic } 6553297Smckusic } 6563297Smckusic 6573297Smckusic linenum(p) 6583297Smckusic struct nl *p; 6593297Smckusic { 6603297Smckusic if (p->class == FUNC) 6613297Smckusic return p->ptr[NL_FVAR]->value[NL_LINENO]; 6623297Smckusic return p->value[NL_LINENO]; 6633297Smckusic } 664