1*5517Slinton /* Copyright (c) 1982 Regents of the University of California */
2*5517Slinton 
3*5517Slinton static char sccsid[] = "@(#)frame.c 1.1 01/18/82";
4*5517Slinton 
5*5517Slinton /*
6*5517Slinton  * Activation record handling.
7*5517Slinton  *
8*5517Slinton  * The routines curframe and nextframe cheat by using a global copy
9*5517Slinton  * of the display.  This means there can't be multiple instances of
10*5517Slinton  * them active at the same time and nextframe won't work in arbitrary cases.
11*5517Slinton  *
12*5517Slinton  * This could be solved by putting the display copy into the FRAME structure,
13*5517Slinton  * but I didn't feel like doing this.  The idea is that they be used
14*5517Slinton  * in looping through all frames, if I had generators I would use them.
15*5517Slinton  */
16*5517Slinton 
17*5517Slinton #include "defs.h"
18*5517Slinton #include "runtime.h"
19*5517Slinton #include "machine.h"
20*5517Slinton #include "process.h"
21*5517Slinton #include "sym.h"
22*5517Slinton #include "object.h"
23*5517Slinton #include "mappings.h"
24*5517Slinton #include "process/pxinfo.h"
25*5517Slinton #include "frame.rep"
26*5517Slinton 
27*5517Slinton /*
28*5517Slinton  * Return a pointer to the current activation record.
29*5517Slinton  * Return NIL if currently in the main program.
30*5517Slinton  * The storage is static.
31*5517Slinton  */
32*5517Slinton 
33*5517Slinton #define MAXDEPTH 7
34*5517Slinton #define dispblk(dp)		((dp - DISPLAY) / 2)
35*5517Slinton 
36*5517Slinton LOCAL ADDRESS *display[MAXDEPTH];
37*5517Slinton LOCAL int dispindex;
38*5517Slinton 
39*5517Slinton FRAME *curframe()
40*5517Slinton {
41*5517Slinton 	static FRAME frame;
42*5517Slinton 	FRAME *frp;
43*5517Slinton 	ADDRESS *dp, *disp;
44*5517Slinton 	int i;
45*5517Slinton 
46*5517Slinton 	frp = &frame;
47*5517Slinton 	dp = curdp();
48*5517Slinton 	disp = contents(dp);
49*5517Slinton 	if (dispblk(dp) <= MAINBLK) {
50*5517Slinton 		return NIL;
51*5517Slinton 	} else {
52*5517Slinton 		getframe(frp, disp);
53*5517Slinton 		for (i = 1; i < MAXDEPTH; i++) {
54*5517Slinton 			display[i] = dispval(i);
55*5517Slinton 		}
56*5517Slinton 		dispindex = dispblk(dp);
57*5517Slinton 		return frp;
58*5517Slinton 	}
59*5517Slinton }
60*5517Slinton 
61*5517Slinton /*
62*5517Slinton  * Return a pointer to the next activation record up the stack.
63*5517Slinton  * Return NIL if there is none.
64*5517Slinton  * Writes over space pointed to by given argument.
65*5517Slinton  */
66*5517Slinton 
67*5517Slinton FRAME *nextframe(frp)
68*5517Slinton FRAME *frp;
69*5517Slinton {
70*5517Slinton 	ADDRESS *fp;
71*5517Slinton 
72*5517Slinton 	if (dispblk(frp->save_dp) <= MAINBLK) {
73*5517Slinton 		return(NIL);
74*5517Slinton 	} else {
75*5517Slinton 		display[dispindex] = frp->save_disp;
76*5517Slinton 		dispindex = dispblk(frp->save_dp);
77*5517Slinton 		fp = display[dispindex];
78*5517Slinton 		getframe(frp, fp);
79*5517Slinton 		return(frp);
80*5517Slinton 	}
81*5517Slinton }
82*5517Slinton 
83*5517Slinton /*
84*5517Slinton  * Return the frame associated with the given function.
85*5517Slinton  */
86*5517Slinton 
87*5517Slinton FRAME *findframe(f)
88*5517Slinton SYM *f;
89*5517Slinton {
90*5517Slinton 	static FRAME frame;
91*5517Slinton 	FRAME *frp, *prevfrp;
92*5517Slinton 
93*5517Slinton 	frame.save_dp = curdp();
94*5517Slinton 	frame.save_disp = contents(frame.save_dp);
95*5517Slinton 	prevfrp = &frame;
96*5517Slinton 	for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
97*5517Slinton 		if (whatblock(entry(frp)) == f) {
98*5517Slinton 			return frp;
99*5517Slinton 		}
100*5517Slinton 		*prevfrp = *frp;
101*5517Slinton 	}
102*5517Slinton 	if (f == program) {
103*5517Slinton 		return prevfrp;
104*5517Slinton 	} else {
105*5517Slinton 		return NIL;
106*5517Slinton 	}
107*5517Slinton }
108*5517Slinton 
109*5517Slinton /*
110*5517Slinton  * Get the activation record associated with the given display pointer.
111*5517Slinton  */
112*5517Slinton 
113*5517Slinton LOCAL getframe(frp, disp)
114*5517Slinton FRAME *frp;
115*5517Slinton ADDRESS *disp;
116*5517Slinton {
117*5517Slinton 	if (disp == NIL) {
118*5517Slinton 		panic("bad disp in getframe");
119*5517Slinton 	}
120*5517Slinton 	dread(frp, disp, sizeof(FRAME));
121*5517Slinton 	frp->save_pc -= ENDOFF;
122*5517Slinton }
123*5517Slinton 
124*5517Slinton /*
125*5517Slinton  * Return the address of the display in the px process for the given block.
126*5517Slinton  */
127*5517Slinton 
128*5517Slinton ADDRESS *dispval(b)
129*5517Slinton int b;
130*5517Slinton {
131*5517Slinton 	ADDRESS *r;
132*5517Slinton 
133*5517Slinton 	dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
134*5517Slinton 	return r;
135*5517Slinton }
136*5517Slinton 
137*5517Slinton /*
138*5517Slinton  * Return the current display pointer.
139*5517Slinton  */
140*5517Slinton 
141*5517Slinton ADDRESS *curdp()
142*5517Slinton {
143*5517Slinton 	ADDRESS *r;
144*5517Slinton 
145*5517Slinton 	dread(&r, (ADDRESS) DP, sizeof(r));
146*5517Slinton 	return r;
147*5517Slinton }
148*5517Slinton 
149*5517Slinton /*
150*5517Slinton  * Return the contents of the given display pointer.
151*5517Slinton  */
152*5517Slinton 
153*5517Slinton ADDRESS *contents(dp)
154*5517Slinton ADDRESS *dp;
155*5517Slinton {
156*5517Slinton 	ADDRESS *r;
157*5517Slinton 
158*5517Slinton 	dread(&r, (ADDRESS) dp, sizeof(r));
159*5517Slinton 	return r;
160*5517Slinton }
161*5517Slinton 
162*5517Slinton /*
163*5517Slinton  * Return the px stack address associated with a given frame pointer.
164*5517Slinton  * Actually, to confuse the issue we want the stack address of the
165*5517Slinton  * frame one up from the given one.
166*5517Slinton  */
167*5517Slinton 
168*5517Slinton ADDRESS stkaddr(frp, b)
169*5517Slinton FRAME *frp;
170*5517Slinton int b;
171*5517Slinton {
172*5517Slinton 	return (ADDRESS) display[b];
173*5517Slinton }
174