1 |
/* |
2 |
* procframe.h: Method interpreter debugger stack frame information. |
3 |
* by Benjamin Allan |
4 |
* March 17, 1998 |
5 |
* Part of ASCEND |
6 |
* Version: $Revision: 1.2 $ |
7 |
* Version control file: $RCSfile: procframe.h,v $ |
8 |
* Date last modified: $Date: 1998/06/16 16:38:49 $ |
9 |
* Last modified by: $Author: mthomas $ |
10 |
* |
11 |
* This file is part of the Ascend Language Interpreter. |
12 |
* |
13 |
* Copyright (C) 1998 Carnegie Mellon University |
14 |
* |
15 |
* The Ascend Language Interpreter is free software; you can |
16 |
* redistribute it and/or modify it under the terms of the GNU |
17 |
* General Public License as published by the Free Software |
18 |
* Foundation; either version 2 of the License, or (at your option) |
19 |
* any later version. |
20 |
* |
21 |
* The Ascend Language Interpreter is distributed in hope that it |
22 |
* will be useful, but WITHOUT ANY WARRANTY; without even the implied |
23 |
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
24 |
* See the GNU General Public License for more details. |
25 |
* |
26 |
* You should have received a copy of the GNU General Public License |
27 |
* along with the program; if not, write to the Free Software |
28 |
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139 USA. Check |
29 |
* the file named COPYING. |
30 |
*/ |
31 |
|
32 |
/** @file |
33 |
* Method interpreter debugger stack frame information. |
34 |
* The data structures in this header should not be passed |
35 |
* through headers except inside gl_lists. This header |
36 |
* should not be accessed except by the interpreter and |
37 |
* interpreter io routines. watchpt.h is the header for |
38 |
* client consumption. |
39 |
* <pre> |
40 |
* When #including procframe.h, make sure these files are #included first: |
41 |
* #include <stdio.h> |
42 |
* #include "utilities/ascConfig.h" |
43 |
* </pre> |
44 |
*/ |
45 |
|
46 |
#ifndef __PROCFRAME_H_SEEN__ |
47 |
#define __PROCFRAME_H_SEEN__ |
48 |
|
49 |
enum FrameMode { |
50 |
FrameInherit, /**< Inherit previous mode when used in Add. */ |
51 |
FrameNormal, /**< Normal operations. Inheritable. */ |
52 |
FrameDebug, /**< Trace operations. Inheritable. */ |
53 |
FrameStart, /**< Not yet supported. Initiate something. */ |
54 |
FrameStep, /**< Not yet supported. Do next statement any scope. */ |
55 |
FrameNext, /**< Not yet supported. Do next instruction this scope. */ |
56 |
FrameDestroyed /**< Severe error if seen. */ |
57 |
}; |
58 |
|
59 |
/** |
60 |
* Because error handling is user defined according to watchpt.h |
61 |
* the following enum is used internally. |
62 |
* External package functions |
63 |
* should return Proc_CallOK, Proc_CallError, |
64 |
* Proc_CallBreak, or Proc_CallContinue. |
65 |
* Error message output is affected by FrameControl. |
66 |
*/ |
67 |
enum FrameControl { |
68 |
FrameOK = 0, /**< Normal return and entry state. */ |
69 |
FrameError, /**< Error return. only the erroneous frame uses this. */ |
70 |
FrameBreak, /**< Break from an enclosing loop. If no enclosing loop |
71 |
exists, will be passed up to calling frame. */ |
72 |
FrameContinue, /**< Skip to next iteration in an enclosing loop. If no |
73 |
enclosing loop exists, will be passed up to calling frame. */ |
74 |
FrameFallthru, /**< Suppress break inside switch processing of cases. */ |
75 |
FrameReturn, /**< Frames above a FrameError or FrameReturn stop & return. |
76 |
Initialize morphs this back to a FrameError for client. */ |
77 |
FrameLoop /**< In the scope of a loop. Valid entry state. */ |
78 |
}; |
79 |
/* keep the above in sync with the internals of FrameControlToString below */ |
80 |
|
81 |
/** |
82 |
* some watch point structures for internal use only. |
83 |
* see watchpt.h for UI watchpoint input structures. |
84 |
*/ |
85 |
struct anywatch { |
86 |
void *key; /**< all watches hash on some sort of unique ptr key */ |
87 |
void *next; /**< all watches are in hash tables. */ |
88 |
void *data; /**< everyone wants to know something. */ |
89 |
unsigned long flags; /**< control bits */ |
90 |
}; |
91 |
|
92 |
struct namewatch { |
93 |
symchar *leafname; |
94 |
struct namewatch *next; |
95 |
struct gl_list_t *where; |
96 |
unsigned long flags; /**< control bits */ |
97 |
}; |
98 |
|
99 |
struct procwatch { |
100 |
symchar *leafname; |
101 |
struct procwatch *next; |
102 |
struct gl_list_t *where; |
103 |
unsigned long flags; /**< control bits */ |
104 |
}; |
105 |
|
106 |
struct statwatch { |
107 |
struct Statement *stat; |
108 |
struct statwatch *next; |
109 |
struct gl_list_t *where; |
110 |
unsigned long flags; /**< control bits */ |
111 |
}; |
112 |
|
113 |
struct varswatch { |
114 |
struct Instance *var; /**< watched var */ |
115 |
struct varswatch *next; |
116 |
struct gl_list_t *where; /**< list of statement/context pairs */ |
117 |
unsigned long flags; /**< control bits */ |
118 |
}; |
119 |
|
120 |
struct typewatch { |
121 |
struct TypeDescription *desc; /**< watched var type */ |
122 |
struct typewatch *next; |
123 |
struct TypeDescription *ancestor; /**< watched ancestor causing this */ |
124 |
unsigned long flags; /**< control bits */ |
125 |
}; |
126 |
|
127 |
/** |
128 |
* Masks are always = 2^N -1 for some N. Such a mask |
129 |
* can be used in hashing a pointer into an array of size 2^N. |
130 |
* N should be even. |
131 |
* Until we run tests, hard to say what the masks should be. |
132 |
* Would expect that VWTMASK may need to be much larger when |
133 |
* debugging very large variables and monitoring for multiple |
134 |
* assignments. |
135 |
* The shift for a given mask 2^N-1 should be 32-(N+2). |
136 |
* Note that an excessive upper bound for N is probably 16 |
137 |
* on a 32 bit hardware with memory considered to cost something. |
138 |
*/ |
139 |
#define NWTMASK 255 |
140 |
#define PWTMASK 255 |
141 |
#define SWTMASK 255 |
142 |
#define TWTMASK 255 |
143 |
#define VWTMASK 255 |
144 |
#define NWTSHIFT 22 |
145 |
#define PWTSHIFT 22 |
146 |
#define SWTSHIFT 22 |
147 |
#define TWTSHIFT 22 |
148 |
#define VWTSHIFT 22 |
149 |
/** The idea here is that pointers (to persistent instances, names, types |
150 |
* and methods, but not stack instances) are unique keys during method |
151 |
* execution, so these can be hashed for more or less linear cost trace |
152 |
* operations. We're hashing things because it's really gross to use |
153 |
* interface ptrs. |
154 |
*/ |
155 |
#define PTRMAGICHASH 1103515245 |
156 |
#define NWTINDEX(p) (((((long) (p))*PTRMAGICHASH) << NWTSHIFT) & NWTMASK) |
157 |
#define PWTINDEX(p) (((((long) (p))*PTRMAGICHASH) << PWTSHIFT) & PWTMASK) |
158 |
#define SWTINDEX(p) (((((long) (p))*PTRMAGICHASH) << SWTSHIFT) & SWTMASK) |
159 |
#define TWTINDEX(p) (((((long) (p))*PTRMAGICHASH) << TWTSHIFT) & TWTMASK) |
160 |
#define VWTINDEX(p) (((((long) (p))*PTRMAGICHASH) << VWTSHIFT) & VWTMASK) |
161 |
|
162 |
struct procDebug { |
163 |
wpflags what; |
164 |
/**< what tells what tables are active. check it, not the table ptrs */ |
165 |
FILE *log; /**< where debugger output should go. probably same as err */ |
166 |
int errcnt; /**< total error messages issued while processing this stack */ |
167 |
struct namewatch **ntab; /**< hash table of leaf names being watched */ |
168 |
struct procwatch **ptab; /**< hash table of proc names being watched */ |
169 |
struct statwatch **stab; /**< hash table of statements being watched */ |
170 |
struct typewatch **ttab; /**< hash table of var types being watched */ |
171 |
struct varswatch **vtab; /**< hash table of variables being watched */ |
172 |
/* above watch tables point at below data spaces unless no break points |
173 |
* of the classes involved are set. If a table is not used, its tab |
174 |
* pointer is left NULL instead of being assigned to its head. |
175 |
*/ |
176 |
struct namewatch *namehead[NWTMASK+1]; |
177 |
struct procwatch *prochead[PWTMASK+1]; |
178 |
struct statwatch *stathead[SWTMASK+1]; |
179 |
struct typewatch *typehead[TWTMASK+1]; |
180 |
struct varswatch *varshead[VWTMASK+1]; |
181 |
}; |
182 |
|
183 |
/** |
184 |
* a procFrame defines the stack information we may carry about while |
185 |
* executing a method call from the interface. It is for the |
186 |
* internal use of initialize.c only. |
187 |
*/ |
188 |
struct procFrame { |
189 |
enum FrameMode m; /**< 0 -> no -> rest of frame data empty */ |
190 |
enum FrameControl flow; /**< flow of control info */ |
191 |
enum Proc_enum ErrNo; /**< last status computed */ |
192 |
int depth; /**< where on the stack. redundant. */ |
193 |
FILE *err; /**< where interactive messages should be sent */ |
194 |
struct Instance *i; /**< scope proc is being executed in. */ |
195 |
char *cname; /**< name of scope by which we got here. */ |
196 |
struct InitProcedure *proc; /**< proc being evaluated. */ |
197 |
struct Statement *stat; /**< statement being evaluated. */ |
198 |
struct procFrame *caller; /**< scope that lead here in execution. |
199 |
* NULL if caller was a user interface. |
200 |
*/ |
201 |
wpflags gen; /**< some general debug options valid |
202 |
* whether or not dbi == NULL. |
203 |
*/ |
204 |
struct procDebug *dbi; /**< points to debugging information which |
205 |
* is shared by all frames in a stack since |
206 |
* debugging is a global activity. |
207 |
* The root frame should create this data. |
208 |
* If NULL, no messaging at all. |
209 |
*/ |
210 |
/* not yet supported: */ |
211 |
struct gl_list_t *locals; /**< local vars simulation list. */ |
212 |
}; |
213 |
|
214 |
/** |
215 |
* Setting this to 1 causes a STOP at the next sensible moment. |
216 |
* UIs access this variable through watchpt.h only. |
217 |
*/ |
218 |
extern int g_procframe_stop; |
219 |
|
220 |
/** Return a string (not caller's to free). Form of the enum given. */ |
221 |
extern char *FrameControlToString(enum FrameControl frc); |
222 |
/* |
223 |
* Doing anything more than output during execution probably calls for |
224 |
* a real debugging thread or a most careful inside-out method |
225 |
* execution protocol. |
226 |
*/ |
227 |
|
228 |
/** Init a top procFrame for normal execution with no debugging. */ |
229 |
extern void InitNormalTopProcFrame(struct procFrame *fm, |
230 |
struct Instance *i, |
231 |
char *cname, |
232 |
FILE *eff, |
233 |
int options); |
234 |
|
235 |
/** Init a top procFrame for debugging execution. */ |
236 |
extern void InitDebugTopProcFrame(struct procFrame *fm, |
237 |
struct Instance *i, |
238 |
char *cname, |
239 |
FILE *err, |
240 |
int options, |
241 |
struct procDebug *dbi, |
242 |
struct gl_list_t *watches, |
243 |
FILE *dplog); |
244 |
|
245 |
/** |
246 |
* Add a frame |
247 |
* |
248 |
* Create a frame for a stack. parent should be the |
249 |
* containing frame unless this is the first frame in a |
250 |
* stack. Context is the instance statements are supposed |
251 |
* to be executed in/on. incrname is the name by which |
252 |
* we got here from last frame, or global name if there |
253 |
* is no parent frame. Proc should be the proc that will |
254 |
* be executed using the returned frame. |
255 |
* M is the trace mode which should be FrameDebug, |
256 |
* FrameNormal, or (IFF parent != NULL) FrameInherit. |
257 |
*/ |
258 |
extern struct procFrame *AddProcFrame(struct procFrame *parent, |
259 |
struct Instance *context, |
260 |
char *incrname, |
261 |
struct InitProcedure *proc, |
262 |
enum FrameMode m); |
263 |
|
264 |
/** |
265 |
* Update context info in a frame. |
266 |
* Set the statement for the given frame. Statement had best be somewhere |
267 |
* in the proc list of the frame. i had better be the context the |
268 |
* statement is to be evaluated in if it is evaluated. |
269 |
*/ |
270 |
extern void UpdateProcFrame(struct procFrame *fm, |
271 |
struct Statement *stat, |
272 |
struct Instance *i); |
273 |
|
274 |
/** iffy */ |
275 |
extern void DestroyProcFrame(struct procFrame *fm); |
276 |
|
277 |
#endif /* __PROCFRAME_H_SEEN__ */ |
278 |
|