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.1 (Berkeley) 06/06/85";
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 
33 /*
34  * Return a pointer to the current activation record.
35  * Return NIL if currently in the main program.
36  * The storage is static.
37  */
38 
39 #define MAXDEPTH 7
40 #define dispblk(dp)		((dp - DISPLAY) / 2)
41 
42 LOCAL ADDRESS *display[MAXDEPTH];
43 LOCAL int dispindex;
44 
45 FRAME *curframe()
46 {
47 	static FRAME frame;
48 	FRAME *frp;
49 	ADDRESS *dp, *disp;
50 	int i;
51 
52 	frp = &frame;
53 	dp = curdp();
54 	disp = contents(dp);
55 	if (dispblk(dp) <= MAINBLK) {
56 		return NIL;
57 	} else {
58 		getframe(frp, disp);
59 		for (i = 1; i < MAXDEPTH; i++) {
60 			display[i] = dispval(i);
61 		}
62 		dispindex = dispblk(dp);
63 		return frp;
64 	}
65 }
66 
67 /*
68  * Return a pointer to the next activation record up the stack.
69  * Return NIL if there is none.
70  * Writes over space pointed to by given argument.
71  */
72 
73 FRAME *nextframe(frp)
74 FRAME *frp;
75 {
76 	ADDRESS *fp;
77 
78 	if (dispblk(frp->save_dp) <= MAINBLK) {
79 		return(NIL);
80 	} else {
81 		display[dispindex] = frp->save_disp;
82 		dispindex = dispblk(frp->save_dp);
83 		fp = display[dispindex];
84 		getframe(frp, fp);
85 		return(frp);
86 	}
87 }
88 
89 /*
90  * Return the frame associated with the given function.
91  */
92 
93 FRAME *findframe(f)
94 SYM *f;
95 {
96 	static FRAME frame;
97 	FRAME *frp, *prevfrp;
98 
99 	frame.save_dp = curdp();
100 	frame.save_disp = contents(frame.save_dp);
101 	prevfrp = &frame;
102 	for (frp = curframe(); frp != NIL; frp = nextframe(frp)) {
103 		if (whatblock(entry(frp)) == f) {
104 			return frp;
105 		}
106 		*prevfrp = *frp;
107 	}
108 	if (f == program) {
109 		return prevfrp;
110 	} else {
111 		return NIL;
112 	}
113 }
114 
115 /*
116  * Get the activation record associated with the given display pointer.
117  */
118 
119 LOCAL getframe(frp, disp)
120 FRAME *frp;
121 ADDRESS *disp;
122 {
123 	if (disp == NIL) {
124 		panic("bad disp in getframe");
125 	}
126 	dread(frp, disp, sizeof(FRAME));
127 	frp->save_pc -= ENDOFF;
128 }
129 
130 /*
131  * Return the address of the display in the px process for the given block.
132  */
133 
134 ADDRESS *dispval(b)
135 int b;
136 {
137 	ADDRESS *r;
138 
139 	dread(&r, (ADDRESS) (DISPLAY + 2*b), sizeof(r));
140 	return r;
141 }
142 
143 /*
144  * Return the current display pointer.
145  */
146 
147 ADDRESS *curdp()
148 {
149 	ADDRESS *r;
150 
151 	dread(&r, (ADDRESS) DP, sizeof(r));
152 	return r;
153 }
154 
155 /*
156  * Return the contents of the given display pointer.
157  */
158 
159 ADDRESS *contents(dp)
160 ADDRESS *dp;
161 {
162 	ADDRESS *r;
163 
164 	dread(&r, (ADDRESS) dp, sizeof(r));
165 	return r;
166 }
167 
168 /*
169  * Return the px stack address associated with a given frame pointer.
170  * Actually, to confuse the issue we want the stack address of the
171  * frame one up from the given one.
172  */
173 
174 ADDRESS stkaddr(frp, b)
175 FRAME *frp;
176 int b;
177 {
178 	return (ADDRESS) display[b];
179 }
180