* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)callproc.c 8.1 (Berkeley) %G%";
* Evaluate a call to a procedure.
* This file is a botch as far as modularity is concerned.
* In fact, FIXME, it does not work on either the Vax or Tahoe
* at this point (Sep 22, 1988). It possibly doesn't work because
* the ptrace interface never sets "pc" back into the interpreter's
* program counter location.
* Due to portability changes
* in px for ANSI C, it is now even further broken, since the operand
* stack is no longer the system stack and since the interpreter's
* "pc" that we see is never read by the interpreter. We could fix
* this, and increase the modularity, by:
* * changing this whole module to build a string of bytecodes
* that would: push a series of constant parameters, then call a
* procedure, then take a breakpoint.
* * Having px allocate a place for us to do this, and pass us the
* address of this (otherwise unused) variable.
* * Creating an entry point into the px interpreter which would
* pick up the pc value from "*addrpc" and then enter the main loop.
* Currently we never pick up *addrpc for speed.
* * Fix the code below to use the new entry point rather than "loopaddr".
* But I suspect this code is dead enough that nobody will ever get
* around to it. -- gnu@toad.com, 22Sep88
#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
)
register int tmpsp
, tmptmp
;
extern BOOLEAN shouldrestart
;
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 hopefully keeps stack aligned, so we won't bother
* aligning it afterwards, neither will we align process->sp
* after subtracting args_size.
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 or 11 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
[11] = process
->sp
;
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.
/* this should be done somewhere else, but... */
push(BOOLEAN
, isstopped
);
process
->reg
[12] = pc
+ ENDOFF
;
process
->reg
[11] = pc
+ ENDOFF
;
* Pop back to the real world.
isstopped
= pop(BOOLEAN
);
p
->reg
[12] = pc
+ 1 + ENDOFF
;
if (filename
!= cursource
) {