1 |
/* |
2 |
* procframe.c: 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.c,v $ |
8 |
* Date last modified: $Date: 1998/06/16 16:38:47 $ |
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 |
#include <ascend/utilities/ascConfig.h> |
33 |
#include <ascend/utilities/ascMalloc.h> |
34 |
#include <ascend/general/list.h> |
35 |
|
36 |
|
37 |
|
38 |
#include "expr_types.h" |
39 |
#include "stattypes.h" |
40 |
#include "proc.h" |
41 |
#include "instance_enum.h" |
42 |
#include "watchpt.h" |
43 |
#include "procframe.h" |
44 |
|
45 |
/* The following goo all goes to slow down the method execution. |
46 |
* need to be smarter about these macros. |
47 |
*/ |
48 |
#define FMALLOC ASC_NEW(struct procFrame) |
49 |
#define FMFREE(f) ascfree(f) |
50 |
|
51 |
/* make a name for the path we took to get here. join is either "" or "." */ |
52 |
#define FMNCREATE(new,old,incr,join) \ |
53 |
(new) = (char *)ascmalloc(((old!=NULL)?strlen(old):0)+strlen(incr)+ \ |
54 |
+ strlen(join)+1); \ |
55 |
sprintf((new),"%s%s%s",((old)!=NULL?(old):""),(join),(incr)) |
56 |
char * fmncreate(CONST char *old, char *incr, char* join) |
57 |
{ |
58 |
char *new; |
59 |
if (old == NULL) { old = "";} |
60 |
if (join == NULL) { join = "";} |
61 |
if (incr == NULL) { incr = "";} |
62 |
new = ASC_NEW_ARRAY(char,( (old!=NULL) ? strlen(old) : 0 )+strlen(incr)+ strlen(join)+1); |
63 |
sprintf(new, "%s%s%s", ( old!=NULL ? old : ""), join , incr ); |
64 |
return new; |
65 |
} |
66 |
/* destroy said name when done with it. */ |
67 |
#define FMNFREE(n) ascfree(n) |
68 |
|
69 |
/* These are the only legal wpflags if debugging is not active. */ |
70 |
#define WP_LEGALOPTS (WP_STOPONERR | WP_BTUIFSTOP | WP_UIFEXT | WP_UIFCOMP) |
71 |
|
72 |
/* These are the legal wpflags if debugging is active. */ |
73 |
#define WP_DEBUGOPTS (WP_LEGALOPTS | WP_BTLOGSTOP | WP_LOGEXT | WP_LOGCOMP | \ |
74 |
WP_LOGMULCALL | WP_UIFMULCALL | WP_LOGMULASGN | WP_UIFMULASGN) |
75 |
/* other option bits can only be specified through the watchlist */ |
76 |
|
77 |
int g_procframe_stop = 0; |
78 |
|
79 |
void InitNormalTopProcFrame(struct procFrame *fm, struct Instance *i, |
80 |
CONST char *cname, FILE *err, int options) |
81 |
{ |
82 |
assert(i !=NULL); |
83 |
assert(cname !=NULL); |
84 |
assert(err!=NULL); /* good design? */ |
85 |
fm->i = i; |
86 |
fm->flow = FrameOK; |
87 |
fm->ErrNo = Proc_all_ok; |
88 |
fm->m = FrameNormal; |
89 |
fm->depth = 0; |
90 |
fm->cname = fmncreate(cname, NULL,""); |
91 |
fm->proc = NULL; |
92 |
fm->stat = NULL; |
93 |
fm->caller = NULL; |
94 |
fm->dbi = NULL; |
95 |
fm->locals = NULL; |
96 |
fm->gen = options & WP_LEGALOPTS; |
97 |
fm->err = err; |
98 |
} |
99 |
|
100 |
/* returns number of errors encountered. */ |
101 |
static |
102 |
int WatchConfigureProcDebug(struct procFrame *fm, struct gl_list_t *wl) |
103 |
{ |
104 |
unsigned long c,len; |
105 |
struct procDebug *dbi; |
106 |
dbi = fm->dbi; |
107 |
assert(dbi!=NULL); |
108 |
len = gl_length(wl); |
109 |
for (c = 1; c <= len; c++) { |
110 |
/* if something or other, set tab ptr and set flags and if needed |
111 |
* set data in hash tables. see watchpt.h and procframe.h. |
112 |
*/ |
113 |
} |
114 |
dbi->ntab = dbi->namehead; |
115 |
dbi->ptab = dbi->prochead; |
116 |
dbi->stab = dbi->stathead; |
117 |
dbi->ttab = dbi->typehead; |
118 |
dbi->vtab = dbi->varshead; |
119 |
return 1; |
120 |
} |
121 |
|
122 |
void InitDebugTopProcFrame(struct procFrame *fm, struct Instance *i, |
123 |
CONST char *cname, FILE *err, int options, |
124 |
struct procDebug *dbi, struct gl_list_t *watches, |
125 |
FILE *log) |
126 |
{ |
127 |
assert(i !=NULL); |
128 |
assert(cname !=NULL); |
129 |
assert(dbi !=NULL); |
130 |
fm->i = i; |
131 |
fm->flow = FrameOK; |
132 |
fm->ErrNo = Proc_all_ok; |
133 |
fm->m = FrameDebug; |
134 |
fm->depth = 0; |
135 |
fm->cname = fmncreate(cname, NULL,""); |
136 |
fm->proc = NULL; |
137 |
fm->stat = NULL; |
138 |
fm->caller = NULL; |
139 |
fm->dbi = dbi; |
140 |
fm->dbi->log = log; |
141 |
fm->locals = NULL; |
142 |
fm->err = err; |
143 |
fm->gen = options & WP_DEBUGOPTS; |
144 |
WatchConfigureProcDebug(fm,watches); |
145 |
} |
146 |
|
147 |
/* |
148 |
* Create a frame for a stack. parent should be the |
149 |
* containing frame unless this is the first frame in a |
150 |
* stack. Context is the instance statements are supposed |
151 |
* to be executed in/on. incrname is the name by which |
152 |
* we got here from last frame, or global name if there |
153 |
* is no parent frame. Proc should be the proc that will |
154 |
* be executed using the returned frame. |
155 |
* M is the trace mode which should be FrameDebug, |
156 |
* FrameNormal, or (IFF parent != NULL) FrameInherit. |
157 |
*/ |
158 |
struct procFrame *AddProcFrame(struct procFrame *parent, |
159 |
struct Instance *context, |
160 |
char *incrname, |
161 |
struct InitProcedure *proc, |
162 |
enum FrameMode m) |
163 |
{ |
164 |
struct procFrame *fm; |
165 |
assert(context != NULL); |
166 |
assert(incrname != NULL); |
167 |
assert(proc != NULL); |
168 |
if (parent == NULL) { |
169 |
assert(m == FrameNormal || m == FrameDebug); |
170 |
fm = FMALLOC; |
171 |
assert(fm!=NULL); |
172 |
fm->m = m; |
173 |
fm->depth = 1; |
174 |
fm->err = ASCERR; |
175 |
fm->gen = 0; /* tell the user nothing...? */ |
176 |
fm->cname =fmncreate(NULL,incrname,""); |
177 |
} else { |
178 |
fm = FMALLOC; |
179 |
assert(fm!=NULL); |
180 |
if (m != FrameInherit) { |
181 |
fm->m = m; |
182 |
} else { |
183 |
fm->m = parent->m; |
184 |
} |
185 |
fm->err = parent->err; |
186 |
fm->depth = parent->depth + 1; |
187 |
fm->cname = fmncreate(parent->cname,incrname,((context==parent->i)?"":".")); |
188 |
fm->gen = parent->gen; |
189 |
} |
190 |
fm->i = context; |
191 |
fm->proc = proc; |
192 |
fm->locals = NULL; |
193 |
fm->stat = NULL; |
194 |
fm->flow = FrameOK; |
195 |
fm->ErrNo = Proc_all_ok; |
196 |
fm->caller = parent; |
197 |
return fm; |
198 |
} |
199 |
|
200 |
/* set the statement for the given frame. statement had best be somewhere |
201 |
* in the proc list of the frame. i had better be the context the |
202 |
* statement is to be evaluated in if it is evaluated. |
203 |
*/ |
204 |
void UpdateProcFrame(struct procFrame *fm, struct Statement *stat, |
205 |
struct Instance *i) |
206 |
{ |
207 |
assert(fm != NULL); |
208 |
fm->stat = stat; |
209 |
fm->i = i; |
210 |
} |
211 |
|
212 |
void DestroyProcFrame(struct procFrame *fm) |
213 |
{ |
214 |
assert(fm != NULL); |
215 |
fm->m = FrameDestroyed; |
216 |
fm->i = NULL; |
217 |
fm->depth = -1; |
218 |
fm->proc = NULL; |
219 |
fm->stat = NULL; |
220 |
if (fm->locals != NULL) { |
221 |
gl_destroy(fm->locals); |
222 |
/* elements of list assumed already destroyed. */ |
223 |
} |
224 |
FMNFREE(fm->cname); |
225 |
fm->cname = NULL; |
226 |
fm->caller = NULL; |
227 |
FMFREE(fm); |
228 |
} |
229 |
|
230 |
/* return a string (not caller's to free) form of the enum given */ |
231 |
char *FrameControlToString(enum FrameControl frc) |
232 |
{ |
233 |
switch (frc) { |
234 |
case FrameOK: |
235 |
return "FrameOK"; |
236 |
case FrameError: |
237 |
return "FrameError"; |
238 |
case FrameBreak: |
239 |
return "FrameBreak"; |
240 |
case FrameContinue: |
241 |
return "FrameContinue"; |
242 |
case FrameFallthru: |
243 |
return "FrameFallthru"; |
244 |
case FrameReturn: |
245 |
return "FrameReturn"; |
246 |
case FrameLoop: |
247 |
return "FrameLoop"; |
248 |
default: |
249 |
return "FrameUnknownEnum"; |
250 |
} |
251 |
} |
252 |
#if 0 /* junk */ |
253 |
/* the following are valid without debug mode active */ |
254 |
#define WP_STOPONERR 0x1 /* stop on errors */ |
255 |
#define WP_BTUIFSTOP 0x4 /* print backtrace to UI file on stopping */ |
256 |
#define WP_UIFEXT 0x20 /* print external calls/returns to UI file */ |
257 |
#define WP_UIFCOMP 0x80 /* print con/destructor calls to UI file */ |
258 |
|
259 |
/* the following require debugging active */ |
260 |
#define WP_BTLOGSTOP 0x8 /* print backtrace to log on stopping */ |
261 |
#define WP_LOGEXT 0x10 /* print external calls/returns to log */ |
262 |
#define WP_LOGCOMP 0x40 /* print con/destructor calls to log */ |
263 |
#define WP_LOGMULCALL 0x100 /* print recalls of any proc/context to log */ |
264 |
#define WP_UIFMULCALL 0x200 /* print recalls of any proc/context to UI */ |
265 |
#define WP_LOGMULASGN 0x400 /* print reassignments of any var to log */ |
266 |
#define WP_UIFMULASGN 0x800 /* print reassignments of any var to UI */ |
267 |
|
268 |
/* the following cannot be set from options, but are computed from watchlist */ |
269 |
#define WP_RESERVED 0xFFFF0000 /* internally computed bits affecting memory. */ |
270 |
#define WP_LOGPROC 0x10000 /* print method entries/returns to log */ |
271 |
#define WP_UIFPROC 0x20000 /* print method entries/returns to UI file */ |
272 |
#define WP_LOGSTAT 0x40000 /* print statement record to log */ |
273 |
#define WP_UIFSTAT 0x80000 /* print statement record to UI file */ |
274 |
#define WP_LOGVAR 0x100000 /* print specific instance assignments to log */ |
275 |
#define WP_UIFVAR 0x200000 /* print specific instance assignments to UI */ |
276 |
#define WP_LOGTYPE 0x400000 /* print assignment to vars of type to log */ |
277 |
#define WP_UIFTYPE 0x800000 /* print assignment of vars of type to UI */ |
278 |
#define WP_NAMEWATCH 0x1000000 /* name watches are defined */ |
279 |
#define WP_PROCWATCH 0x2000000 /* proc watches are defined */ |
280 |
#define WP_STATWATCH 0x4000000 /* stat watches are defined */ |
281 |
#define WP_TYPEWATCH 0x8000000 /* type watches are defined */ |
282 |
#define WP_VARSWATCH 0x10000000 /* single var watches are defined */ |
283 |
#define WP_WATCH2 0x20000000 /* reserved */ |
284 |
#define WP_WATCH4 0x40000000 /* reserved */ |
285 |
#define WP_DEBUGWATCH 0x80000000 /* if set, Asc_wp_stop_here activated */ |
286 |
#endif |