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