| 1 |
aw0a |
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 |
jpye |
2323 |
#include <ascend/general/platform.h> |
| 33 |
jpye |
2322 |
#include <ascend/general/ascMalloc.h> |
| 34 |
jpye |
2018 |
#include <ascend/general/list.h> |
| 35 |
johnpye |
1210 |
|
| 36 |
johnpye |
1211 |
|
| 37 |
|
|
|
| 38 |
johnpye |
669 |
#include "expr_types.h" |
| 39 |
johnpye |
399 |
#include "stattypes.h" |
| 40 |
|
|
#include "proc.h" |
| 41 |
|
|
#include "instance_enum.h" |
| 42 |
|
|
#include "watchpt.h" |
| 43 |
|
|
#include "procframe.h" |
| 44 |
aw0a |
1 |
|
| 45 |
|
|
/* The following goo all goes to slow down the method execution. |
| 46 |
|
|
* need to be smarter about these macros. |
| 47 |
|
|
*/ |
| 48 |
johnpye |
709 |
#define FMALLOC ASC_NEW(struct procFrame) |
| 49 |
aw0a |
1 |
#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 |
ballan |
2036 |
char * fmncreate(CONST char *old, char *incr, char* join) |
| 57 |
ben.allan |
467 |
{ |
| 58 |
ballan |
2036 |
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 |
ben.allan |
467 |
sprintf(new, "%s%s%s", ( old!=NULL ? old : ""), join , incr ); |
| 64 |
|
|
return new; |
| 65 |
|
|
} |
| 66 |
aw0a |
1 |
/* 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 |
ballan |
2036 |
CONST char *cname, FILE *err, int options) |
| 81 |
aw0a |
1 |
{ |
| 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 |
ballan |
2036 |
fm->cname = fmncreate(cname, NULL,""); |
| 91 |
aw0a |
1 |
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 |
jds |
97 |
dbi = fm->dbi; |
| 107 |
aw0a |
1 |
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 |
ballan |
2036 |
CONST char *cname, FILE *err, int options, |
| 124 |
aw0a |
1 |
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 |
ballan |
2036 |
fm->cname = fmncreate(cname, NULL,""); |
| 136 |
aw0a |
1 |
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 |
ben.allan |
467 |
fm->cname =fmncreate(NULL,incrname,""); |
| 177 |
aw0a |
1 |
} 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 |
ben.allan |
467 |
fm->cname = fmncreate(parent->cname,incrname,((context==parent->i)?"":".")); |
| 188 |
aw0a |
1 |
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 |