148095Sbostic /*-
2*62145Sbostic  * Copyright (c) 1980, 1993
3*62145Sbostic  *	The Regents of the University of California.  All rights reserved.
448095Sbostic  *
548095Sbostic  * %sccs.include.redist.c%
622519Sdist  */
75517Slinton 
822519Sdist #ifndef lint
9*62145Sbostic static char sccsid[] = "@(#)frame.c	8.1 (Berkeley) 06/06/93";
1048095Sbostic #endif /* not lint */
115517Slinton 
125517Slinton /*
135517Slinton  * Activation record handling.
145517Slinton  *
155517Slinton  * The routines curframe and nextframe cheat by using a global copy
165517Slinton  * of the display.  This means there can't be multiple instances of
175517Slinton  * them active at the same time and nextframe won't work in arbitrary cases.
185517Slinton  *
195517Slinton  * This could be solved by putting the display copy into the FRAME structure,
205517Slinton  * but I didn't feel like doing this.  The idea is that they be used
215517Slinton  * in looping through all frames, if I had generators I would use them.
225517Slinton  */
235517Slinton 
245517Slinton #include "defs.h"
255517Slinton #include "runtime.h"
265517Slinton #include "machine.h"
275517Slinton #include "process.h"
285517Slinton #include "sym.h"
295517Slinton #include "object.h"
305517Slinton #include "mappings.h"
315517Slinton #include "process/pxinfo.h"
325517Slinton #include "frame.rep"
3330849Smckusick #include "process/process.rep"
345517Slinton 
355517Slinton /*
365517Slinton  * Return a pointer to the current activation record.
375517Slinton  * Return NIL if currently in the main program.
385517Slinton  * The storage is static.
395517Slinton  */
405517Slinton 
415517Slinton #define MAXDEPTH 7
425517Slinton #define dispblk(dp)		((dp - DISPLAY) / 2)
435517Slinton 
445517Slinton LOCAL ADDRESS *display[MAXDEPTH];
455517Slinton LOCAL int dispindex;
465517Slinton 
curframe()475517Slinton FRAME *curframe()
485517Slinton {
495517Slinton 	static FRAME frame;
505517Slinton 	FRAME *frp;
515517Slinton 	ADDRESS *dp, *disp;
525517Slinton 	int i;
535517Slinton 
545517Slinton 	frp = &frame;
555517Slinton 	dp = curdp();
565517Slinton 	disp = contents(dp);
575517Slinton 	if (dispblk(dp) <= MAINBLK) {
585517Slinton 		return NIL;
595517Slinton 	} else {
605517Slinton 		getframe(frp, disp);
615517Slinton 		for (i = 1; i < MAXDEPTH; i++) {
625517Slinton 			display[i] = dispval(i);
635517Slinton 		}
645517Slinton 		dispindex = dispblk(dp);
655517Slinton 		return frp;
665517Slinton 	}
675517Slinton }
685517Slinton 
695517Slinton /*
705517Slinton  * Return a pointer to the next activation record up the stack.
715517Slinton  * Return NIL if there is none.
725517Slinton  * Writes over space pointed to by given argument.
735517Slinton  */
745517Slinton 
nextframe(frp)755517Slinton FRAME *nextframe(frp)
765517Slinton FRAME *frp;
775517Slinton {
785517Slinton 	ADDRESS *fp;
795517Slinton 
805517Slinton 	if (dispblk(frp->save_dp) <= MAINBLK) {
815517Slinton 		return(NIL);
825517Slinton 	} else {
835517Slinton 		display[dispindex] = frp->save_disp;
845517Slinton 		dispindex = dispblk(frp->save_dp);
855517Slinton 		fp = display[dispindex];
865517Slinton 		getframe(frp, fp);
875517Slinton 		return(frp);
885517Slinton 	}
895517Slinton }
905517Slinton 
915517Slinton /*
925517Slinton  * Return the frame associated with the given function.
935517Slinton  */
945517Slinton 
findframe(f)955517Slinton FRAME *findframe(f)
965517Slinton SYM *f;
975517Slinton {
985517Slinton 	static FRAME frame;
995517Slinton 	FRAME *frp, *prevfrp;
1005517Slinton 
1015517Slinton 	frame.save_dp = curdp();
1025517Slinton 	frame.save_disp = contents(frame.save_dp);
1035517Slinton 	prevfrp = &frame;
1045517Slinton 	for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
1055517Slinton 		if (whatblock(entry(frp)) == f) {
1065517Slinton 			return frp;
1075517Slinton 		}
1085517Slinton 		*prevfrp = *frp;
1095517Slinton 	}
1105517Slinton 	if (f == program) {
1115517Slinton 		return prevfrp;
1125517Slinton 	} else {
1135517Slinton 		return NIL;
1145517Slinton 	}
1155517Slinton }
1165517Slinton 
1175517Slinton /*
1185517Slinton  * Get the activation record associated with the given display pointer.
1195517Slinton  */
1205517Slinton 
getframe(frp,disp)1215517Slinton LOCAL getframe(frp, disp)
1225517Slinton FRAME *frp;
1235517Slinton ADDRESS *disp;
1245517Slinton {
1255517Slinton 	if (disp == NIL) {
1265517Slinton 		panic("bad disp in getframe");
1275517Slinton 	}
1285517Slinton 	dread(frp, disp, sizeof(FRAME));
1295517Slinton 	frp->save_pc -= ENDOFF;
1305517Slinton }
1315517Slinton 
1325517Slinton /*
1335517Slinton  * Return the address of the display in the px process for the given block.
1345517Slinton  */
1355517Slinton 
dispval(b)1365517Slinton ADDRESS *dispval(b)
1375517Slinton int b;
1385517Slinton {
1395517Slinton 	ADDRESS *r;
1405517Slinton 
1415517Slinton 	dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
1425517Slinton 	return r;
1435517Slinton }
1445517Slinton 
1455517Slinton /*
1465517Slinton  * Return the current display pointer.
1475517Slinton  */
1485517Slinton 
curdp()1495517Slinton ADDRESS *curdp()
1505517Slinton {
1515517Slinton 	ADDRESS *r;
1525517Slinton 
1535517Slinton 	dread(&r, (ADDRESS) DP, sizeof(r));
1545517Slinton 	return r;
1555517Slinton }
1565517Slinton 
1575517Slinton /*
1585517Slinton  * Return the contents of the given display pointer.
1595517Slinton  */
1605517Slinton 
contents(dp)1615517Slinton ADDRESS *contents(dp)
1625517Slinton ADDRESS *dp;
1635517Slinton {
1645517Slinton 	ADDRESS *r;
1655517Slinton 
1665517Slinton 	dread(&r, (ADDRESS) dp, sizeof(r));
1675517Slinton 	return r;
1685517Slinton }
1695517Slinton 
1705517Slinton /*
1715517Slinton  * Return the px stack address associated with a given frame pointer.
1725517Slinton  * Actually, to confuse the issue we want the stack address of the
1735517Slinton  * frame one up from the given one.
1745517Slinton  */
1755517Slinton 
stkaddr(frp,b)1765517Slinton ADDRESS stkaddr(frp, b)
1775517Slinton FRAME *frp;
1785517Slinton int b;
1795517Slinton {
1805517Slinton 	return (ADDRESS) display[b];
1815517Slinton }
182