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