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