1*745Speter /* Copyright (c) 1979 Regents of the University of California */ 2*745Speter 3*745Speter static char sccsid[] = "@(#)call.c 1.1 08/27/80"; 4*745Speter 5*745Speter #include "whoami.h" 6*745Speter #include "0.h" 7*745Speter #include "tree.h" 8*745Speter #include "opcode.h" 9*745Speter #include "objfmt.h" 10*745Speter #ifdef PC 11*745Speter # include "pc.h" 12*745Speter # include "pcops.h" 13*745Speter #endif PC 14*745Speter 15*745Speter /* 16*745Speter * Call generates code for calls to 17*745Speter * user defined procedures and functions 18*745Speter * and is called by proc and funccod. 19*745Speter * P is the result of the lookup 20*745Speter * of the procedure/function symbol, 21*745Speter * and porf is PROC or FUNC. 22*745Speter * Psbn is the block number of p. 23*745Speter */ 24*745Speter struct nl * 25*745Speter call(p, argv, porf, psbn) 26*745Speter struct nl *p; 27*745Speter int *argv, porf, psbn; 28*745Speter { 29*745Speter register struct nl *p1, *q; 30*745Speter int *r; 31*745Speter 32*745Speter # ifdef PC 33*745Speter long temp; 34*745Speter int firsttime; 35*745Speter int rettype; 36*745Speter # endif PC 37*745Speter 38*745Speter # ifdef OBJ 39*745Speter if (porf == FUNC) 40*745Speter /* 41*745Speter * Push some space 42*745Speter * for the function return type 43*745Speter */ 44*745Speter put2(O_PUSH, even(-width(p->type))); 45*745Speter # endif OBJ 46*745Speter # ifdef PC 47*745Speter if ( porf == FUNC ) { 48*745Speter switch( classify( p -> type ) ) { 49*745Speter case TSTR: 50*745Speter case TSET: 51*745Speter case TREC: 52*745Speter case TFILE: 53*745Speter case TARY: 54*745Speter temp = sizes[ cbn ].om_off -= width( p -> type ); 55*745Speter putlbracket( ftnno , -sizes[cbn].om_off ); 56*745Speter if (sizes[cbn].om_off < sizes[cbn].om_max) { 57*745Speter sizes[cbn].om_max = sizes[cbn].om_off; 58*745Speter } 59*745Speter putRV( 0 , cbn , temp , P2STRTY ); 60*745Speter } 61*745Speter } 62*745Speter { 63*745Speter char extname[ BUFSIZ ]; 64*745Speter char *starthere; 65*745Speter int funcbn; 66*745Speter int i; 67*745Speter 68*745Speter starthere = &extname[0]; 69*745Speter funcbn = p -> nl_block & 037; 70*745Speter for ( i = 1 ; i < funcbn ; i++ ) { 71*745Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 72*745Speter starthere += strlen( enclosing[ i ] ) + 1; 73*745Speter } 74*745Speter sprintf( starthere , EXTFORMAT , p -> symbol ); 75*745Speter starthere += strlen( p -> symbol ) + 1; 76*745Speter if ( starthere >= &extname[ BUFSIZ ] ) { 77*745Speter panic( "call namelength" ); 78*745Speter } 79*745Speter putleaf( P2ICON , 0 , 0 , p2type( p ) , extname ); 80*745Speter } 81*745Speter firsttime = TRUE; 82*745Speter # endif PC 83*745Speter /* 84*745Speter * Loop and process each of 85*745Speter * arguments to the proc/func. 86*745Speter */ 87*745Speter for (p1 = p->chain; p1 != NIL; p1 = p1->chain) { 88*745Speter if (argv == NIL) { 89*745Speter error("Not enough arguments to %s", p->symbol); 90*745Speter return (NIL); 91*745Speter } 92*745Speter switch (p1->class) { 93*745Speter case REF: 94*745Speter /* 95*745Speter * Var parameter 96*745Speter */ 97*745Speter r = argv[1]; 98*745Speter if (r != NIL && r[0] != T_VAR) { 99*745Speter error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 100*745Speter break; 101*745Speter } 102*745Speter q = lvalue( (int *) argv[1], MOD , LREQ ); 103*745Speter if (q == NIL) 104*745Speter break; 105*745Speter if (q != p1->type) { 106*745Speter error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 107*745Speter break; 108*745Speter } 109*745Speter break; 110*745Speter case VAR: 111*745Speter /* 112*745Speter * Value parameter 113*745Speter */ 114*745Speter # ifdef OBJ 115*745Speter q = rvalue(argv[1], p1->type , RREQ ); 116*745Speter # endif OBJ 117*745Speter # ifdef PC 118*745Speter /* 119*745Speter * structure arguments require lvalues, 120*745Speter * scalars use rvalue. 121*745Speter */ 122*745Speter switch( classify( p1 -> type ) ) { 123*745Speter case TFILE: 124*745Speter case TARY: 125*745Speter case TREC: 126*745Speter case TSET: 127*745Speter case TSTR: 128*745Speter q = rvalue( argv[1] , p1 -> type , LREQ ); 129*745Speter break; 130*745Speter case TINT: 131*745Speter case TSCAL: 132*745Speter case TBOOL: 133*745Speter case TCHAR: 134*745Speter precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 135*745Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 136*745Speter postcheck( p1 -> type ); 137*745Speter break; 138*745Speter /* 139*745Speter * and fall through 140*745Speter */ 141*745Speter default: 142*745Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 143*745Speter break; 144*745Speter } 145*745Speter # endif PC 146*745Speter if (q == NIL) 147*745Speter break; 148*745Speter if (incompat(q, p1->type, argv[1])) { 149*745Speter cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 150*745Speter break; 151*745Speter } 152*745Speter # ifdef OBJ 153*745Speter if (isa(p1->type, "bcsi")) 154*745Speter rangechk(p1->type, q); 155*745Speter if (q->class != STR) 156*745Speter convert(q, p1->type); 157*745Speter # endif OBJ 158*745Speter # ifdef PC 159*745Speter switch( classify( p1 -> type ) ) { 160*745Speter case TFILE: 161*745Speter case TARY: 162*745Speter case TREC: 163*745Speter case TSET: 164*745Speter case TSTR: 165*745Speter putstrop( P2STARG 166*745Speter , p2type( p1 -> type ) 167*745Speter , lwidth( p1 -> type ) 168*745Speter , align( p1 -> type ) ); 169*745Speter } 170*745Speter # endif PC 171*745Speter break; 172*745Speter default: 173*745Speter panic("call"); 174*745Speter } 175*745Speter # ifdef PC 176*745Speter /* 177*745Speter * if this is the nth (>1) argument, 178*745Speter * hang it on the left linear list of arguments 179*745Speter */ 180*745Speter if ( firsttime ) { 181*745Speter firsttime = FALSE; 182*745Speter } else { 183*745Speter putop( P2LISTOP , P2INT ); 184*745Speter } 185*745Speter # endif PC 186*745Speter argv = argv[2]; 187*745Speter } 188*745Speter if (argv != NIL) { 189*745Speter error("Too many arguments to %s", p->symbol); 190*745Speter rvlist(argv); 191*745Speter return (NIL); 192*745Speter } 193*745Speter # ifdef OBJ 194*745Speter put2(O_CALL | psbn << 8+INDX, p->entloc); 195*745Speter put2(O_POP, p->value[NL_OFFS]-DPOFF2); 196*745Speter # endif OBJ 197*745Speter # ifdef PC 198*745Speter if ( porf == FUNC ) { 199*745Speter rettype = p2type( p -> type ); 200*745Speter switch ( classify( p -> type ) ) { 201*745Speter case TBOOL: 202*745Speter case TCHAR: 203*745Speter case TINT: 204*745Speter case TSCAL: 205*745Speter case TDOUBLE: 206*745Speter case TPTR: 207*745Speter if ( p -> chain == NIL ) { 208*745Speter putop( P2UNARY P2CALL , rettype ); 209*745Speter } else { 210*745Speter putop( P2CALL , rettype ); 211*745Speter } 212*745Speter break; 213*745Speter default: 214*745Speter if ( p -> chain == NIL ) { 215*745Speter putstrop( P2UNARY P2STCALL 216*745Speter , ADDTYPE( rettype , P2PTR ) 217*745Speter , lwidth( p -> type ) 218*745Speter , align( p -> type ) ); 219*745Speter } else { 220*745Speter putstrop( P2STCALL 221*745Speter , ADDTYPE( rettype , P2PTR ) 222*745Speter , lwidth( p -> type ) 223*745Speter , align( p -> type ) ); 224*745Speter } 225*745Speter putstrop( P2STASG , rettype , lwidth( p -> type ) 226*745Speter , align( p -> type ) ); 227*745Speter putLV( 0 , cbn , temp , rettype ); 228*745Speter putop( P2COMOP , P2INT ); 229*745Speter break; 230*745Speter } 231*745Speter } else { 232*745Speter if ( p -> chain == NIL ) { 233*745Speter putop( P2UNARY P2CALL , P2INT ); 234*745Speter } else { 235*745Speter putop( P2CALL , P2INT ); 236*745Speter } 237*745Speter putdot( filename , line ); 238*745Speter } 239*745Speter # endif PC 240*745Speter return (p->type); 241*745Speter } 242*745Speter 243*745Speter rvlist(al) 244*745Speter register int *al; 245*745Speter { 246*745Speter 247*745Speter for (; al != NIL; al = al[2]) 248*745Speter rvalue( (int *) al[1], NLNIL , RREQ ); 249*745Speter } 250