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