1*22519Sdist /*
2*22519Sdist  * Copyright (c) 1980 Regents of the University of California.
3*22519Sdist  * All rights reserved.  The Berkeley software License Agreement
4*22519Sdist  * specifies the terms and conditions for redistribution.
5*22519Sdist  */
65517Slinton 
7*22519Sdist #ifndef lint
8*22519Sdist static char sccsid[] = "@(#)frame.c	5.1 (Berkeley) 06/06/85";
9*22519Sdist #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"
325517Slinton 
335517Slinton /*
345517Slinton  * Return a pointer to the current activation record.
355517Slinton  * Return NIL if currently in the main program.
365517Slinton  * The storage is static.
375517Slinton  */
385517Slinton 
395517Slinton #define MAXDEPTH 7
405517Slinton #define dispblk(dp)		((dp - DISPLAY) / 2)
415517Slinton 
425517Slinton LOCAL ADDRESS *display[MAXDEPTH];
435517Slinton LOCAL int dispindex;
445517Slinton 
455517Slinton FRAME *curframe()
465517Slinton {
475517Slinton 	static FRAME frame;
485517Slinton 	FRAME *frp;
495517Slinton 	ADDRESS *dp, *disp;
505517Slinton 	int i;
515517Slinton 
525517Slinton 	frp = &frame;
535517Slinton 	dp = curdp();
545517Slinton 	disp = contents(dp);
555517Slinton 	if (dispblk(dp) <= MAINBLK) {
565517Slinton 		return NIL;
575517Slinton 	} else {
585517Slinton 		getframe(frp, disp);
595517Slinton 		for (i = 1; i < MAXDEPTH; i++) {
605517Slinton 			display[i] = dispval(i);
615517Slinton 		}
625517Slinton 		dispindex = dispblk(dp);
635517Slinton 		return frp;
645517Slinton 	}
655517Slinton }
665517Slinton 
675517Slinton /*
685517Slinton  * Return a pointer to the next activation record up the stack.
695517Slinton  * Return NIL if there is none.
705517Slinton  * Writes over space pointed to by given argument.
715517Slinton  */
725517Slinton 
735517Slinton FRAME *nextframe(frp)
745517Slinton FRAME *frp;
755517Slinton {
765517Slinton 	ADDRESS *fp;
775517Slinton 
785517Slinton 	if (dispblk(frp->save_dp) <= MAINBLK) {
795517Slinton 		return(NIL);
805517Slinton 	} else {
815517Slinton 		display[dispindex] = frp->save_disp;
825517Slinton 		dispindex = dispblk(frp->save_dp);
835517Slinton 		fp = display[dispindex];
845517Slinton 		getframe(frp, fp);
855517Slinton 		return(frp);
865517Slinton 	}
875517Slinton }
885517Slinton 
895517Slinton /*
905517Slinton  * Return the frame associated with the given function.
915517Slinton  */
925517Slinton 
935517Slinton FRAME *findframe(f)
945517Slinton SYM *f;
955517Slinton {
965517Slinton 	static FRAME frame;
975517Slinton 	FRAME *frp, *prevfrp;
985517Slinton 
995517Slinton 	frame.save_dp = curdp();
1005517Slinton 	frame.save_disp = contents(frame.save_dp);
1015517Slinton 	prevfrp = &frame;
1025517Slinton 	for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
1035517Slinton 		if (whatblock(entry(frp)) == f) {
1045517Slinton 			return frp;
1055517Slinton 		}
1065517Slinton 		*prevfrp = *frp;
1075517Slinton 	}
1085517Slinton 	if (f == program) {
1095517Slinton 		return prevfrp;
1105517Slinton 	} else {
1115517Slinton 		return NIL;
1125517Slinton 	}
1135517Slinton }
1145517Slinton 
1155517Slinton /*
1165517Slinton  * Get the activation record associated with the given display pointer.
1175517Slinton  */
1185517Slinton 
1195517Slinton LOCAL getframe(frp, disp)
1205517Slinton FRAME *frp;
1215517Slinton ADDRESS *disp;
1225517Slinton {
1235517Slinton 	if (disp == NIL) {
1245517Slinton 		panic("bad disp in getframe");
1255517Slinton 	}
1265517Slinton 	dread(frp, disp, sizeof(FRAME));
1275517Slinton 	frp->save_pc -= ENDOFF;
1285517Slinton }
1295517Slinton 
1305517Slinton /*
1315517Slinton  * Return the address of the display in the px process for the given block.
1325517Slinton  */
1335517Slinton 
1345517Slinton ADDRESS *dispval(b)
1355517Slinton int b;
1365517Slinton {
1375517Slinton 	ADDRESS *r;
1385517Slinton 
1395517Slinton 	dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
1405517Slinton 	return r;
1415517Slinton }
1425517Slinton 
1435517Slinton /*
1445517Slinton  * Return the current display pointer.
1455517Slinton  */
1465517Slinton 
1475517Slinton ADDRESS *curdp()
1485517Slinton {
1495517Slinton 	ADDRESS *r;
1505517Slinton 
1515517Slinton 	dread(&r, (ADDRESS) DP, sizeof(r));
1525517Slinton 	return r;
1535517Slinton }
1545517Slinton 
1555517Slinton /*
1565517Slinton  * Return the contents of the given display pointer.
1575517Slinton  */
1585517Slinton 
1595517Slinton ADDRESS *contents(dp)
1605517Slinton ADDRESS *dp;
1615517Slinton {
1625517Slinton 	ADDRESS *r;
1635517Slinton 
1645517Slinton 	dread(&r, (ADDRESS) dp, sizeof(r));
1655517Slinton 	return r;
1665517Slinton }
1675517Slinton 
1685517Slinton /*
1695517Slinton  * Return the px stack address associated with a given frame pointer.
1705517Slinton  * Actually, to confuse the issue we want the stack address of the
1715517Slinton  * frame one up from the given one.
1725517Slinton  */
1735517Slinton 
1745517Slinton ADDRESS stkaddr(frp, b)
1755517Slinton FRAME *frp;
1765517Slinton int b;
1775517Slinton {
1785517Slinton 	return (ADDRESS) display[b];
1795517Slinton }
180