/* Copyright (c) 1982 Regents of the University of California */
static char sccsid
[] = "@(#)callproc.c 1.2 %G%";
* Evaluate a call to a procedure.
* This file is a botch as far as modularity is concerned.
#include "process/process.rep"
#include "process/pxinfo.h"
* Controlling logic of procedure calling.
* Calling a procedure before ever executing the program must
callproc(procnode
, arglist
)
curline
= firstline(program
);
proc
= procnode
->nameval
;
error("\"%s\" is not a procedure or function", proc
->symbol
);
pushenv(proc
->symvalue
.funcv
.codeloc
);
* Push the arguments on the process' stack. We do this by first
* evaluating them on the "eval" stack, then copying into the process'
LOCAL
pushargs(proc
, arglist
)
evalargs(proc
->symbol
, proc
->chain
, arglist
);
process
->sp
-= args_size
;
dwrite(savesp
, process
->sp
, args_size
);
* Evaluate arguments right-to-left because the eval stack
* grows up, px's stack grows down.
LOCAL
evalargs(procname
, arg
, explist
)
error("too many parameters to \"%s\"", procname
);
} else if (explist
== NIL
) {
error("not enough parameters to \"%s\"", procname
);
if (explist
->op
!= O_COMMA
) {
panic("evalargs: arglist missing comma");
evalargs(procname
, arg
->chain
, explist
->right
);
if (!compatible(arg
->type
, exp
->nodetype
)) {
trerror("%t is not the same type as parameter \"%s\"",
error("variable expected for parameter \"%s\"", arg
->symbol
);
* Simulate a CALL instruction by pushing the appropriate
* stack frame information.
* Massage register 10 appropriately since it contains the
retaddr
= program
->symvalue
.funcv
.codeloc
;
* This stuff is set by the callee, just here to take up space.
callframe
.save_loc
= NIL
;
callframe
.save_disp
= NIL
;
* This is the useful stuff.
callframe
.save_dp
= curdp();
callframe
.save_pc
= retaddr
+ ENDOFF
;
newdp
= DISPLAY
+ (2 * b
);
dwrite(&newdp
, DP
, sizeof(newdp
));
process
->sp
-= sizeof(callframe
);
dwrite(&callframe
, process
->sp
, sizeof(callframe
));
process
->reg
[10] = process
->sp
;
* Execute the procedure. This routine does NOT return because it
* calls "cont", which doesn't return. We set a CALLPROC breakpoint
* at "retaddr", the address where the called routine will return.
* The action for a CALLPROC is to call "procreturn" where we restore
addbp(retaddr
, CALLPROC
, f
, NIL
, NIL
, 0);
printf("%s returns ", f
->symbol
);
dread(sp
, process
->sp
, len
);
printf("successfully\n");
* Push the current environment.
* This involves both saving pdx and interpreter values.
* LOOPADDR is the address of the main interpreter loop.
push(BOOLEAN
, isstopped
);
process
->reg
[11] = pc
+ ENDOFF
;
* Pop back to the real world.
isstopped
= pop(BOOLEAN
);
if (filename
!= cursource
) {