+ * Check to see if an expression is correct for a given parameter.
+ * If the given parameter is false, don't worry about type inconsistencies.
+ *
+ * Return whether or not it is ok.
+ */
+
+private boolean chkparam (actual, formal, chk)
+Node actual;
+Symbol formal;
+boolean chk;
+{
+ boolean b;
+
+ b = true;
+ if (chk) {
+ if (formal == nil) {
+ beginerrmsg();
+ fprintf(stderr, "too many parameters");
+ b = false;
+ } else if (not compatible(formal->type, actual->nodetype)) {
+ beginerrmsg();
+ fprintf(stderr, "type mismatch for %s", symname(formal));
+ b = false;
+ }
+ }
+ if (b and formal != nil and
+ isvarparam(formal) and not isopenarray(formal->type) and
+ not (
+ actual->op == O_RVAL or actual->nodetype == t_addr or
+ (
+ actual->op == O_TYPERENAME and
+ (
+ actual->value.arg[0]->op == O_RVAL or
+ actual->value.arg[0]->nodetype == t_addr
+ )
+ )
+ )
+ ) {
+ beginerrmsg();
+ fprintf(stderr, "expected variable, found \"");
+ prtree(stderr, actual);
+ fprintf(stderr, "\"");
+ b = false;
+ }
+ return b;
+}
+
+/*
+ * Pass an expression to a particular parameter.
+ *
+ * Normally we pass either the address or value, but in some cases
+ * (such as C strings) we want to copy the value onto the stack and
+ * pass its address.
+ *
+ * Another special case raised by strings is the possibility that
+ * the actual parameter will be larger than the formal, even with
+ * appropriate type-checking. This occurs because we assume during
+ * evaluation that strings are null-terminated, whereas some languages,
+ * notably Pascal, do not work under that assumption.
+ */
+
+private passparam (actual, formal)
+Node actual;
+Symbol formal;
+{
+ boolean b;
+ Address addr;
+ Stack *savesp;
+ integer actsize, formsize;
+
+ if (formal != nil and isvarparam(formal) and
+ (not isopenarray(formal->type))
+ ) {
+ addr = lval(actual->value.arg[0]);
+ push(Address, addr);
+ } else if (passaddr(formal, actual->nodetype)) {
+ savesp = sp;
+ eval(actual);
+ actsize = sp - savesp;
+ setreg(STKP,
+ reg(STKP) - ((actsize + sizeof(Word) - 1) & ~(sizeof(Word) - 1))
+ );
+ dwrite(savesp, reg(STKP), actsize);
+ sp = savesp;
+ push(Address, reg(STKP));
+ if (formal != nil and isopenarray(formal->type)) {
+ push(integer, actsize div size(formal->type->type));
+ }
+ } else if (formal != nil) {
+ formsize = size(formal);
+ savesp = sp;
+ eval(actual);
+ actsize = sp - savesp;
+ if (actsize > formsize) {
+ sp -= (actsize - formsize);
+ }
+ } else {
+ eval(actual);
+ }
+}
+
+/*
+ * Evaluate an argument list left-to-right.