Commit | Line | Data |
---|---|---|
7329404e BB |
1 | /****************************************************************************** |
2 | * Copyright (c) 2000-2016 Ericsson Telecom AB | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * | |
10 | * Baranyi, Botond – initial implementation | |
11 | * | |
12 | ******************************************************************************/ | |
13 | ||
14 | #ifndef DEBUGGER_HH | |
15 | #define DEBUGGER_HH | |
16 | ||
17 | #include "Vector.hh" | |
18 | #include "Basetype.hh" | |
19 | #include "Charstring.hh" | |
20 | #ifdef TITAN_RUNTIME_2 | |
21 | #include "RT2/PreGenRecordOf.hh" | |
22 | #else | |
23 | #include "RT1/PreGenRecordOf.hh" | |
24 | #endif | |
016a1a93 | 25 | #include <regex.h> |
7329404e BB |
26 | |
27 | /** alias for record of charstring */ | |
28 | typedef PreGenRecordOf::PREGEN__RECORD__OF__CHARSTRING charstring_list; | |
29 | ||
f08ff9ca | 30 | // debugger forward declarations |
7329404e BB |
31 | class TTCN3_Debug_Scope; |
32 | class TTCN3_Debug_Function; | |
33 | ||
f08ff9ca BB |
34 | // other forward declarations |
35 | class Module_Param; | |
36 | ||
7329404e BB |
37 | |
38 | ////////////////////////////////////////////////////// | |
39 | ////////////////// TTCN3_Debugger //////////////////// | |
40 | ////////////////////////////////////////////////////// | |
41 | ||
42 | /** main debugger class | |
43 | * | |
44 | * instantiated once per process at the beginning of the current process, | |
45 | * destroyed at the end of the current process */ | |
46 | class TTCN3_Debugger { | |
47 | public: | |
48 | ||
f08ff9ca BB |
49 | struct variable_t; |
50 | ||
51 | typedef CHARSTRING (*print_function_t)(const variable_t&); | |
52 | typedef boolean (*set_function_t)(variable_t&, Module_Param&); | |
53 | ||
7329404e BB |
54 | /** type for keeping track of a variable */ |
55 | struct variable_t { | |
56 | /** pointer to the variable object, not owned */ | |
f08ff9ca BB |
57 | union { |
58 | /** container for non-constant variable objects */ | |
59 | void* value; | |
60 | /** container for constant variable objects */ | |
61 | const void* cvalue; | |
62 | }; | |
7329404e BB |
63 | /** variable name (used for looking up variables), not owned */ |
64 | const char* name; | |
65 | /** name of the variable's type, not owned */ | |
66 | const char* type_name; | |
67 | /** variable printing function (using the variable object's log() function) */ | |
f08ff9ca BB |
68 | print_function_t print_function; |
69 | /** variable setting (overwriting) function (using the variable object's | |
70 | * set_param() function) - set to NULL for constant variables */ | |
71 | set_function_t set_function; | |
7329404e BB |
72 | }; |
73 | ||
74 | /** this type pairs a debug scope with a name, used for storing global and | |
75 | * component scopes */ | |
76 | struct named_scope_t { | |
77 | /** scope name (module name for global scopes, or component type name for | |
016a1a93 | 78 | * component scopes), not owned */ |
7329404e BB |
79 | const char* name; |
80 | /** scope pointer, owned */ | |
81 | TTCN3_Debug_Scope* scope; | |
82 | }; | |
83 | ||
f08ff9ca BB |
84 | /** type for storing a function call in the call stack */ |
85 | struct function_call_t { | |
86 | /** pointer to the debug function object */ | |
87 | TTCN3_Debug_Function* function; | |
88 | /** TTCN-3 line number, where the function was called from */ | |
89 | int caller_line; | |
90 | }; | |
91 | ||
7329404e BB |
92 | /** type for storing breakpoints */ |
93 | struct breakpoint_t { | |
94 | /** module name, owned */ | |
95 | char* module; | |
96 | /** line number */ | |
97 | int line; | |
f08ff9ca BB |
98 | /** batch file to be executed when the breakpoint is reached (optional) */ |
99 | char* batch_file; | |
7329404e BB |
100 | }; |
101 | ||
7329404e BB |
102 | /** special breakpoint types, passed to breakpoint_entry() as the line parameter, |
103 | * so these need to be 0 or negative, to never conflict with any line number */ | |
104 | enum special_breakpoint_t { | |
105 | /** triggered when the local verdict is set to ERROR (by dynamic test case errors) */ | |
106 | SBP_ERROR_VERDICT = 0, | |
107 | /** triggered when the local verdict is set to FAIL (by the user) */ | |
108 | SBP_FAIL_VERDICT = -1 | |
109 | }; | |
110 | ||
f08ff9ca BB |
111 | /** type for storing the settings of automatic breakpoints */ |
112 | struct automatic_breakpoint_behavior_t { | |
113 | /** indicates whether the breakpoint should be triggered by the associated event */ | |
114 | bool trigger; | |
115 | /** batch file to be executed if the breakpoint is triggered (optional) */ | |
116 | char* batch_file; | |
117 | }; | |
118 | ||
119 | /** stepping type */ | |
120 | enum stepping_t { | |
121 | NOT_STEPPING, | |
122 | STEP_OVER, | |
123 | STEP_INTO, | |
124 | STEP_OUT | |
125 | }; | |
126 | ||
7329404e BB |
127 | private: |
128 | ||
016a1a93 BB |
129 | /** indicates whether the debugger has been activated, meaning that the debugger's |
130 | * command line option (-n) was used during the build (switched automatically | |
131 | * by generated code) */ | |
132 | bool enabled; | |
133 | ||
134 | /** the debugger's on/off switch (switched by the user) */ | |
7329404e BB |
135 | bool active; |
136 | ||
016a1a93 BB |
137 | /** true if test execution has been halted (by a breakpoint or by the user) */ |
138 | bool halted; | |
139 | ||
140 | /** the debugger's output file handler (NULL if the debugger's output is only | |
141 | * sent to the console) */ | |
142 | FILE* output_file; | |
143 | ||
144 | /** name of the debugger's output file (NULL if the debugger's output is only | |
145 | * sent to the console) */ | |
146 | char* output_file_name; | |
147 | ||
148 | /** indicates whether the debugger's output should be sent to the console */ | |
149 | bool send_to_console; | |
7329404e BB |
150 | |
151 | /** list of all global and component variables, elements are owned */ | |
152 | Vector<variable_t*> variables; | |
153 | ||
154 | /** list of global scopes */ | |
155 | Vector<named_scope_t> global_scopes; | |
156 | ||
157 | /** list of component scopes */ | |
158 | Vector<named_scope_t> component_scopes; | |
159 | ||
f08ff9ca BB |
160 | /** pointers to debug function objects and the lines they were called from |
161 | * (resembling a call stack), the current function is always the last element | |
162 | * in the array (the top element in the stack) */ | |
163 | Vector<function_call_t> call_stack; | |
7329404e BB |
164 | |
165 | /** list of breakpoints */ | |
166 | Vector<breakpoint_t> breakpoints; | |
167 | ||
168 | /** string containing function call snapshots, owned */ | |
169 | char* snapshots; | |
170 | ||
171 | /** stores the last line hit by breakpoint_entry() */ | |
172 | breakpoint_t last_breakpoint_entry; | |
173 | ||
016a1a93 | 174 | /** current stack level (reset when test execution is halted or resumed) */ |
7329404e BB |
175 | int stack_level; |
176 | ||
f08ff9ca BB |
177 | /** automatic breakpoint triggered by setting the local verdict to FAIL */ |
178 | automatic_breakpoint_behavior_t fail_behavior; | |
7329404e | 179 | |
f08ff9ca BB |
180 | /** automatic breakpoint triggered by setting the local verdict to ERROR */ |
181 | automatic_breakpoint_behavior_t error_behavior; | |
7329404e | 182 | |
f08ff9ca BB |
183 | /** batch file executed automatically when test execution is halted |
184 | * NULL if switched off | |
185 | * is overridden by breakpoint-specific batch files */ | |
186 | char* global_batch_file; | |
187 | ||
188 | /** result of the currently executing command */ | |
016a1a93 BB |
189 | char* command_result; |
190 | ||
f08ff9ca BB |
191 | /** result of the last D_LIST_VARIABLES command */ |
192 | char* last_variable_list; | |
193 | ||
194 | /** stores which stepping option was requested by the user (if any) */ | |
195 | stepping_t stepping_type; | |
196 | ||
197 | /** stores the size of the call stack when the last stepping operation was | |
198 | * initiated */ | |
199 | size_t stepping_stack_size; | |
200 | ||
201 | /** temporary breakpoint set by the 'run to cursor' operation */ | |
202 | breakpoint_t temporary_breakpoint; | |
203 | ||
204 | /** true if an 'exit all' command was issued | |
205 | * switched to false when test execution is restarted */ | |
206 | bool exiting; | |
207 | ||
208 | /** test execution is automatically halted at start if set to true */ | |
209 | bool halt_at_start; | |
210 | ||
211 | /** batch file executed automatically at the start of test execution | |
212 | * if not set to NULL (not owned) */ | |
213 | const char* initial_batch_file; | |
214 | ||
7329404e BB |
215 | ////////////////////////////////////////////////////// |
216 | ///////////////// internal functions ///////////////// | |
217 | ////////////////////////////////////////////////////// | |
218 | ||
016a1a93 BB |
219 | /** switches the debugger on or off |
220 | * handles the D_SWITCH command */ | |
221 | void switch_state(const char* p_state_str); | |
7329404e | 222 | |
f08ff9ca BB |
223 | /** adds a new breakpoint at the specified module and line with the specified |
224 | * batch file (if not NULL), or changes the batch file of an existing | |
225 | * breakpoint | |
7329404e | 226 | * handles the D_ADD_BREAKPOINT command */ |
f08ff9ca | 227 | void set_breakpoint(const char* p_module, int p_line, const char* batch_file); |
7329404e BB |
228 | |
229 | /** removes the breakpoint from the specified module/line, if it exists | |
f08ff9ca BB |
230 | * can also be used to remove all breakpoints from the specified module or |
231 | * all breakpoints in all modules | |
7329404e | 232 | * handles the D_REMOVE_BREAKPOINT command */ |
f08ff9ca BB |
233 | void remove_breakpoint(const char* p_module, const char* p_line); |
234 | ||
235 | /** switches an automatic breakpoint related to the specified event on or off | |
236 | * and/or sets the batch file to run when the breakpoint is triggered | |
237 | * @param p_event_str string representation of the event that triggers the | |
238 | * breakpoint (either "error" or "fail") | |
239 | * @param p_state_str "on" or "off", indicates the new state of the breakpoint | |
240 | * @param p_batch_file name of the batch file to execute (NULL means don't | |
241 | * execute anything) | |
242 | * handles the D_SET_AUTOMATIC_BREAKPOINT command */ | |
243 | void set_automatic_breakpoint(const char* p_event_str, const char* p_state_str, | |
244 | const char* p_batch_file); | |
7329404e BB |
245 | |
246 | /** prints the current call stack | |
247 | * handles the D_PRINT_CALL_STACK command */ | |
248 | void print_call_stack(); | |
249 | ||
016a1a93 | 250 | /** sets the current stack level to the specified value |
7329404e BB |
251 | * handles the D_SET_STACK_LEVEL command */ |
252 | void set_stack_level(int new_level); | |
253 | ||
f08ff9ca BB |
254 | /** finds the variable with the specified name, and prints its value or an |
255 | * error message | |
7329404e | 256 | * handles (one parameter of) the D_PRINT_VARIABLE command */ |
f08ff9ca BB |
257 | void print_variable(const char* p_var_name); |
258 | ||
259 | void overwrite_variable(const char* p_var_name, int p_value_element_count, | |
260 | char** p_value_elements); | |
7329404e | 261 | |
016a1a93 | 262 | /** sets the debugger's output to the console and/or a text file |
7329404e | 263 | * handles the D_SET_OUTPUT command |
016a1a93 BB |
264 | * @param p_output_type "console", "file" or "both" |
265 | * @param p_file_name output file name or NULL */ | |
7329404e BB |
266 | void set_output(const char* p_output_type, const char* p_file_name); |
267 | ||
f08ff9ca BB |
268 | /** switches the global batch file on or off |
269 | * handles the D_SET_GLOBAL_BATCH_FILE command */ | |
270 | void set_global_batch_file(const char* p_state_str, const char* p_file_name); | |
271 | ||
272 | /** resumes execution until the next breakpoint entry (in the stack levels | |
273 | * specified by the stepping type arguments) is reached (or until test execution | |
274 | * is halted for any other reason) | |
275 | * handles the D_STEP_OVER, D_STEP_INTO and D_STEP_OUT commands */ | |
276 | void step(stepping_t p_stepping_type); | |
277 | ||
278 | /** resumes execution until the specified location is reached | |
279 | * (or until test execution is halted for any other reason) | |
280 | * handles the D_RUN_TO_CURSOR command */ | |
281 | void run_to_cursor(const char* p_module, int p_line); | |
282 | ||
016a1a93 | 283 | /** halts test execution, processing only debug commands |
f08ff9ca BB |
284 | * @param p_batch_file batch file executed after the halt (if not NULL) |
285 | * @param p_run_global_batch indicates whether the global batch file should | |
286 | * be executed after the halt (only if p_batch_file is NULL) | |
016a1a93 | 287 | * handles the D_HALT command */ |
f08ff9ca | 288 | void halt(const char* p_batch_file, bool p_run_global_batch); |
016a1a93 BB |
289 | |
290 | /** resumes the halted test execution | |
291 | * handles the D_CONTINUE command */ | |
292 | void resume(); | |
293 | ||
294 | /** exits the current test or the execution of all tests | |
295 | * handles the D_EXIT command */ | |
296 | void exit_(const char* p_what); | |
297 | ||
7329404e BB |
298 | /** returns the index of the specified breakpoint, if found, |
299 | * otherwise returns breakpoints.size() */ | |
300 | size_t find_breakpoint(const char* p_module, int p_line) const; | |
301 | ||
302 | /** returns the specified variable, if found, otherwise returns NULL */ | |
303 | TTCN3_Debugger::variable_t* find_variable(const void* p_value) const; | |
016a1a93 BB |
304 | |
305 | /** handles metacharacters in the specified file name skeleton | |
306 | * @return final file name (must be freed by caller) */ | |
307 | static char* finalize_file_name(const char* p_file_name_skeleton); | |
f08ff9ca BB |
308 | |
309 | /** initialization function, called when the first function is added to the | |
310 | * call stack */ | |
311 | void test_execution_started(); | |
312 | ||
313 | /** clean up function, called when the last function is removed from the | |
314 | * call stack */ | |
315 | void test_execution_finished(); | |
7329404e BB |
316 | |
317 | public: | |
318 | /** constructor - called once per process (at the beginning) */ | |
319 | TTCN3_Debugger(); | |
320 | ||
321 | /** destructor - called once per process (at the end) */ | |
322 | ~TTCN3_Debugger(); | |
323 | ||
324 | ////////////////////////////////////////////////////// | |
325 | ////// methods called from TITAN generated code ////// | |
326 | ////////////////////////////////////////////////////// | |
327 | ||
016a1a93 BB |
328 | /** activates the debugger */ |
329 | void activate() { enabled = true; } | |
330 | ||
331 | /** creates, stores and returns a new global scope for the specified module | |
332 | * (this scope contains all global variables visible in the module) */ | |
7329404e BB |
333 | TTCN3_Debug_Scope* add_global_scope(const char* p_module); |
334 | ||
016a1a93 BB |
335 | /** creates, stores and returns a new component scope for the specified component |
336 | * type (this scope contains all variables declared in the component type) */ | |
7329404e BB |
337 | TTCN3_Debug_Scope* add_component_scope(const char* p_component); |
338 | ||
339 | /** stores the string representation of the current function's return value | |
340 | * (only if the debugger is switched on) */ | |
341 | void set_return_value(const CHARSTRING& p_value); | |
342 | ||
343 | /** activates a breakpoint if the specified line and the current function's module | |
344 | * match any of the breakpoints stored in the debugger | |
345 | * the special parameter values (SBP_ERROR_VERDICT and SBP_FAIL_VERDICT) only | |
346 | * trigger a breakpoint if their respective behaviors have been set to do so | |
347 | * (does nothing if the debugger is switched off) */ | |
f08ff9ca | 348 | void breakpoint_entry(int p_line); |
7329404e BB |
349 | |
350 | /** variable printing function for base types */ | |
351 | static CHARSTRING print_base_var(const variable_t& p_var); | |
352 | ||
f08ff9ca BB |
353 | /** variable setting function for base types */ |
354 | static boolean set_base_var(variable_t& p_var, Module_Param& p_new_value); | |
355 | ||
7329404e BB |
356 | /** variable printing function for value arrays */ |
357 | template <typename T_type, unsigned int array_size, int index_offset> | |
358 | static CHARSTRING print_value_array(const variable_t& p_var) | |
359 | { | |
f08ff9ca | 360 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 361 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 362 | ((VALUE_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
363 | return TTCN_Logger::end_event_log2str(); |
364 | } | |
365 | ||
f08ff9ca BB |
366 | /** variable setting function for value arrays */ |
367 | template <typename T_type, unsigned int array_size, int index_offset> | |
368 | static boolean set_value_array(variable_t& p_var, Module_Param& p_new_value) | |
369 | { | |
370 | ((VALUE_ARRAY<T_type, array_size, index_offset>*)p_var.value)->set_param(p_new_value); | |
371 | return TRUE; | |
372 | } | |
373 | ||
7329404e BB |
374 | /** variable printing function for template arrays */ |
375 | template <typename T_value_type, typename T_template_type, | |
376 | unsigned int array_size, int index_offset> | |
377 | static CHARSTRING print_template_array(const variable_t& p_var) | |
378 | { | |
f08ff9ca | 379 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e BB |
380 | TTCN_Logger::begin_event_log2str(); |
381 | ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size, | |
f08ff9ca | 382 | index_offset>*)ptr)->log(); |
7329404e BB |
383 | return TTCN_Logger::end_event_log2str(); |
384 | } | |
385 | ||
f08ff9ca BB |
386 | /** variable setting function for template arrays */ |
387 | template <typename T_value_type, typename T_template_type, | |
388 | unsigned int array_size, int index_offset> | |
389 | static boolean set_template_array(variable_t& p_var, Module_Param& p_new_value) | |
390 | { | |
391 | ((TEMPLATE_ARRAY<T_value_type, T_template_type, array_size, | |
392 | index_offset>*)p_var.value)->set_param(p_new_value); | |
393 | return TRUE; | |
394 | } | |
395 | ||
7329404e BB |
396 | /** variable printing function for port arrays */ |
397 | template <typename T_type, unsigned int array_size, int index_offset> | |
398 | static CHARSTRING print_port_array(const variable_t& p_var) | |
399 | { | |
f08ff9ca | 400 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 401 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 402 | ((PORT_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
403 | return TTCN_Logger::end_event_log2str(); |
404 | } | |
405 | ||
406 | /** variable printing function for timer arrays */ | |
407 | template <typename T_type, unsigned int array_size, int index_offset> | |
408 | static CHARSTRING print_timer_array(const variable_t& p_var) | |
409 | { | |
f08ff9ca | 410 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 411 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 412 | ((TIMER_ARRAY<T_type, array_size, index_offset>*)ptr)->log(); |
7329404e BB |
413 | return TTCN_Logger::end_event_log2str(); |
414 | } | |
415 | ||
416 | /** variable printing function for lazy parameters */ | |
417 | template <typename EXPR_TYPE> | |
418 | static CHARSTRING print_lazy_param(const variable_t& p_var) | |
419 | { | |
f08ff9ca | 420 | const void* ptr = p_var.set_function != NULL ? p_var.value : p_var.cvalue; |
7329404e | 421 | TTCN_Logger::begin_event_log2str(); |
f08ff9ca | 422 | ((Lazy_Param<EXPR_TYPE>*)ptr)->log(); |
7329404e BB |
423 | return TTCN_Logger::end_event_log2str(); |
424 | } | |
425 | ||
426 | ////////////////////////////////////////////////////// | |
427 | ////// methods called by other debugger classes ////// | |
428 | ////////////////////////////////////////////////////// | |
429 | ||
016a1a93 BB |
430 | /** returns true if the debugger is activated (through the compiler switch) */ |
431 | bool is_activated() const { return enabled; } | |
432 | ||
7329404e BB |
433 | /** returns true if the debugger is switched on */ |
434 | bool is_on() const { return active; } | |
435 | ||
016a1a93 BB |
436 | /** returns true if test execution has been halted by the debugger */ |
437 | bool is_halted() const { return halted; } | |
438 | ||
439 | /** prints the formatted string to the console and/or output file | |
440 | * (used for printing notifications or error messages) */ | |
441 | void print(int return_type, const char* fmt, ...) const; | |
442 | ||
443 | /** adds the formatted string to the currently executed command's result string */ | |
444 | void add_to_result(const char* fmt, ...); | |
7329404e BB |
445 | |
446 | /** adds the specified function object pointer to the call stack | |
447 | * (only if the debugger is switched on) */ | |
448 | void add_function(TTCN3_Debug_Function* p_function); | |
449 | ||
450 | /** adds the specified scope object pointer to the current function's scope list | |
451 | * (only if the debugger is switched on and the call stack is not empty) */ | |
452 | void add_scope(TTCN3_Debug_Scope* p_scope); | |
453 | ||
454 | /** removes the specified function object pointer from the call stack, if it is | |
455 | * the function at the top of the stack */ | |
456 | void remove_function(TTCN3_Debug_Function* p_function); | |
457 | ||
458 | /** removes the specified scope object pointer from the current function's scope list | |
459 | * (only if the call stack is not empty) */ | |
460 | void remove_scope(TTCN3_Debug_Scope* p_scope); | |
461 | ||
f08ff9ca BB |
462 | /** finds or creates, and returns the constant variable entry specified by |
463 | * the parameters | |
7329404e BB |
464 | * |
465 | * if the call stack is empty, an entry for a global or component variable is | |
466 | * created and stored in the main debugger object (if it doesn't already exist); | |
467 | * if the call stack is not empty (and if the debugger is switched on), the | |
016a1a93 | 468 | * variable entry for a local variable is created and stored by the current function */ |
f08ff9ca BB |
469 | variable_t* add_variable(const void* p_value, const char* p_name, const char* p_type, |
470 | print_function_t p_print_function); | |
471 | ||
472 | /** same as before, but for non-constant variables */ | |
473 | variable_t* add_variable(void* p_value, const char* p_name, const char* p_type, | |
474 | print_function_t p_print_function, set_function_t p_set_function); | |
7329404e BB |
475 | |
476 | /** removes the variable entry for the specified local variable in the current | |
477 | * function (only if the call stack is not empty) */ | |
478 | void remove_variable(const variable_t* p_var); | |
479 | ||
480 | /** returns the global scope object associated with the specified module */ | |
481 | const TTCN3_Debug_Scope* get_global_scope(const char* p_module) const; | |
482 | ||
483 | /** returns the component scope object associated with the specified component type */ | |
484 | const TTCN3_Debug_Scope* get_component_scope(const char* p_component) const; | |
485 | ||
486 | /** appends the specified function call snapshot to the end of the snapshot string */ | |
487 | void add_snapshot(const char* p_snapshot); | |
488 | ||
489 | /** executes a command received from the user interface */ | |
016a1a93 BB |
490 | void execute_command(int p_command, int p_argument_count, char** p_arguments); |
491 | ||
492 | /** opens the debugger's output file for writing (if one has been set, but not | |
493 | * opened, in the HC process) */ | |
494 | void open_output_file(); | |
f08ff9ca BB |
495 | |
496 | /** indicates whether an 'exit all' command has been issued | |
497 | * (this causes the execution of tests in the current queue to stop) */ | |
498 | bool is_exiting() const { return exiting; } | |
499 | ||
500 | /** sets the debugger to halt test execution at start (only in single mode) */ | |
501 | void set_halt_at_start() { halt_at_start = true; } | |
502 | ||
503 | /** sets the specified batch file to be executed at the start of test execution | |
504 | * (only in single mode) */ | |
505 | void set_initial_batch_file(const char* p_batch_file) { | |
506 | initial_batch_file = p_batch_file; | |
507 | } | |
7329404e BB |
508 | }; |
509 | ||
510 | /** the main debugger object */ | |
511 | extern TTCN3_Debugger ttcn3_debugger; | |
512 | ||
513 | ||
514 | ////////////////////////////////////////////////////// | |
515 | //////////////// TTCN3_Debug_Scope /////////////////// | |
516 | ////////////////////////////////////////////////////// | |
517 | ||
518 | /** debugger scope class | |
519 | * | |
520 | * instantiated at the beginning of every code block in the TTCN-3 code (except | |
521 | * for the code blocks of functions), plus one (global scope) instance is created | |
522 | * for every module and one (component scope) for every component type | |
523 | * | |
524 | * the class' main purpose is to track which local variables were created in the | |
525 | * current code block or to track which of the main debugger object's variables | |
526 | * belong to which global or component scope */ | |
527 | class TTCN3_Debug_Scope { | |
528 | ||
529 | /** list of pointers to local variable entries from the current function object or | |
530 | * global or component variable entries from the main debugger object | |
531 | * (the elements are not owned)*/ | |
f08ff9ca | 532 | Vector<TTCN3_Debugger::variable_t*> variables; |
7329404e BB |
533 | |
534 | public: | |
535 | ||
536 | /** constructor - lets the current function know of this new scope */ | |
537 | TTCN3_Debug_Scope(); | |
538 | ||
539 | /** destructor - tells the current function to delete the variable entries listed | |
540 | * in this instance */ | |
541 | ~TTCN3_Debug_Scope(); | |
542 | ||
543 | ////////////////////////////////////////////////////// | |
544 | ////// methods called from TITAN generated code ////// | |
545 | ////////////////////////////////////////////////////// | |
546 | ||
547 | /** passes the parameters to the main debugger or current function object to | |
f08ff9ca BB |
548 | * create and store a (constant) variable entry from them, and tracks this new |
549 | * variable by storing a pointer to it | |
7329404e BB |
550 | * (local variables are only created and stored if the debugger is switched on) */ |
551 | void add_variable(const void* p_value, const char* p_name, const char* p_type, | |
f08ff9ca BB |
552 | TTCN3_Debugger::print_function_t p_print_function); |
553 | ||
554 | /** same as before, but for non-constant variables */ | |
555 | void add_variable(void* p_value, const char* p_name, const char* p_type, | |
556 | TTCN3_Debugger::print_function_t p_print_function, | |
557 | TTCN3_Debugger::set_function_t p_set_function); | |
7329404e BB |
558 | |
559 | ////////////////////////////////////////////////////// | |
560 | ////// methods called by other debugger classes ////// | |
561 | ////////////////////////////////////////////////////// | |
562 | ||
563 | /** returns true if there is at least one variable in the scope object */ | |
564 | bool has_variables() const { return !variables.empty(); } | |
565 | ||
566 | /** returns the specified variable, if found, otherwise returns NULL */ | |
f08ff9ca | 567 | TTCN3_Debugger::variable_t* find_variable(const char* p_name) const; |
7329404e | 568 | |
016a1a93 BB |
569 | /** prints the names of variables in this scope that match the specified |
570 | * @param p_posix_regexp the pattern converted into a POSIX regex structure | |
7329404e | 571 | * @param p_first true if no variables have been printed yet */ |
016a1a93 | 572 | void list_variables(regex_t* p_posix_regexp, bool& p_first) const; |
7329404e BB |
573 | }; |
574 | ||
575 | ||
576 | ////////////////////////////////////////////////////// | |
577 | /////////////// TTCN3_Debug_Function ///////////////// | |
578 | ////////////////////////////////////////////////////// | |
579 | ||
580 | /** debugger function class | |
581 | * | |
582 | * instantiated at the beginning of every function, destroyed when function execution ends | |
583 | * | |
584 | * tracks all variables created during the function's execution (local variables), | |
585 | * including the function's parameters, and stores the function's return value */ | |
586 | class TTCN3_Debug_Function { | |
587 | ||
588 | /** name of the function, not owned */ | |
589 | const char* function_name; | |
590 | ||
591 | /** the TTCN-3 keyword(s) used to define the function ("function", "testcase", | |
592 | * "altstep", "template" or "external function"), not owned */ | |
593 | const char* function_type; | |
594 | ||
595 | /** name of the module this function is defined in, not owned */ | |
596 | const char* module_name; | |
597 | ||
598 | /** names of the function's parameters (in the order of their declaration), owned */ | |
599 | charstring_list* parameter_names; | |
600 | ||
601 | /** types (directions) of the function's parameters ("in", "inout" or "out"), owned */ | |
602 | charstring_list* parameter_types; | |
603 | ||
604 | /** list of local variables tracked by this object, the array elements are owned */ | |
605 | Vector<TTCN3_Debugger::variable_t*> variables; | |
606 | ||
607 | /** list of pointers to the scope objects of code blocks in the function, | |
608 | * the elements are not owned | |
609 | * (currently not used for anything) */ | |
610 | Vector<TTCN3_Debug_Scope*> scopes; | |
611 | ||
612 | /** pointer to the global scope object, not owned | |
613 | * (may be NULL, if the module's global scope is empty) */ | |
614 | const TTCN3_Debug_Scope* global_scope; | |
615 | ||
616 | /** pointer to the runs-on component's scope object, not owned | |
617 | * (may be NULL, if the component's scope is empty or if the function has no runs-on clause) */ | |
618 | const TTCN3_Debug_Scope* component_scope; | |
619 | ||
620 | /** the function's return value (unbound if the return value has not been set yet, | |
621 | * or if the function doesn't return anything) | |
622 | * | |
623 | * since this is only set right before the function ends, it is only accessible | |
624 | * from the destructor */ | |
625 | CHARSTRING return_value; | |
626 | ||
627 | public: | |
628 | ||
629 | /** constructor - initializes the instance with the specified parameters, | |
630 | * retrieves the global scope and component scope from the main debugger object */ | |
631 | TTCN3_Debug_Function(const char* p_name, const char* p_type, const char* p_module, | |
632 | const charstring_list& p_parameter_names, const charstring_list& p_parameter_types, const char* p_component_name); | |
633 | ||
634 | /** destructor - frees resources and saves the function's ending snapshot | |
635 | * (including the values of 'out' and 'inout' parameters and the return value) | |
636 | * in the main debugger object (only if the debugger is switched on) */ | |
637 | ~TTCN3_Debug_Function(); | |
638 | ||
639 | ////////////////////////////////////////////////////// | |
640 | ////// methods called from TITAN generated code ////// | |
641 | ////////////////////////////////////////////////////// | |
642 | ||
f08ff9ca | 643 | /** creates, stores and returns the variable entry of the local (constant) variable |
7329404e | 644 | * specified by the parameters (only if the debugger is switched on) */ |
f08ff9ca BB |
645 | TTCN3_Debugger::variable_t* add_variable(const void* p_value, const char* p_name, |
646 | const char* p_type, TTCN3_Debugger::print_function_t p_print_function); | |
647 | ||
648 | /** same as before, but for non-constant variables */ | |
649 | TTCN3_Debugger::variable_t* add_variable(void* p_value, const char* p_name, | |
650 | const char* p_type, TTCN3_Debugger::print_function_t p_print_function, | |
651 | TTCN3_Debugger::set_function_t p_set_function); | |
7329404e BB |
652 | |
653 | /** stores the string representation of the value returned by the function */ | |
654 | void set_return_value(const CHARSTRING& p_value); | |
655 | ||
016a1a93 | 656 | /** saves the function's initial snapshot (including the values of 'in' and |
7329404e BB |
657 | * 'inout' parameters) in the main debugger object |
658 | * (only if the debugger is switched on) */ | |
659 | void initial_snapshot() const; | |
660 | ||
661 | ////////////////////////////////////////////////////// | |
662 | ////// methods called by other debugger classes ////// | |
663 | ////////////////////////////////////////////////////// | |
664 | ||
665 | /** adds the specified scope object pointer to the function's scope list */ | |
666 | void add_scope(TTCN3_Debug_Scope* p_scope); | |
667 | ||
668 | /** removes the specified scope object pointer from the function's scope list, | |
669 | * if it is the last scope in the list */ | |
670 | void remove_scope(TTCN3_Debug_Scope* p_scope); | |
671 | ||
672 | /** removes the specified variable from the variable list */ | |
673 | void remove_variable(const TTCN3_Debugger::variable_t* p_var); | |
674 | ||
675 | /** searches for the variable entry with the specified name in the function's | |
676 | * local variable list, the global scope (if any) and the component scope (if any), | |
677 | * returns NULL, if the variable was not found */ | |
f08ff9ca | 678 | TTCN3_Debugger::variable_t* find_variable(const char* p_name) const; |
7329404e BB |
679 | |
680 | /** prints the function's type, name and current values of parameters */ | |
681 | void print_function() const; | |
682 | ||
683 | /** returns the name of the module the function was defined in */ | |
684 | const char* get_module_name() const { return module_name; } | |
685 | ||
686 | /** prints the names of variables specified by the parameters (separated by spaces) | |
687 | * handles the D_LIST_VARIABLES debugger command | |
688 | * @param p_scope specifies which scope to print variables from: | |
689 | * - "local" - the function's local variables (including variables in code blocks) | |
690 | * - "global" - variables in the module's global scope | |
691 | * - "comp" or "component" - variables in the function's runs-on component scope | |
692 | * - "all" - all variables visible in the function (i.e. all of the above) | |
693 | * @param p_filter a pattern to filter variable names further */ | |
694 | void list_variables(const char* p_scope, const char* p_filter) const; | |
f08ff9ca BB |
695 | |
696 | /** returns true if this instance belongs to a control part */ | |
697 | bool is_control_part() const; | |
698 | ||
699 | /** returns true if this instance belongs to a test case */ | |
700 | bool is_test_case() const; | |
7329404e BB |
701 | }; |
702 | ||
703 | /** This macro stores a function's return value in the current function. | |
704 | * The returned value might be an expression, so it is copied to a temporary first, | |
705 | * to avoid being evaluated twice. */ | |
706 | #define DEBUGGER_STORE_RETURN_VALUE(tmp, ret_val) \ | |
707 | (tmp = (ret_val), \ | |
708 | ttcn3_debugger.set_return_value((TTCN_Logger::begin_event_log2str(), \ | |
709 | tmp.log(), \ | |
710 | TTCN_Logger::end_event_log2str())), \ | |
711 | tmp) | |
712 | ||
713 | #endif /* DEBUGGER_HH */ | |
714 |