/* @(#)call.c 2.2 SCCS id keyword */ /* Copyright (c) 1979 Regents of the University of California */ # /* * pi - Pascal interpreter code translator * * Charles Haley, Bill Joy UCB * Version 1.2 November 1978 */ #include "whoami" #include "0.h" #include "tree.h" #include "opcode.h" /* * Call generates code for calls to * user defined procedures and functions * and is called by proc and funccod. * P is the result of the lookup * of the procedure/function symbol, * and porf is PROC or FUNC. * Psbn is the block number of p. */ struct nl * call(p, argv, porf, psbn) struct nl *p; int *argv, porf, psbn; { register struct nl *p1, *q; int *r; if (porf == FUNC) /* * Push some space * for the function return type */ put2(O_PUSH, even(-width(p->type))); /* * Loop and process each of * arguments to the proc/func. */ for (p1 = p->chain; p1 != NIL; p1 = p1->chain) { if (argv == NIL) { error("Not enough arguments to %s", p->symbol); return (NIL); } switch (p1->class) { case REF: /* * Var parameter */ r = argv[1]; if (r != NIL && r[0] != T_VAR) { error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); break; } q = lvalue( (int *) argv[1], MOD); if (q == NIL) break; if (q != p1->type) { error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); break; } break; case VAR: /* * Value parameter */ q = rvalue(argv[1], p1->type); if (q == NIL) break; if (incompat(q, p1->type, argv[1])) { cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); break; } if (isa(p1->type, "bcsi")) rangechk(p1->type, q); if (q->class != STR) convert(q, p1->type); break; default: panic("call"); } argv = argv[2]; } if (argv != NIL) { error("Too many arguments to %s", p->symbol); rvlist(argv); return (NIL); } put2(O_CALL | psbn << 9, p->value[NL_LOC]); put2(O_POP, p->value[NL_OFFS]-DPOFF2); return (p->type); } rvlist(al) register int *al; { for (; al != NIL; al = al[2]) rvalue( (int *) al[1], NLNIL); }