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