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