| 1 |
jds |
54 |
/* |
| 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 |
jds |
54 |
/** @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 |
johnpye |
1066 |
#ifndef ASC_PROCFRAME_H |
| 47 |
|
|
#define ASC_PROCFRAME_H |
| 48 |
aw0a |
1 |
|
| 49 |
johnpye |
1066 |
/** addtogroup compiler Compiler |
| 50 |
|
|
@{ |
| 51 |
|
|
*/ |
| 52 |
|
|
|
| 53 |
aw0a |
1 |
enum FrameMode { |
| 54 |
jds |
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 |
aw0a |
1 |
}; |
| 62 |
|
|
|
| 63 |
jds |
54 |
/** |
| 64 |
|
|
* Because error handling is user defined according to watchpt.h |
| 65 |
aw0a |
1 |
* 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 |
jds |
54 |
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 |
aw0a |
1 |
}; |
| 83 |
jds |
54 |
/* keep the above in sync with the internals of FrameControlToString below */ |
| 84 |
aw0a |
1 |
|
| 85 |
jds |
54 |
/** |
| 86 |
aw0a |
1 |
* some watch point structures for internal use only. |
| 87 |
|
|
* see watchpt.h for UI watchpoint input structures. |
| 88 |
|
|
*/ |
| 89 |
|
|
struct anywatch { |
| 90 |
jds |
54 |
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 |
aw0a |
1 |
}; |
| 95 |
|
|
|
| 96 |
|
|
struct namewatch { |
| 97 |
|
|
symchar *leafname; |
| 98 |
|
|
struct namewatch *next; |
| 99 |
|
|
struct gl_list_t *where; |
| 100 |
jds |
54 |
unsigned long flags; /**< control bits */ |
| 101 |
aw0a |
1 |
}; |
| 102 |
|
|
|
| 103 |
|
|
struct procwatch { |
| 104 |
|
|
symchar *leafname; |
| 105 |
|
|
struct procwatch *next; |
| 106 |
|
|
struct gl_list_t *where; |
| 107 |
jds |
54 |
unsigned long flags; /**< control bits */ |
| 108 |
aw0a |
1 |
}; |
| 109 |
|
|
|
| 110 |
|
|
struct statwatch { |
| 111 |
|
|
struct Statement *stat; |
| 112 |
|
|
struct statwatch *next; |
| 113 |
|
|
struct gl_list_t *where; |
| 114 |
jds |
54 |
unsigned long flags; /**< control bits */ |
| 115 |
aw0a |
1 |
}; |
| 116 |
|
|
|
| 117 |
|
|
struct varswatch { |
| 118 |
jds |
54 |
struct Instance *var; /**< watched var */ |
| 119 |
aw0a |
1 |
struct varswatch *next; |
| 120 |
jds |
54 |
struct gl_list_t *where; /**< list of statement/context pairs */ |
| 121 |
|
|
unsigned long flags; /**< control bits */ |
| 122 |
aw0a |
1 |
}; |
| 123 |
|
|
|
| 124 |
|
|
struct typewatch { |
| 125 |
jds |
54 |
struct TypeDescription *desc; /**< watched var type */ |
| 126 |
aw0a |
1 |
struct typewatch *next; |
| 127 |
jds |
54 |
struct TypeDescription *ancestor; /**< watched ancestor causing this */ |
| 128 |
|
|
unsigned long flags; /**< control bits */ |
| 129 |
aw0a |
1 |
}; |
| 130 |
|
|
|
| 131 |
jds |
54 |
/** |
| 132 |
|
|
* Masks are always = 2^N -1 for some N. Such a mask |
| 133 |
aw0a |
1 |
* 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 |
ben.allan |
33 |
/** The idea here is that pointers (to persistent instances, names, types |
| 154 |
aw0a |
1 |
* 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 |
jds |
54 |
/**< 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 |
aw0a |
1 |
* 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 |
jds |
54 |
/** |
| 188 |
aw0a |
1 |
* 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 |
jds |
54 |
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 |
aw0a |
1 |
}; |
| 217 |
|
|
|
| 218 |
jds |
54 |
/** |
| 219 |
|
|
* Setting this to 1 causes a STOP at the next sensible moment. |
| 220 |
|
|
* UIs access this variable through watchpt.h only. |
| 221 |
|
|
*/ |
| 222 |
aw0a |
1 |
extern int g_procframe_stop; |
| 223 |
|
|
|
| 224 |
jds |
54 |
/** Return a string (not caller's to free). Form of the enum given. */ |
| 225 |
|
|
extern char *FrameControlToString(enum FrameControl frc); |
| 226 |
|
|
/* |
| 227 |
aw0a |
1 |
* 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 |
jds |
54 |
/** 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 |
aw0a |
1 |
|
| 239 |
jds |
54 |
/** 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 |
johnpye |
908 |
FILE *dplog); |
| 248 |
aw0a |
1 |
|
| 249 |
ben.allan |
33 |
/** |
| 250 |
jds |
54 |
* Add a frame |
| 251 |
|
|
* |
| 252 |
aw0a |
1 |
* 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 |
jds |
54 |
extern struct procFrame *AddProcFrame(struct procFrame *parent, |
| 263 |
|
|
struct Instance *context, |
| 264 |
|
|
char *incrname, |
| 265 |
|
|
struct InitProcedure *proc, |
| 266 |
|
|
enum FrameMode m); |
| 267 |
aw0a |
1 |
|
| 268 |
jds |
54 |
/** |
| 269 |
|
|
* Update context info in a frame. |
| 270 |
|
|
* Set the statement for the given frame. Statement had best be somewhere |
| 271 |
aw0a |
1 |
* 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 |
jds |
54 |
extern void UpdateProcFrame(struct procFrame *fm, |
| 275 |
|
|
struct Statement *stat, |
| 276 |
|
|
struct Instance *i); |
| 277 |
aw0a |
1 |
|
| 278 |
ben.allan |
33 |
/** iffy */ |
| 279 |
jds |
54 |
extern void DestroyProcFrame(struct procFrame *fm); |
| 280 |
aw0a |
1 |
|
| 281 |
johnpye |
1066 |
/* @} */ |
| 282 |
aw0a |
1 |
|
| 283 |
johnpye |
1066 |
#endif /* ASC_PROCFRAME_H */ |
| 284 |
|
|
|