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