* Copyright (c) 1980 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)callproc.c 5.4 (Berkeley) 4/16/91";
* 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
) {