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