BSD 4_3 release
[unix-history] / usr / src / ucb / pascal / pdx / runtime / frame.c
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
static char sccsid[] = "@(#)frame.c 5.1 (Berkeley) 6/6/85";
#endif not lint
/*
* Activation record handling.
*
* The routines curframe and nextframe cheat by using a global copy
* of the display. This means there can't be multiple instances of
* them active at the same time and nextframe won't work in arbitrary cases.
*
* This could be solved by putting the display copy into the FRAME structure,
* but I didn't feel like doing this. The idea is that they be used
* in looping through all frames, if I had generators I would use them.
*/
#include "defs.h"
#include "runtime.h"
#include "machine.h"
#include "process.h"
#include "sym.h"
#include "object.h"
#include "mappings.h"
#include "process/pxinfo.h"
#include "frame.rep"
/*
* Return a pointer to the current activation record.
* Return NIL if currently in the main program.
* The storage is static.
*/
#define MAXDEPTH 7
#define dispblk(dp) ((dp - DISPLAY) / 2)
LOCAL ADDRESS *display[MAXDEPTH];
LOCAL int dispindex;
FRAME *curframe()
{
static FRAME frame;
FRAME *frp;
ADDRESS *dp, *disp;
int i;
frp = &frame;
dp = curdp();
disp = contents(dp);
if (dispblk(dp) <= MAINBLK) {
return NIL;
} else {
getframe(frp, disp);
for (i = 1; i < MAXDEPTH; i++) {
display[i] = dispval(i);
}
dispindex = dispblk(dp);
return frp;
}
}
/*
* Return a pointer to the next activation record up the stack.
* Return NIL if there is none.
* Writes over space pointed to by given argument.
*/
FRAME *nextframe(frp)
FRAME *frp;
{
ADDRESS *fp;
if (dispblk(frp->save_dp) <= MAINBLK) {
return(NIL);
} else {
display[dispindex] = frp->save_disp;
dispindex = dispblk(frp->save_dp);
fp = display[dispindex];
getframe(frp, fp);
return(frp);
}
}
/*
* Return the frame associated with the given function.
*/
FRAME *findframe(f)
SYM *f;
{
static FRAME frame;
FRAME *frp, *prevfrp;
frame.save_dp = curdp();
frame.save_disp = contents(frame.save_dp);
prevfrp = &frame;
for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
if (whatblock(entry(frp)) == f) {
return frp;
}
*prevfrp = *frp;
}
if (f == program) {
return prevfrp;
} else {
return NIL;
}
}
/*
* Get the activation record associated with the given display pointer.
*/
LOCAL getframe(frp, disp)
FRAME *frp;
ADDRESS *disp;
{
if (disp == NIL) {
panic("bad disp in getframe");
}
dread(frp, disp, sizeof(FRAME));
frp->save_pc -= ENDOFF;
}
/*
* Return the address of the display in the px process for the given block.
*/
ADDRESS *dispval(b)
int b;
{
ADDRESS *r;
dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
return r;
}
/*
* Return the current display pointer.
*/
ADDRESS *curdp()
{
ADDRESS *r;
dread(&r, (ADDRESS) DP, sizeof(r));
return r;
}
/*
* Return the contents of the given display pointer.
*/
ADDRESS *contents(dp)
ADDRESS *dp;
{
ADDRESS *r;
dread(&r, (ADDRESS) dp, sizeof(r));
return r;
}
/*
* Return the px stack address associated with a given frame pointer.
* Actually, to confuse the issue we want the stack address of the
* frame one up from the given one.
*/
ADDRESS stkaddr(frp, b)
FRAME *frp;
int b;
{
return (ADDRESS) display[b];
}